Пример исходного кода микшера
#include <example.h>#include <proto.h>static uint8_t example_mixer_read( example_t *example, uint32_t reg ){uint8_t val = 0;/* Здесь должен быть код для чтения регистра микшера и установки значения переменной "val". */return val;}static void example_mixer_write( example_t *example, uint32_t reg, uint8_t val ){/* Здесь должен быть код для записи в регистр микшера значения переменной.*/}static snd_mixer_voice_t stereo_voices[2] = { {SND_MIXER_VOICE_LEFT, 0},{SND_MIXER_VOICE_RIGHT, 0} };static struct snd_mixer_element_volume1_range output_range[2] = { {0, 63, -600, 1650},{0, 63, -600, 1650} };static struct snd_mixer_element_volume1_range input_range[2] = { {0, 15, -2850, 300},{0, 15, -2850, 300} };static int32_t example_master_vol_control( MIXER_CONTEXT_T *example, ado_mixer_delement_t *element, uint8_t set,uint32_t *vol, void *instance_data ){enum example_mixer_reg reg = (int32_t)instance_data;uint32_t data[2];int32_t altered = 0;int max = ado_mixer_element_vol_range_max( element );data[0] = example_mixer_read( example, reg + 0 );data[1] = example_mixer_read( example, reg + 2 );if ( set ){altered = vol[0] != (data[0] & max) || vol[1] != (data[1] & max);data[0] = (data[0] & ~(max)) | vol[0];data[1] = (data[1] & ~(max)) | vol[0];example_mixer_write( example, reg + 0, data[0] );example_mixer_write( example, reg + 2, data[1] );} else {vol[0] = (data[0] & max);vol[1] = (data[1] & max);}return (altered);}static int32_t example_master_mute_control( MIXER_CONTEXT_T *example, ado_mixer_delement_t *element, uint8_t set,uint32_t *val, void *instance_data ){enum example_mixer_reg reg = (int32_t)instance_data;uint32_t data[2];int32_t altered = 0;data[0] = example_mixer_read( example, reg + 0 );data[1] = example_mixer_read( example, reg + 2 );if ( set ){altered = val[0] != ((data[0] & 0x40) ? (1 << 0) : 0) |((data[1] & 0x40) ? (1 << 1) : 0);data[0] = (data[0] & ~0x40) | ((val[0] & (1 << 0)) ? 0x40 : 0);data[1] = (data[1] & ~0x40) | ((val[0] & (1 << 1)) ? 0x40 : 0);example_mixer_write( example, reg + 0, data[0] );example_mixer_write( example, reg + 2, data[1] );} elseval[0] = ((data[0] & 0x40) ? (1 << 0) : 0) |((data[1] & 0x40) ? (1 << 1) : 0);return (altered);}static int32_t example_vol_control( MIXER_CONTEXT_T *example, ado_mixer_delement_t *element, uint8_t set,uint32_t *vol, void *instance_data ){enum example_mixer_reg reg = (int32_t)instance_data;uint32_t data;int32_t altered = 0;int max = ado_mixer_element_vol_range_max( element );data = example_mixer_read( example, reg );if ( set ){altered = vol[0] != ((data & (max << 8)) >> 8) || vol[1] != (data & max);data = (data & ~((max << 4) | max)) | ((vol[0]) << 4) | (vol[1]);example_mixer_write( example, reg, data );} else {vol[0] = ((data & (max << 4)) >> 4);vol[1] = ((data & max));}return (altered);}int build_in_group( MIXER_CONTEXT_T *example, char *name_p, char *name_c, example_group *grp,enum example_mixer_reg reg_p, enum example_mixer_reg reg_c ){int error = 0;ado_mixer_delement_t *pre_elem,*elem = NULL;char ename[sizeof( ((snd_mixer_eid_t *)0)->name )];if ( grp == &example->pcm ){if ( !error && (elem = ado_mixer_element_io( example->mixer, name_p, SND_MIXER_ETYPE_PLAYBACK1,0, 2, stereo_voices )) == NULL )error++;} else {if ( !error && (elem = ado_mixer_element_io( example->mixer, name_p, SND_MIXER_ETYPE_INPUT,0, 2, stereo_voices )) == NULL )error++;}pre_elem = elem;sprintf( ename, "%s %s", name_p, "Volume" );if ( !error && (elem = ado_mixer_element_volume1( example->mixer, ename, 2, input_range, example_vol_control,(void *)reg_p, NULL )) == NULL )error++;if ( !error && ado_mixer_element_route_add( example->mixer, pre_elem, elem ) != 0 )error++;grp->vol_out = elem;if ( !error && ado_mixer_element_route_add( example->mixer, elem, example->output_accu ) != 0 )error++;if ( name_c ){if ( !error && ado_mixer_element_route_add( example->mixer, pre_elem, example->input_accu ) != 0 )error++;}if ( !error && name_p && (grp->group_p = ado_mixer_playback_group_create( example->mixer, name_p, SND_MIXER_CHN_MASK_STEREO,grp->vol_out, NULL )) == NULL )error++;if ( !error && name_c && (grp->group_c = ado_mixer_capture_group_create( example->mixer, name_c, SND_MIXER_CHN_MASK_STEREO,NULL, NULL, NULL, NULL )) == NULL )error++;return (0);}int build_example_mixer( MIXER_CONTEXT_T *example, ado_mixer_t *mixer ){int error = 0;ado_mixer_delement_t *pre_elem,*elem = NULL;/* ################ *//* Выходная группа *//* ################ */if ( (example->output_accu = ado_mixer_element_accu1( mixer, SND_MIXER_ELEMENT_OUTPUT_ACCU, 0 )) == NULL )error++;pre_elem = example->output_accu;if ( !error && (elem = ado_mixer_element_volume1( mixer, "Output Volume", 2, output_range, example_master_vol_control,(void *)EXAMPLE_MASTER_LEFT, NULL )) == NULL )error++;if ( !error && ado_mixer_element_route_add( mixer, pre_elem, elem ) != 0 )error++;example->master_vol = elem;pre_elem = elem;if ( !error && (elem = ado_mixer_element_sw2( mixer, "Output Mute", example_master_mute_control,(void *)EXAMPLE_MASTER_LEFT, NULL )) == NULL )error++;if ( !error && ado_mixer_element_route_add( mixer, pre_elem, elem ) != 0 )error++;example->master_mute = elem;pre_elem = elem;if ( !error && (elem = ado_mixer_element_io( mixer, "Output", SND_MIXER_ETYPE_OUTPUT, 0, 2, stereo_voices )) == NULL )error++;if ( !error && ado_mixer_element_route_add( mixer, pre_elem, elem ) != 0 )error++;if ( !error && (example->master_grp = ado_mixer_playback_group_create( mixer, SND_MIXER_MASTER_OUT, SND_MIXER_CHN_MASK_STEREO,example->master_vol, example->master_mute )) == NULL )error++;/* ############### *//* Входная группа*//* ############### */if ( (example->input_accu = ado_mixer_element_accu1( mixer, SND_MIXER_ELEMENT_INPUT_ACCU, 0 )) == NULL )error++;pre_elem = example->input_accu;if ( !error && (elem = ado_mixer_element_volume1( mixer, "Input Volume", 2, input_range, example_vol_control,(void *)EXAMPLE_RECORD_LEVEL, NULL )) == NULL )error++;if ( !error && ado_mixer_element_route_add( mixer, pre_elem, elem ) != 0 )error++;example->master_vol = elem;pre_elem = elem;if ( !error && (elem = ado_mixer_element_io( mixer, SND_MIXER_ELEMENT_CAPTURE, SND_MIXER_ETYPE_CAPTURE1, 0, 2,stereo_voices )) == NULL )error++;if ( !error && ado_mixer_element_route_add( mixer, pre_elem, elem ) != 0 )error++;if ( !error && (example->input_grp = ado_mixer_capture_group_create( mixer, SND_MIXER_GRP_IGAIN, SND_MIXER_CHN_MASK_STEREO,example->master_vol, NULL, NULL, NULL )) == NULL )error++;/* ################ *//* Входные группы *//* ################ */if ( !error && build_in_group( example, SND_MIXER_PCM_OUT, NULL, &example->pcm, EXAMPLE_PCM_OUT_VOL, NULL ) != 0 )error++;if ( !error && build_in_group( example, SND_MIXER_MIC_OUT, SND_MIXER_MIC_IN, &example->mic, EXAMPLE_MIC_OUT_VOL,EXAMPLE_MIC_IN_VOL ) != 0 )error++;if ( !error && build_in_group( example, SND_MIXER_CD_OUT, SND_MIXER_CD_IN, &example->cd, EXAMPLE_CD_OUT_VOL,EXAMPLE_CD_IN_VOL ) != 0 )error++;return (0);}ado_mixer_reset_t example_reset;int example_reset( MIXER_CONTEXT_T *example ){/* Эта функция устанаваливает микшер в состояние по умолчанию */example_mixer_write( example, EXAMPLE_PCM_OUT_VOL, 0xff ); /* Установка громксти PCM на 0% */example_mixer_write( example, EXAMPLE_CD_OUT_VOL, 0xff ); /* Установка громкости cd на 0% */example_mixer_write( example, EXAMPLE_REC_SEL, 0x05 ); /* Установка источника записи в микшер */return (0);}ado_mixer_destroy_t example_destroy;int example_destroy( MIXER_CONTEXT_T *example ){/* Эта функция устанавливает микшер в безопасное состояние */example_mixer_write( example, EXAMPLE_PCM_OUT_VOL, 0x0 ); /* Установка громксти PCM на 0% */example_mixer_write( example, EXAMPLE_CD_OUT_VOL, 0x00 ); /* Установка громкости cd на 0% */return (0);}int example_mixer( ado_card_t *card, HW_CONTEXT_T *example ){int32_t status;if ( (status = ado_mixer_create( card, "Example", &example->mixer, example )) != EOK )return (status);example_mixer_write( example, 0x00, 0x00 ); /* Сброс микшера */if ( build_example_mixer( example, example->mixer ) )return (-1);if ( example_reset( example ) )return (-1);/* Следующие функции не являются обязательными, но они должны быть реализованы, если у вас есть действия, которые должны выполняться аппаратным обеспечением* всякий раз, когда микшер сбрасывается или уничтожается. Эти функции предназначены специально для конкретных требований к оборудованию. */ado_mixer_set_reset_func( example->mixer, example_reset );ado_mixer_set_destroy_func( example->mixer, example_destroy );return (0);}
Предыдущий раздел: Библиотека libado