From 9d5b8f205df85177dc3bf58c3f983846897f897f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Sat, 15 Jul 2000 10:21:59 +0000 Subject: [PATCH] Changes reflecting the new control API and kernel mixer API removal. --- alsactl/alsactl.c | 30 +- alsactl/alsactl.h | 54 +- alsactl/alsactl_lexer.l | 55 +- alsactl/alsactl_parser.y | 741 +++--------------------- alsactl/merge.c | 477 ++------------- alsactl/setup.c | 776 +++++-------------------- alsamixer/alsamixer.c | 298 +++++----- amixer/amixer.c | 1189 ++++++-------------------------------- 8 files changed, 627 insertions(+), 2993 deletions(-) diff --git a/alsactl/alsactl.c b/alsactl/alsactl.c index 44f6f86..cdd81f7 100644 --- a/alsactl/alsactl.c +++ b/alsactl/alsactl.c @@ -79,11 +79,7 @@ static int store_setup(const char *cardname) soundcard_setup_init(); for (idx = 0; idx < 32; idx++) { if (card_mask & (1 << idx)) { /* find each installed soundcards */ - if ((err = soundcard_setup_collect_switches(idx))) { - soundcard_setup_done(); - return err; - } - if ((err = soundcard_setup_collect_data(idx))) { + if ((err = soundcard_setup_collect_controls(idx))) { soundcard_setup_done(); return err; } @@ -99,11 +95,7 @@ static int store_setup(const char *cardname) error("Cannot find soundcard '%s'...", cardname); return 1; } - if ((err = soundcard_setup_collect_switches(cardno))) { - soundcard_setup_done(); - return err; - } - if ((err = soundcard_setup_collect_data(cardno))) { + if ((err = soundcard_setup_collect_controls(cardno))) { soundcard_setup_done(); return err; } @@ -126,27 +118,15 @@ static int restore_setup(const char *cardname) } if ((err = soundcard_setup_load(cfgfile, 0))) return err; - if ((err = soundcard_setup_collect_switches(cardno))) { + if ((err = soundcard_setup_collect_controls(cardno))) { soundcard_setup_done(); return err; } - if ((err = soundcard_setup_merge_switches(cardno))) { + if ((err = soundcard_setup_merge_controls(cardno))) { soundcard_setup_done(); return err; } - if ((err = soundcard_setup_process_switches(cardno))) { - soundcard_setup_done(); - return err; - } - if ((err = soundcard_setup_collect_data(cardno))) { - soundcard_setup_done(); - return err; - } - if ((err = soundcard_setup_merge_data(cardno))) { - soundcard_setup_done(); - return err; - } - if ((err = soundcard_setup_process_data(cardno))) { + if ((err = soundcard_setup_process_controls(cardno))) { soundcard_setup_done(); return err; } diff --git a/alsactl/alsactl.h b/alsactl/alsactl.h index 9b80f86..89df00a 100644 --- a/alsactl/alsactl.h +++ b/alsactl/alsactl.h @@ -37,53 +37,22 @@ extern int debugflag; extern void error(const char *fmt,...); -struct ctl_switch { +struct ctl_control { int change; - snd_switch_t s; - struct ctl_switch *next; + snd_control_type_t type; + snd_control_info_t info; + snd_control_t c; + struct ctl_control *next; }; struct ctl { snd_ctl_hw_info_t hwinfo; - struct ctl_switch *switches; -}; - -struct mixer_element { - snd_mixer_element_info_t info; - snd_mixer_element_t element; - struct mixer_element *next; -}; - -struct mixer { - int no; - snd_mixer_info_t info; - struct mixer_element *elements; - struct ctl_switch *switches; - struct mixer *next; -}; - -struct pcm { - int no; - snd_pcm_info_t info; - struct ctl_switch *pswitches; - struct ctl_switch *rswitches; - struct pcm *next; -}; - -struct rawmidi { - int no; - snd_rawmidi_info_t info; - struct ctl_switch *iswitches; - struct ctl_switch *oswitches; - struct rawmidi *next; + struct ctl_control *controls; }; struct soundcard { int no; /* card number */ struct ctl control; - struct mixer *mixers; - struct pcm *pcms; - struct rawmidi *rawmidis; struct soundcard *next; }; @@ -94,11 +63,8 @@ void soundcard_setup_init(void); void soundcard_setup_done(void); int soundcard_setup_load(const char *filename, int skip); int soundcard_setup_write(const char *filename, int cardno); -int soundcard_setup_collect_switches(int cardno); -int soundcard_setup_collect_data(int cardno); -int soundcard_setup_merge_switches(int cardno); -int soundcard_setup_merge_data(int cardno); -int soundcard_setup_process_switches(int cardno); -int soundcard_setup_process_data(int cardno); +int soundcard_setup_collect_controls(int cardno); +int soundcard_setup_merge_controls(int cardno); +int soundcard_setup_process_controls(int cardno); -char *mixer_element_id(snd_mixer_eid_t *eid); +char *control_id(snd_control_id_t *id); diff --git a/alsactl/alsactl_lexer.l b/alsactl/alsactl_lexer.l index 69c396d..77be63c 100644 --- a/alsactl/alsactl_lexer.l +++ b/alsactl/alsactl_lexer.l @@ -53,53 +53,14 @@ int linecount; soundcard return L_SOUNDCARD; control return L_CONTROL; + +global return L_GLOBAL; +hwdep return L_HWDEP; mixer return L_MIXER; -element return L_ELEMENT; -switch return L_SWITCH; -rawdata return L_RAWDATA; pcm return L_PCM; rawmidi return L_RAWMIDI; -playback return L_PLAYBACK; -capture return L_CAPTURE; -output return L_OUTPUT; -input return L_INPUT; -iec958ocs return L_IEC958OCS; -3d return L_3D; -reset return L_RESET; -user return L_USER; -valid return L_VALID; -data return L_DATA; -protect return L_PROTECT; -pre2 return L_PRE2; -fsunlock return L_FSUNLOCK; -type return L_TYPE; -gstatus return L_GSTATUS; -enable return L_ENABLE; -disable return L_DISABLE; -sw return L_SW; -mono_sw return L_MONO_SW; -wide return L_WIDE; -volume return L_VOLUME; -center return L_CENTER; -space return L_SPACE; -depth return L_DEPTH; -delay return L_DELAY; -feedback return L_FEEDBACK; -depth_rear return L_DEPTH_REAR; -bass return L_BASS; -treble return L_TREBLE; - - /* element types */ - -Switch1 return L_SWITCH1; -Switch2 return L_SWITCH2; -Switch3 return L_SWITCH3; -Volume1 return L_VOLUME1; -Accu3 return L_ACCU3; -Mux1 return L_MUX1; -Mux2 return L_MUX2; -ToneControl1 return L_TONE_CONTROL1; -_3D_Effect1 return L_3D_EFFECT1; +timer return L_TIMER; +sequencer return L_SEQUENCER; /* boolean */ @@ -108,10 +69,8 @@ true|on|yes return L_TRUE; /* integers */ -[0-9]+ { yylval.i_value = atoi(yytext); return L_INTEGER; } -0x[0-9a-f]+ { char *end; - yylval.i_value = strtol(yytext, &end, 0); - return L_INTEGER; } +[0-9]+ { yylval.i_value = strtol(yytext, (char **)NULL, 10); return L_INTEGER; } +0x[0-9a-f]+ { yylval.i_value = strtol(yytext, (char **)NULL, 0); return L_INTEGER; } /* byte array */ diff --git a/alsactl/alsactl_parser.y b/alsactl/alsactl_parser.y index 7e9e419..586127a 100644 --- a/alsactl/alsactl_parser.y +++ b/alsactl/alsactl_parser.y @@ -44,54 +44,18 @@ struct bytearray { static void yyerror(char *, ...); static void build_soundcard(char *name); -static void build_mixer(char *name); -static void build_pcm(char *name); -static void build_rawmidi(char *name); - -static void build_mixer_element(char *name, int index, int etype); - -static void build_control_switch(char *name); -static void build_mixer_switch(char *name); -static void build_pcm_playback_switch(char *name); -static void build_pcm_capture_switch(char *name); -static void build_rawmidi_output_switch(char *name); -static void build_rawmidi_input_switch(char *name); - -static void mixer_switch1(int end); -static void mixer_switch1_value(int val); -static void mixer_switch2(int end); -static void mixer_switch2_value(int val); -static void mixer_switch3(int end); -static void mixer_switch3_value(int val); -static void mixer_volume1(int end); -static void mixer_volume1_value(int val); -static void mixer_3d_effect1(int end); -static void mixer_3d_effect1_value(unsigned int effect, int val); -static void mixer_accu3(int end); -static void mixer_accu3_value(int val); -static void mixer_mux1(int end); -static void mixer_mux1_value(char *str, int index, int type); -static void mixer_mux2(int end); -static void mixer_mux2_value(char *str, int index, int type); -static void mixer_tone_control1(int end); -static void mixer_tone_control1_value(unsigned int effect, int val); - -static void set_switch_boolean(int val); -static void set_switch_integer(int val); -static void set_switch_bytearray(struct bytearray val); -static void set_switch_iec958ocs_begin(int end); -static void set_switch_iec958ocs(int idx, unsigned short val, unsigned short mask); +static void build_control_begin(int iface, unsigned int device, unsigned int subdevice, char *name, unsigned int index); +static void build_control_end(void); +static void set_control_boolean(int val); +static void set_control_integer(long val); +static void set_control_bytearray(struct bytearray val); /* local variables */ static struct soundcard *Xsoundcard = NULL; -static struct mixer *Xmixer = NULL; -static struct pcm *Xpcm = NULL; -static struct rawmidi *Xrawmidi = NULL; -static struct mixer_element *Xelement = NULL; -static struct ctl_switch *Xswitch = NULL; -static unsigned int Xswitchiec958ocs = 0; -static unsigned short Xswitchiec958ocs1[16]; +static struct ctl_control *Xcontrol = NULL; +static int Xposition = 0; +static snd_control_type_t Xtype = SND_CONTROL_TYPE_NONE; %} @@ -99,7 +63,7 @@ static unsigned short Xswitchiec958ocs1[16]; %union { int b_value; - int i_value; + long i_value; char *s_value; struct bytearray a_value; }; @@ -116,19 +80,12 @@ static unsigned short Xswitchiec958ocs1[16]; /* misc */ %token L_DOUBLE1 /* other keywords */ -%token L_SOUNDCARD L_MIXER L_ELEMENT L_SWITCH L_RAWDATA -%token L_CONTROL L_PCM L_RAWMIDI L_PLAYBACK L_CAPTURE L_INPUT L_OUTPUT -%token L_SWITCH1 L_SWITCH2 L_SWITCH3 L_VOLUME1 L_3D_EFFECT1 L_ACCU3 -%token L_MUX1 L_MUX2 L_TONE_CONTROL1 -%token L_IEC958OCS L_3D L_RESET L_USER L_VALID L_DATA L_PROTECT L_PRE2 -%token L_FSUNLOCK L_TYPE L_GSTATUS L_ENABLE L_DISABLE -%token L_SW L_MONO_SW L_WIDE L_VOLUME L_CENTER L_SPACE L_DEPTH L_DELAY -%token L_DEPTH_REAR -%token L_FEEDBACK L_BASS L_TREBLE +%token L_SOUNDCARD L_CONTROL L_RAWDATA +%token L_GLOBAL L_HWDEP L_MIXER L_PCM L_RAWMIDI L_TIMER L_SEQUENCER %type boolean -%type integer +%type integer iface %type string %type rawdata @@ -147,224 +104,31 @@ soundcards : | soundcards soundcard ; -soundcard : L_CONTROL '{' controls '}' - | L_MIXER '(' string { build_mixer($3); } - L_DOUBLE1 mixers '}' { build_mixer(NULL); } - | L_PCM '(' string { build_pcm($3); } - L_DOUBLE1 pcms '}' { build_pcm(NULL); } - | L_RAWMIDI '(' string { build_rawmidi($3); } - L_DOUBLE1 rawmidis '}' { build_rawmidi(NULL); } +soundcard : L_CONTROL '(' iface ',' integer ',' integer ',' string ',' integer + { build_control_begin($3, $5, $7, $9, $11); } + ',' controls ')' { build_control_end(); } | error { yyerror( "an unknown keyword in the soundcard{} level"); } ; controls : control - | controls control + | controls ',' control ; -control : L_SWITCH '(' string { build_control_switch($3); } - ',' switches ')' { build_control_switch(NULL); } - | error { yyerror("an unknown keyword in the control{} level"); } +control : boolean { set_control_boolean($1); } + | integer { set_control_integer($1); } + | rawdata { set_control_bytearray($1); } + | error { yyerror( "an unknown keyword in the control() data parameter" ); } ; - -mixers : /* empty */ - | mixers mixer - ; - -mixer : L_ELEMENT '(' string - ',' integer ',' integer { build_mixer_element($3, $5, $7); } - ',' etype ')' { build_mixer_element(NULL, -1, -1); } - | L_SWITCH '(' string { build_mixer_switch($3); } - ',' switches ')' { build_mixer_switch(NULL); } - | error { yyerror("an unknown keyword in the mixer level"); } - ; - - -etype : L_SWITCH1 '(' { mixer_switch1(0); } - m_switch1 ')' { mixer_switch1(1); } - | L_SWITCH2 '(' { mixer_switch2(0); } - m_switch2 ')' { mixer_switch2(1); } - | L_SWITCH3 '(' { mixer_switch3(0); } - m_switch3 ')' { mixer_switch3(1); } - | L_VOLUME1 '(' { mixer_volume1(0); } - m_volume1 ')' { mixer_volume1(1); } - | L_3D_EFFECT1 '(' { mixer_3d_effect1(0); } - m_3d_effect1 ')' { mixer_3d_effect1(1); } - | L_ACCU3 '(' { mixer_accu3(0); } - m_accu3 ')' { mixer_accu3(1); } - | L_MUX1 '(' { mixer_mux1(0); } - m_mux1 ')' { mixer_mux1(1); } - | L_MUX2 '(' { mixer_mux2(0); } - L_ELEMENT '(' - string ',' - integer ',' - integer ')' { mixer_mux2_value($6, $8, $10); } - ')' { mixer_mux2(1); } - | L_TONE_CONTROL1 '(' { mixer_tone_control1(0); } - m_tone_control1 ')' { mixer_tone_control1(1); } - | error { yyerror("an unknown keyword in the mixer element level"); } - ; - -m_switch1 : m_switch1_0 - | m_switch1 ',' m_switch1_0 - ; - -m_switch1_0 : boolean { mixer_switch1_value($1); } - | error { yyerror("an unknown keyword in the Switch1 element level"); } - ; - -m_switch2 : m_switch2_0 - | m_switch2 ',' m_switch2_0 - ; - -m_switch2_0 : boolean { mixer_switch2_value($1); } - | error { yyerror("an unknown keyword in the Switch2 element level"); } - ; - -m_switch3 : m_switch3_0 - | m_switch3 ',' m_switch3_0 - ; - -m_switch3_0 : boolean { mixer_switch3_value($1); } - | error { yyerror("an unknown keyword in the Switch3 element level"); } - ; - -m_volume1 : m_volume1_0 - | m_volume1 ',' m_volume1_0 - ; - -m_volume1_0 : integer { mixer_volume1_value($1); } - | error { yyerror("an unknown keyword in the Volume1 element level"); } - ; - -m_3d_effect1 : m_3d_effect1_0 - | m_3d_effect1 ',' m_3d_effect1_0 - ; - -m_3d_effect1_0 : L_SW '=' boolean { mixer_3d_effect1_value(SND_MIXER_EFF1_SW, $3); } - | L_MONO_SW '=' boolean { mixer_3d_effect1_value(SND_MIXER_EFF1_MONO_SW, $3); } - | L_WIDE '=' integer { mixer_3d_effect1_value(SND_MIXER_EFF1_WIDE, $3); } - | L_VOLUME '=' integer { mixer_3d_effect1_value(SND_MIXER_EFF1_VOLUME, $3); } - | L_CENTER '=' integer { mixer_3d_effect1_value(SND_MIXER_EFF1_CENTER, $3); } - | L_SPACE '=' integer { mixer_3d_effect1_value(SND_MIXER_EFF1_SPACE, $3); } - | L_DEPTH '=' integer { mixer_3d_effect1_value(SND_MIXER_EFF1_DEPTH, $3); } - | L_DELAY '=' integer { mixer_3d_effect1_value(SND_MIXER_EFF1_DELAY, $3); } - | L_FEEDBACK '=' integer { mixer_3d_effect1_value(SND_MIXER_EFF1_FEEDBACK, $3); } - | L_DEPTH_REAR '=' integer { mixer_3d_effect1_value(SND_MIXER_EFF1_DEPTH_REAR, $3); } - | error { yyerror("an unknown keyword in the 3D Effect1 element level"); } - ; - -m_accu3 : m_accu3_0 - | m_accu3 ',' m_accu3_0 - ; - -m_accu3_0 : integer { mixer_accu3_value($1); } - | error { yyerror("an unknown keyword in the Accu3 element level"); } - ; - -m_mux1 : m_mux1_0 - | m_mux1 ',' m_mux1_0 - ; - -m_mux1_0 : L_ELEMENT '(' string - ',' integer ',' - integer ')' { mixer_mux1_value($3, $5, $7); } - | error { yyerror("an unknown keyword in the Mux1 element level"); } - ; - -m_tone_control1 : m_tone_control1_0 - | m_tone_control1 ',' m_tone_control1_0 - ; - -m_tone_control1_0 : L_SW '=' boolean { mixer_tone_control1_value(SND_MIXER_TC1_SW, $3); } - | L_BASS '=' integer { mixer_tone_control1_value(SND_MIXER_TC1_BASS, $3); } - | L_TREBLE '=' integer { mixer_tone_control1_value(SND_MIXER_TC1_TREBLE, $3); } - | error { yyerror("an unknown keyword in the ToneControl1 element level"); } - ; - - -pcms : pcm - | pcms pcm - ; - -pcm : L_PLAYBACK '{' playbacks '}' - | L_CAPTURE '{' captures '}' - | error { yyerror("an unknown keyword in the pcm{} section"); } - ; - -playbacks : playback - | playbacks playback - ; - -playback : L_SWITCH '(' string { build_pcm_playback_switch($3); } - ',' switches ')' { build_pcm_playback_switch(NULL); } - | error { yyerror("an unknown keyword in the playback{} section"); } - ; - -captures : capture - | captures capture - ; - -capture : L_SWITCH '(' string { build_pcm_capture_switch($3); } - ',' switches ')' { build_pcm_capture_switch(NULL); } - | error { yyerror("an unknown keyword in the capture{} section"); } - ; - -rawmidis : rawmidi - | rawmidis rawmidi - ; - -rawmidi : L_INPUT '{' inputs '}' - | L_OUTPUT '{' outputs '}' - ; - -inputs : input - | inputs input - ; - -input : L_SWITCH '(' string { build_rawmidi_input_switch($3); } - ',' switches ')' { build_rawmidi_input_switch(NULL); } - | error { yyerror( "an unknown keyword in the input{} section" ); } - ; - -outputs : output - | outputs output - ; - -output : L_SWITCH '(' string { build_rawmidi_output_switch($3); } - ',' switches ')' { build_rawmidi_output_switch(NULL); } - | error { yyerror( "an unknown keyword in the output{} section" ); } - ; - -switches : switch - | switches switch - ; - -switch : boolean { set_switch_boolean($1); } - | integer { set_switch_integer($1); } - | L_IEC958OCS '(' { set_switch_iec958ocs_begin(0); } - iec958ocs ')' { set_switch_iec958ocs_begin(1); } - | rawdata { set_switch_bytearray($1); } - | error { yyerror( "an unknown keyword in the switch() data parameter" ); } - ; - -iec958ocs : iec958ocs1 - | iec958ocs ',' iec958ocs1 - ; - -iec958ocs1 : L_ENABLE { set_switch_iec958ocs( 0, 1, 0 ); } - | L_DISABLE { set_switch_iec958ocs( 0, 0, 0 ); } - | L_3D { set_switch_iec958ocs( 4, 0x2000, ~0x2000 ); } - | L_RESET { set_switch_iec958ocs( 4, 0x0040, ~0x0040 ); } - | L_USER { set_switch_iec958ocs( 4, 0x0020, ~0x0020 ); } - | L_VALID { set_switch_iec958ocs( 4, 0x0010, ~0x0010 ); } - | L_DATA { set_switch_iec958ocs( 5, 0x0002, ~0x0002 ); } - | L_PROTECT { set_switch_iec958ocs( 5, 0, ~0x0004 ); } - | L_PRE2 { set_switch_iec958ocs( 5, 0x0008, ~0x0018 ); } - | L_FSUNLOCK { set_switch_iec958ocs( 5, 0x0020, ~0x0020 ); } - | L_TYPE '(' integer ')' { set_switch_iec958ocs( 5, ($3 & 0x7f) << 6, ~(0x7f<<6) ); } - | L_GSTATUS { set_switch_iec958ocs( 5, 0x2000, ~0x2000 ); } - | error { yyerror( "an unknown keyword in the iec958ocs1() arguments" ); } +iface : L_INTEGER { $$ = $1; } + | L_GLOBAL { $$ = SND_CONTROL_IFACE_CARD; } + | L_HWDEP { $$ = SND_CONTROL_IFACE_HWDEP; } + | L_MIXER { $$ = SND_CONTROL_IFACE_MIXER; } + | L_PCM { $$ = SND_CONTROL_IFACE_PCM; } + | L_RAWMIDI { $$ = SND_CONTROL_IFACE_RAWMIDI; } + | L_TIMER { $$ = SND_CONTROL_IFACE_TIMER; } + | L_SEQUENCER { $$ = SND_CONTROL_IFACE_SEQUENCER; } + | error { yyerror( "an unknown keyword in the interface field"); } ; boolean : L_TRUE { $$ = 1; } @@ -426,425 +190,86 @@ static void build_soundcard(char *name) free(name); } -static void build_mixer(char *name) +static void build_control_begin(int iface, unsigned int device, unsigned int subdevice, char *name, unsigned int index) { - struct mixer *mixer; + struct ctl_control **first; + struct ctl_control *ctl; - if (!name) { - Xmixer = NULL; - return; - } - Xmixer = (struct mixer *)malloc(sizeof(struct pcm)); - if (!Xmixer) { + first = &Xsoundcard->control.controls; + Xcontrol = (struct ctl_control *)malloc(sizeof(struct ctl_control)); + if (!Xcontrol) { free(name); error_nomem(); return; } - bzero(Xmixer, sizeof(*Xmixer)); - for (mixer = Xsoundcard->mixers; mixer && mixer->next; mixer = mixer->next); - if (mixer) { - mixer->next = Xmixer; + Xposition = 0; + Xtype = SND_CONTROL_TYPE_NONE; + bzero(Xcontrol, sizeof(*Xcontrol)); + for (ctl = *first; ctl && ctl->next; ctl = ctl->next); + if (ctl) { + ctl->next = Xcontrol; } else { - Xsoundcard->mixers = Xmixer; + *first = Xcontrol; } - strncpy(Xmixer->info.name, name, sizeof(Xmixer->info.name)); + Xcontrol->c.id.iface = iface; + Xcontrol->c.id.device = device; + Xcontrol->c.id.subdevice = subdevice; + strncpy(Xcontrol->c.id.name, name, sizeof(Xcontrol->c.id.name)); + Xcontrol->c.id.index = index; free(name); } -static void build_pcm(char *name) +static void build_control_end(void) { - struct pcm *pcm; - - if (!name) { - Xpcm = NULL; - return; - } - Xpcm = (struct pcm *)malloc(sizeof(struct pcm)); - if (!Xpcm) { - free(name); - error_nomem(); - return; - } - bzero(Xpcm, sizeof(*Xpcm)); - for (pcm = Xsoundcard->pcms; pcm && pcm->next; pcm = pcm->next); - if (pcm) { - pcm->next = Xpcm; - } else { - Xsoundcard->pcms = Xpcm; - } - strncpy(Xpcm->info.name, name, sizeof(Xpcm->info.name)); - free(name); + Xcontrol = NULL; } -static void build_rawmidi(char *name) +static void set_control_boolean(int val) { - struct rawmidi *rawmidi; - - if (!name) { - Xrawmidi = NULL; - return; - } - Xrawmidi = (struct rawmidi *)malloc(sizeof(struct rawmidi)); - if (!Xrawmidi) { - free(name); - error_nomem(); - return; - } - bzero(Xrawmidi, sizeof(*Xrawmidi)); - for (rawmidi = Xsoundcard->rawmidis; rawmidi && rawmidi->next; rawmidi = rawmidi->next); - if (rawmidi) { - rawmidi->next = Xrawmidi; - } else { - Xsoundcard->rawmidis = Xrawmidi; - } - strncpy(Xrawmidi->info.name, name, sizeof(Xrawmidi->info.name)); - free(name); -} - -static void build_mixer_element(char *name, int index, int etype) -{ - struct mixer_element *element; - - if (!name) { - Xelement = NULL; - return; - } - Xelement = (struct mixer_element *)malloc(sizeof(struct mixer_element)); - if (!Xelement) { - free(name); - error_nomem(); - return; - } - bzero(Xelement, sizeof(*Xelement)); - for (element = Xmixer->elements; element && element->next; element = element->next); - if (element) { - element->next = Xelement; - } else { - Xmixer->elements = Xelement; - } - strncpy(Xelement->element.eid.name, name, sizeof(Xelement->element.eid.name)); - Xelement->element.eid.index = index; - Xelement->element.eid.type = etype; - Xelement->info.eid = Xelement->element.eid; - free(name); -} - -static void mixer_type_check(int type) -{ - if (Xelement->element.eid.type != type) - yyerror("The element has got the unexpected data type."); -} - -static void mixer_switch1(int end) -{ - mixer_type_check(SND_MIXER_ETYPE_SWITCH1); -} - -static void mixer_switch1_value(int val) -{ - unsigned int *ptr; - - if (Xelement->element.data.switch1.sw_size <= Xelement->element.data.switch1.sw) { - Xelement->element.data.switch1.sw_size += 32; - ptr = (unsigned int *)realloc(Xelement->element.data.switch1.psw, ((Xelement->element.data.switch1.sw_size + 31) / 32) * sizeof(unsigned int)); - if (ptr == NULL) { - error_nomem(); - return; - } - Xelement->element.data.switch1.psw = ptr; - } - snd_mixer_set_bit(Xelement->element.data.switch1.psw, Xelement->element.data.switch1.sw++, val ? 1 : 0); -} - -static void mixer_switch2(int end) -{ - mixer_type_check(SND_MIXER_ETYPE_SWITCH2); -} - -static void mixer_switch2_value(int val) -{ - Xelement->element.data.switch2.sw = val ? 1 : 0; -} - -static void mixer_switch3(int end) -{ - mixer_type_check(SND_MIXER_ETYPE_SWITCH3); -} - -static void mixer_switch3_value(int val) -{ - unsigned int *ptr; - - if (Xelement->element.data.switch3.rsw_size <= Xelement->element.data.switch3.rsw) { - Xelement->element.data.switch3.rsw_size += 32; - ptr = (unsigned int *)realloc(Xelement->element.data.switch1.psw, ((Xelement->element.data.switch3.rsw_size + 31) / 32) * sizeof(unsigned int)); - if (ptr == NULL) { - error_nomem(); - return; - } - Xelement->element.data.switch3.prsw = ptr; - } - snd_mixer_set_bit(Xelement->element.data.switch3.prsw, Xelement->element.data.switch3.rsw++, val ? 1 : 0); -} - -static void mixer_volume1(int end) -{ - mixer_type_check(SND_MIXER_ETYPE_VOLUME1); -} - -static void mixer_volume1_value(int val) -{ - int *ptr; - - if (Xelement->element.data.volume1.channels_size <= Xelement->element.data.volume1.channels) { - Xelement->element.data.volume1.channels_size += 4; - ptr = (int *)realloc(Xelement->element.data.volume1.pchannels, Xelement->element.data.volume1.channels_size * sizeof(int)); - if (ptr == NULL) { - error_nomem(); - return; - } - Xelement->element.data.volume1.pchannels = ptr; - } - Xelement->element.data.volume1.pchannels[Xelement->element.data.volume1.channels++] = val; -} - -static void mixer_3d_effect1(int end) -{ - mixer_type_check(SND_MIXER_ETYPE_3D_EFFECT1); -} - -static void mixer_3d_effect1_value(unsigned int effect, int val) -{ - switch (effect) { - case SND_MIXER_EFF1_SW: - Xelement->element.data.teffect1.sw = val ? 1 : 0; + switch (Xtype) { + case SND_CONTROL_TYPE_NONE: + case SND_CONTROL_TYPE_BOOLEAN: + Xtype = Xcontrol->type = SND_CONTROL_TYPE_BOOLEAN; break; - case SND_MIXER_EFF1_MONO_SW: - Xelement->element.data.teffect1.mono_sw = val ? 1 : 0; - break; - case SND_MIXER_EFF1_WIDE: - Xelement->element.data.teffect1.wide = val; - break; - case SND_MIXER_EFF1_VOLUME: - Xelement->element.data.teffect1.volume = val; - break; - case SND_MIXER_EFF1_CENTER: - Xelement->element.data.teffect1.center = val; - break; - case SND_MIXER_EFF1_SPACE: - Xelement->element.data.teffect1.space = val; - break; - case SND_MIXER_EFF1_DEPTH: - Xelement->element.data.teffect1.depth = val; - break; - case SND_MIXER_EFF1_DELAY: - Xelement->element.data.teffect1.delay = val; - break; - case SND_MIXER_EFF1_FEEDBACK: - Xelement->element.data.teffect1.feedback = val; - break; - case SND_MIXER_EFF1_DEPTH_REAR: - Xelement->element.data.teffect1.depth_rear = val; + case SND_CONTROL_TYPE_INTEGER: break; default: - yyerror("Unknown effect 0x%x\n", effect); + yyerror("Unexpected previous type (%i).\n", Xtype); } -} - -static void mixer_accu3(int end) -{ - mixer_type_check(SND_MIXER_ETYPE_ACCU3); + if (Xposition < 512) + Xcontrol->c.value.integer.value[Xposition++] = val ? 1 : 0; + else + yyerror("Array overflow."); } -static void mixer_accu3_value(int val) -{ - int *ptr; - - if (Xelement->element.data.accu3.channels_size <= Xelement->element.data.accu3.channels) { - Xelement->element.data.accu3.channels_size += 4; - ptr = (int *)realloc(Xelement->element.data.accu3.pchannels, Xelement->element.data.accu3.channels_size * sizeof(int)); - if (ptr == NULL) { - error_nomem(); - return; - } - Xelement->element.data.accu3.pchannels = ptr; - } - Xelement->element.data.accu3.pchannels[Xelement->element.data.accu3.channels++] = val; -} - -static void mixer_mux1(int end) -{ - mixer_type_check(SND_MIXER_ETYPE_MUX1); -} - -static void mixer_mux1_value(char *name, int index, int type) -{ - snd_mixer_eid_t *ptr; - snd_mixer_eid_t *eid; - - if (Xelement->element.data.mux1.sel_size <= Xelement->element.data.mux1.sel) { - Xelement->element.data.mux1.sel_size += 4; - ptr = (snd_mixer_eid_t *)realloc(Xelement->element.data.mux1.psel, Xelement->element.data.mux1.sel_size * sizeof(snd_mixer_eid_t)); - if (ptr == NULL) { - error_nomem(); - free(name); - return; - } - Xelement->element.data.mux1.psel = ptr; - } - eid = &Xelement->element.data.mux1.psel[Xelement->element.data.mux1.sel++]; - strncpy(eid->name, name, sizeof(eid->name)); - eid->index = index; - eid->type = type; - free(name); -} - -static void mixer_mux2(int end) -{ - mixer_type_check(SND_MIXER_ETYPE_MUX2); -} - -static void mixer_mux2_value(char *name, int index, int type) -{ - snd_mixer_eid_t *eid; - - eid = &Xelement->element.data.mux2.sel; - strncpy(eid->name, name, sizeof(eid->name)); - eid->index = index; - eid->type = type; - free(name); -} - -static void mixer_tone_control1(int end) -{ - mixer_type_check(SND_MIXER_ETYPE_TONE_CONTROL1); -} - -static void mixer_tone_control1_value(unsigned int effect, int val) -{ - Xelement->element.data.tc1.tc |= effect; - switch (effect) { - case SND_MIXER_TC1_SW: - Xelement->element.data.tc1.sw = val ? 1 : 0; - break; - case SND_MIXER_TC1_BASS: - Xelement->element.data.tc1.bass = val; - break; - case SND_MIXER_TC1_TREBLE: - Xelement->element.data.tc1.treble = val; - break; - default: - yyerror("Unknown effect 0x%x\n", effect); - } -} - -static void build_switch(struct ctl_switch **first, char *name) -{ - struct ctl_switch *sw; - - if (!name) { - Xswitch = NULL; - return; - } - Xswitch = (struct ctl_switch *)malloc(sizeof(struct ctl_switch)); - if (!Xswitch) { - free(name); - error_nomem(); - return; - } - bzero(Xswitch, sizeof(*Xswitch)); - for (sw = *first; sw && sw->next; sw = sw->next); - if (sw) { - sw->next = Xswitch; - } else { - *first = Xswitch; - } - strncpy(Xswitch->s.name, name, sizeof(Xswitch->s.name)); - free(name); -} - -static void build_control_switch(char *name) -{ - build_switch(&Xsoundcard->control.switches, name); -} - -static void build_mixer_switch(char *name) -{ - build_switch(&Xmixer->switches, name); -} - -static void build_pcm_playback_switch(char *name) -{ - build_switch(&Xpcm->pswitches, name); -} - -static void build_pcm_capture_switch(char *name) -{ - build_switch(&Xpcm->rswitches, name); -} - -static void build_rawmidi_output_switch(char *name) -{ - build_switch(&Xrawmidi->oswitches, name); -} - -static void build_rawmidi_input_switch(char *name) -{ - build_switch(&Xrawmidi->iswitches, name); -} - -static void set_switch_boolean(int val) -{ - Xswitch->s.type = SND_SW_TYPE_BOOLEAN; - Xswitch->s.value.enable = val ? 1 : 0; -} - -static void set_switch_integer(int val) +static void set_control_integer(long val) { unsigned int xx; - Xswitch->s.type = SND_SW_TYPE_DWORD; - xx = val; - memcpy(&Xswitch->s.value, &xx, sizeof(xx)); -} - -static void set_switch_bytearray(struct bytearray val) -{ - Xswitch->s.type = SND_SW_TYPE_USER; - - if (val.datalen > 32) - yyerror("Byte array too large for switch."); - - memcpy(Xswitch->s.value.data8, val.data, val.datalen); -} - -static void set_switch_iec958ocs_begin(int end) -{ - if (end) { - Xswitch->s.value.enable = Xswitchiec958ocs; - Xswitch->s.value.data16[4] = Xswitchiec958ocs1[4]; - Xswitch->s.value.data16[5] = Xswitchiec958ocs1[5]; -#if 0 - printf("IEC958: enable = %i, ocs1[4] = 0x%x, ocs1[5] = 0x%x\n", - sw->value.enable, - sw->value.data16[4], - sw->value.data16[5]); -#endif - return; + switch (Xtype) { + case SND_CONTROL_TYPE_NONE: + case SND_CONTROL_TYPE_BOOLEAN: + case SND_CONTROL_TYPE_INTEGER: + Xtype = Xcontrol->type = SND_CONTROL_TYPE_INTEGER; + break; + default: + yyerror("Unexpected previous type (%i).\n", Xtype); + } + if (Xposition < 512) { + xx = val; + Xcontrol->c.value.integer.value[Xposition++] = val; } - Xswitch->s.type = SND_SW_TYPE_BOOLEAN; - Xswitch->s.value.data32[1] = ('C' << 8) | 'S'; - Xswitchiec958ocs = 0; - Xswitchiec958ocs1[4] = 0x0000; - Xswitchiec958ocs1[5] = 0x0004; /* copy permitted */ } -static void set_switch_iec958ocs(int idx, unsigned short val, unsigned short mask) +static void set_control_bytearray(struct bytearray val) { - if (idx == 0) { - Xswitchiec958ocs = val ? 1 : 0; - return; - } - Xswitchiec958ocs1[idx] &= mask; - Xswitchiec958ocs1[idx] |= val; + if (Xtype != SND_CONTROL_TYPE_NONE && Xtype != SND_CONTROL_TYPE_BYTES) + yyerror("Unexpected previous type (%i).\n", Xtype); + Xtype = Xcontrol->type = SND_CONTROL_TYPE_BYTES; + + if (val.datalen + Xposition > 512) + yyerror("Byte array too large for control."); + + memcpy(&Xcontrol->c.value.bytes.data[Xposition], val.data, val.datalen); + Xposition += val.datalen; } diff --git a/alsactl/merge.c b/alsactl/merge.c index 11e829a..f276b1a 100644 --- a/alsactl/merge.c +++ b/alsactl/merge.c @@ -21,141 +21,98 @@ #include "alsactl.h" -static char *sw_id(const char *name, int cardno, int devno, const char *id) +static int merge_one_control(struct ctl_control *cctl, struct ctl_control *uctl, int cardno) { - static char str[256]; - - sprintf(str, "%s %s card %i", name, id, cardno); - if (devno >= 0) - sprintf(str + strlen(str)," device %i", devno); - return str; -} + int idx; -static int merge_one_sw(struct ctl_switch *csw, struct ctl_switch *usw, int cardno, int devno, const char *id) -{ - switch (csw->s.type) { - case SND_SW_TYPE_BOOLEAN: - if (usw->s.type != SND_SW_TYPE_BOOLEAN) { - error("A wrong type for the switch %s. The type boolean is expected. Skipping...", sw_id(usw->s.name, cardno, devno, id)); + if (!(cctl->info.access & SND_CONTROL_ACCESS_WRITE)) + return 0; + switch (cctl->info.type) { + case SND_CONTROL_TYPE_BOOLEAN: + if (uctl->type != SND_CONTROL_TYPE_BOOLEAN && uctl->type != SND_CONTROL_TYPE_INTEGER) { + error("A wrong type %i for the control '%s'. The type integer is expected. Skipping...", uctl->type, control_id(&uctl->c.id)); return 1; } - if (csw->s.value.enable != usw->s.value.enable) { - csw->change = 1; - csw->s.value.enable = usw->s.value.enable; - } - if (!strncmp(csw->s.name, SND_MIXER_SW_IEC958_OUTPUT, sizeof(csw->s.name))) { - if (usw->s.value.data32[1] == (('C' << 8) | 'S')) { - if (csw->s.value.data16[4] != usw->s.value.data16[4] || - csw->s.value.data16[5] != usw->s.value.data16[5]) { - csw->change = 1; - csw->s.value.data16[4] = usw->s.value.data16[4]; - csw->s.value.data16[5] = usw->s.value.data16[5]; - } + for (idx = 0; idx < cctl->info.values_count; idx++) { + if (cctl->c.value.integer.value[idx] != uctl->c.value.integer.value[idx]) { + cctl->change = 1; + cctl->c.value.integer.value[idx] = uctl->c.value.integer.value[idx]; } } break; - case SND_SW_TYPE_BYTE: - if (usw->s.type != SND_SW_TYPE_DWORD) { - error("A wrong type for the switch %s. The type byte is expected. Skipping...", sw_id(usw->s.name, cardno, devno, id)); + case SND_CONTROL_TYPE_INTEGER: + if (uctl->type != SND_CONTROL_TYPE_BOOLEAN && uctl->type != SND_CONTROL_TYPE_INTEGER) { + error("A wrong type %i for the control '%s'. The type integer is expected. Skipping...", uctl->type, control_id(&uctl->c.id)); return 1; } - if (csw->s.low > usw->s.value.data32[0] || - csw->s.high < usw->s.value.data32[0]) { - error("The value %u for the switch %s is out of range %i-%i.", usw->s.value.data32[0], sw_id(usw->s.name, cardno, devno, id), csw->s.low, csw->s.high); - return 1; - } - if (csw->s.value.data8[0] != (unsigned char)usw->s.value.data32[0]) { - csw->change = 1; - csw->s.value.data8[0] = (unsigned char)usw->s.value.data32[0]; + for (idx = 0; idx < cctl->info.values_count; idx++) { + if (cctl->info.value.integer.min > uctl->c.value.integer.value[idx] || + cctl->info.value.integer.max < uctl->c.value.integer.value[idx]) { + error("The value %li for the control '%s' is out of range %i-%i.", uctl->c.value.integer.value[idx], control_id(&uctl->c.id), cctl->info.value.integer.min, cctl->info.value.integer.max); + return 1; + } + if (cctl->c.value.integer.value[idx] != uctl->c.value.integer.value[idx]) { + cctl->change = 1; + cctl->c.value.integer.value[idx] = uctl->c.value.integer.value[idx]; + } } break; - case SND_SW_TYPE_WORD: - if (usw->s.type != SND_SW_TYPE_DWORD) { - error("A wrong type for the switch %s. The type word is expected. Skipping...", sw_id(usw->s.name, cardno, devno, id)); + case SND_CONTROL_TYPE_ENUMERATED: + if (uctl->type != SND_CONTROL_TYPE_BOOLEAN && uctl->type != SND_CONTROL_TYPE_INTEGER) { + error("A wrong type %i for the control '%s'. The type integer is expected. Skipping...", uctl->type, control_id(&uctl->c.id)); return 1; } - if (csw->s.low > usw->s.value.data32[0] || - csw->s.high < usw->s.value.data32[0]) { - error("The value %u for the switch %s is out of range %i-%i.", usw->s.value.data32[0], sw_id(usw->s.name, cardno, devno, id), csw->s.low, csw->s.high); - return 1; - } - if (csw->s.value.data16[0] != (unsigned short)usw->s.value.data32[0]) { - csw->change = 1; - csw->s.value.data16[0] = (unsigned short)usw->s.value.data32[0]; + for (idx = 0; idx < cctl->info.values_count; idx++) { + if (cctl->info.value.enumerated.items <= uctl->c.value.integer.value[idx]) { + error("The value %u for the control '%s' is out of range 0-%i.", uctl->c.value.integer.value[idx], control_id(&uctl->c.id), cctl->info.value.enumerated.items-1); + return 1; + } + if (cctl->c.value.enumerated.item[idx] != uctl->c.value.integer.value[idx]) { + cctl->change = 1; + cctl->c.value.enumerated.item[idx] = uctl->c.value.integer.value[idx]; + } } break; - case SND_SW_TYPE_DWORD: - if (usw->s.type != SND_SW_TYPE_DWORD) { - error("A wrong type for the switch %s. The type dword is expected. Skipping...", sw_id(usw->s.name, cardno, devno, id)); + case SND_CONTROL_TYPE_BYTES: + if (uctl->type != SND_CONTROL_TYPE_BYTES) { + error("A wrong type %i for the control %s. The type 'bytes' is expected. Skipping...", uctl->type, control_id(&uctl->c.id)); return 1; } - if (csw->s.low > usw->s.value.data32[0] || - csw->s.high < usw->s.value.data32[0]) { - error("The value %u for the switch %s is out of range %i-%i.", usw->s.value.data32[0], sw_id(usw->s.name, cardno, devno, id), csw->s.low, csw->s.high); - return 1; - } - if (csw->s.value.data32[0] != usw->s.value.data32[0]) { - csw->change = 1; - csw->s.value.data32[0] = usw->s.value.data32[0]; - } - break; - case SND_SW_TYPE_LIST: - if (usw->s.type != SND_SW_TYPE_DWORD) { - error("A wrong type for the switch %s. The type list is expected. Skipping...", sw_id(usw->s.name, cardno, devno, id)); - return 1; - } - if (csw->s.low > usw->s.value.data32[0] || - csw->s.high < usw->s.value.data32[0]) { - error("The value %i for the switch %s is out of range %i-%i.", usw->s.value.data32[0], sw_id(usw->s.name, cardno, devno, id), csw->s.low, csw->s.high); - return 1; - } - if (csw->s.value.item_number != usw->s.value.data32[0]) { - csw->change = 1; - csw->s.value.item_number = usw->s.value.data32[0]; - } - break; - case SND_SW_TYPE_USER_READ_ONLY: - break; - case SND_SW_TYPE_USER: - if (usw->s.type != SND_SW_TYPE_USER) { - error("A wrong type %i for the switch %s. The type user is expected. Skipping...", usw->s.type, sw_id(usw->s.name, cardno, devno, id)); - return 1; - } - if (memcmp(csw->s.value.data8, usw->s.value.data8, 32)) { - csw->change = 1; - memcpy(csw->s.value.data8, usw->s.value.data8, 32); + if (memcmp(cctl->c.value.bytes.data, uctl->c.value.bytes.data, uctl->info.values_count)) { + cctl->change = 1; + memcpy(cctl->c.value.bytes.data, uctl->c.value.bytes.data, uctl->info.values_count); } break; default: - error("The switch type %i is not known.", csw->s.type); + error("The control type %i is not known.", cctl->type); } return 0; } -static int soundcard_setup_merge_sw(struct ctl_switch *csw, struct ctl_switch *usw, int cardno, int devno, const char *id) +static int soundcard_setup_merge_control(struct ctl_control *cctl, struct ctl_control *uctl, int cardno) { - struct ctl_switch *csw1; + struct ctl_control *cctl1; - for ( ; usw; usw = usw->next) { - for (csw1 = csw; csw1; csw1 = csw1->next) { - if (!strncmp(csw1->s.name, usw->s.name, sizeof(csw1->s.name))) { - merge_one_sw(csw1, usw, cardno, devno, id); + for ( ; uctl; uctl = uctl->next) { + for (cctl1 = cctl; cctl1; cctl1 = cctl1->next) { + if (cctl1->c.id.iface == uctl->c.id.iface && + cctl1->c.id.device == uctl->c.id.device && + cctl1->c.id.subdevice == uctl->c.id.subdevice && + !strncmp(cctl1->c.id.name, uctl->c.id.name, sizeof(cctl1->c.id.name))) { + merge_one_control(cctl1, uctl, cardno); break; } } - if (!csw1) { - error("Cannot find the switch %s...", sw_id(usw->s.name, cardno, devno, id)); + if (!cctl1) { + error("Cannot find the control %s...", control_id(&uctl->c.id)); } } return 0; } -int soundcard_setup_merge_switches(int cardno) +int soundcard_setup_merge_controls(int cardno) { struct soundcard *soundcard, *rsoundcard; - struct mixer *mixer, *rmixer; - struct pcm *pcm, *rpcm; - struct rawmidi *rawmidi, *rrawmidi; for (rsoundcard = rsoundcards; rsoundcard; rsoundcard = rsoundcard->next) { for (soundcard = soundcards; soundcard; soundcard = soundcard->next) { @@ -168,226 +125,7 @@ int soundcard_setup_merge_switches(int cardno) } if (cardno >= 0 && soundcard->no != cardno) continue; - soundcard_setup_merge_sw(soundcard->control.switches, rsoundcard->control.switches, soundcard->no, -1, "control"); - for (rmixer = rsoundcard->mixers; rmixer; rmixer = rmixer->next) { - for (mixer = soundcard->mixers; mixer; mixer = mixer->next) { - if (!strncmp(mixer->info.name, rmixer->info.name, sizeof(mixer->info.name))) - break; - } - if (!mixer) { - error("The mixer device '%s' from the soundcard %i was not found...\n", rmixer->info.name, soundcard->no); - continue; - } - soundcard_setup_merge_sw(mixer->switches, rmixer->switches, soundcard->no, mixer->no, "mixer"); - } - for (rpcm = rsoundcard->pcms; rpcm; rpcm = rpcm->next) { - for (pcm = soundcard->pcms; pcm; pcm = pcm->next) { - if (!strncmp(pcm->info.name, rpcm->info.name, sizeof(pcm->info.name))) - break; - } - if (!rpcm) { - error("The PCM device '%s' from the soundcard %i was not found...\n", rpcm->info.name, soundcard->no); - continue; - } - soundcard_setup_merge_sw(pcm->pswitches, rpcm->pswitches, soundcard->no, pcm->no, "PCM playback"); - soundcard_setup_merge_sw(pcm->rswitches, rpcm->rswitches, soundcard->no, pcm->no, "PCM capture"); - } - for (rrawmidi = rsoundcard->rawmidis; rrawmidi; rrawmidi = rrawmidi->next) { - for (rawmidi = soundcard->rawmidis; rawmidi; rawmidi = rawmidi->next) { - if (!strncmp(rawmidi->info.name, rrawmidi->info.name, sizeof(rawmidi->info.name))) - break; - } - if (!rrawmidi) { - error("The rawmidi device '%s' from the soundcard %i was not found...\n", rrawmidi->info.name, soundcard->no); - continue; - } - soundcard_setup_merge_sw(rawmidi->iswitches, rrawmidi->iswitches, soundcard->no, rawmidi->no, "rawmidi input"); - soundcard_setup_merge_sw(rawmidi->oswitches, rrawmidi->oswitches, soundcard->no, rawmidi->no, "rawmidi output"); - } - } - return 0; -} - -static char *element_id(snd_mixer_eid_t *eid, int cardno, int devno, const char *id) -{ - static char str[256]; - - sprintf(str, "%s %s card %i", mixer_element_id(eid), id, cardno); - if (devno >= 0) - sprintf(str + strlen(str)," device %i", devno); - return str; -} - -static int merge_one_element(struct mixer_element *celement, struct mixer_element *uelement, int cardno, int devno, const char *id) -{ - int tmp; - - if (snd_mixer_element_has_control(&celement->element.eid) != 1) - return 0; - switch (celement->element.eid.type) { - case SND_MIXER_ETYPE_SWITCH1: - if (celement->element.data.switch1.sw != uelement->element.data.switch1.sw) { - error("Element %s has got a wrong count of channels.", element_id(&celement->element.eid, cardno, devno, id)); - return 1; - } - tmp = ((celement->element.data.switch1.sw + 31) / 32) * sizeof(unsigned int); - memcpy(celement->element.data.switch1.psw, uelement->element.data.switch1.psw, tmp); - break; - case SND_MIXER_ETYPE_SWITCH2: - celement->element.data.switch2.sw = uelement->element.data.switch2.sw; - break; - case SND_MIXER_ETYPE_SWITCH3: - if (celement->element.data.switch3.rsw != uelement->element.data.switch3.rsw) { - error("Element %s has got a wrong count of switches.", element_id(&celement->element.eid, cardno, devno, id)); - return 1; - } - tmp = ((celement->element.data.switch3.rsw + 31) / 32) * sizeof(unsigned int); - memcpy(celement->element.data.switch3.prsw, uelement->element.data.switch3.prsw, tmp); - break; - case SND_MIXER_ETYPE_VOLUME1: - if (celement->element.data.volume1.channels != uelement->element.data.volume1.channels) { - error("Element %s has got a wrong count of channels.", element_id(&celement->element.eid, cardno, devno, id)); - return 1; - } - tmp = celement->element.data.volume1.channels * sizeof(int); - memcpy(celement->element.data.volume1.pchannels, uelement->element.data.volume1.pchannels, tmp); - break; - case SND_MIXER_ETYPE_VOLUME2: - if (celement->element.data.volume2.achannels != uelement->element.data.volume2.achannels) { - error("Element %s has got a wrong count of channels.", element_id(&celement->element.eid, cardno, devno, id)); - return 1; - } - tmp = celement->element.data.volume2.achannels * sizeof(int); - memcpy(celement->element.data.volume2.pachannels, uelement->element.data.volume2.pachannels, tmp); - break; - case SND_MIXER_ETYPE_ACCU3: - if (celement->element.data.accu3.channels != uelement->element.data.accu3.channels) { - error("Element %s has got a wrong count of channels.", element_id(&celement->element.eid, cardno, devno, id)); - return 1; - } - tmp = celement->element.data.accu3.channels * sizeof(int); - memcpy(celement->element.data.accu3.pchannels, uelement->element.data.accu3.pchannels, tmp); - break; - case SND_MIXER_ETYPE_MUX1: - if (celement->element.data.mux1.psel) - free(celement->element.data.mux1.psel); - celement->element.data.mux1.sel_size = 0; - celement->element.data.mux1.sel = 0; - celement->element.data.mux1.sel_over = 0; - tmp = uelement->element.data.mux1.sel * sizeof(snd_mixer_eid_t); - if (tmp > 0) { - celement->element.data.mux1.psel = (snd_mixer_eid_t *)malloc(uelement->element.data.mux1.sel_size * sizeof(snd_mixer_eid_t)); - if (!celement->element.data.mux1.psel) { - error("No enough memory..."); - return 1; - } - celement->element.data.mux1.sel_size = uelement->element.data.mux1.sel_size; - celement->element.data.mux1.sel = uelement->element.data.mux1.sel; - memcpy(celement->element.data.mux1.psel, uelement->element.data.mux1.psel, tmp); - } - break; - case SND_MIXER_ETYPE_MUX2: - celement->element.data.mux2.sel = uelement->element.data.mux2.sel; - break; - case SND_MIXER_ETYPE_TONE_CONTROL1: - if ((uelement->element.data.tc1.tc & ~celement->info.data.tc1.tc) != 0) { - error("Wrong (unsupported) input for the element %s.", element_id(&celement->element.eid, cardno, devno, id)); - return 1; - } - celement->element.data.tc1.tc = uelement->element.data.tc1.tc; - celement->element.data.tc1.sw = uelement->element.data.tc1.sw; - celement->element.data.tc1.bass = uelement->element.data.tc1.bass; - celement->element.data.tc1.treble = uelement->element.data.tc1.treble; - break; - case SND_MIXER_ETYPE_3D_EFFECT1: - if ((uelement->element.data.teffect1.effect & ~celement->info.data.teffect1.effect) != 0) { - error("Wrong (unsupported) input for the element %s.", element_id(&celement->element.eid, cardno, devno, id)); - return 1; - } - celement->element.data.teffect1.effect = uelement->element.data.teffect1.effect; - celement->element.data.teffect1.sw = uelement->element.data.teffect1.sw; - celement->element.data.teffect1.mono_sw = uelement->element.data.teffect1.mono_sw; - celement->element.data.teffect1.wide = uelement->element.data.teffect1.wide; - celement->element.data.teffect1.volume = uelement->element.data.teffect1.volume; - celement->element.data.teffect1.center = uelement->element.data.teffect1.center; - celement->element.data.teffect1.space = uelement->element.data.teffect1.space; - celement->element.data.teffect1.depth = uelement->element.data.teffect1.depth; - celement->element.data.teffect1.delay = uelement->element.data.teffect1.delay; - celement->element.data.teffect1.feedback = uelement->element.data.teffect1.feedback; - celement->element.data.teffect1.depth_rear = uelement->element.data.teffect1.depth_rear; - break; - case SND_MIXER_ETYPE_PRE_EFFECT1: - if (celement->element.data.peffect1.pparameters) - free(celement->element.data.peffect1.pparameters); - celement->element.data.peffect1.parameters_size = 0; - celement->element.data.peffect1.parameters = 0; - celement->element.data.peffect1.parameters_over = 0; - celement->element.data.peffect1.item = uelement->element.data.peffect1.item; - if (celement->element.data.peffect1.item < 0) { - celement->element.data.peffect1.pparameters = (int *)malloc(uelement->element.data.peffect1.parameters_size * sizeof(int)); - if (!celement->element.data.peffect1.pparameters) { - error("No enough memory.."); - return 1; - } - celement->element.data.peffect1.parameters_size = uelement->element.data.peffect1.parameters_size; - celement->element.data.peffect1.parameters = uelement->element.data.peffect1.parameters; - tmp = celement->element.data.peffect1.parameters * sizeof(int); - memcpy(celement->element.data.peffect1.pparameters, uelement->element.data.peffect1.pparameters, tmp); - } - break; - default: - error("The element type %i for the element %s is not known.", celement->element.eid.type, mixer_element_id(&celement->element.eid)); - } - return 0; -} - -static int soundcard_setup_merge_element(struct mixer_element *celement, struct mixer_element *uelement, int cardno, int devno, const char *id) -{ - struct mixer_element *element; - - for ( ; uelement; uelement = uelement->next) { - for (element = celement; element; element = element->next) { - if (!strncmp(element->element.eid.name, uelement->element.eid.name, sizeof(element->element.eid.name)) && - element->element.eid.index == uelement->element.eid.index && - element->element.eid.type == uelement->element.eid.type) { - merge_one_element(element, uelement, cardno, devno, id); - break; - } - } - if (!element) { - error("Cannot find the element %s...", element_id(&uelement->element.eid, cardno, devno, id)); - } - } - return 0; -} - -int soundcard_setup_merge_data(int cardno) -{ - struct soundcard *soundcard, *rsoundcard; - struct mixer *mixer, *rmixer; - - for (rsoundcard = rsoundcards; rsoundcard; rsoundcard = rsoundcard->next) { - for (soundcard = soundcards; soundcard; soundcard = soundcard->next) { - if (!strncmp(soundcard->control.hwinfo.id, rsoundcard->control.hwinfo.id, sizeof(soundcard->control.hwinfo.id))) - break; - } - if (!soundcard) { - error("The soundcard '%s' was not found...\n", rsoundcard->control.hwinfo.id); - continue; - } - if (cardno >= 0 && soundcard->no != cardno) - continue; - for (rmixer = rsoundcard->mixers; rmixer; rmixer = rmixer->next) { - for (mixer = soundcard->mixers; mixer; mixer = mixer->next) { - if (!strncmp(mixer->info.name, rmixer->info.name, sizeof(mixer->info.name))) - break; - } - if (!mixer) { - error("The mixer device '%s' from the soundcard %i was not found...\n", rmixer->info.name, soundcard->no); - continue; - } - soundcard_setup_merge_element(mixer->elements, rmixer->elements, soundcard->no, mixer->no, "mixer"); - } + soundcard_setup_merge_control(soundcard->control.controls, rsoundcard->control.controls, soundcard->no); } return 0; } @@ -405,112 +143,23 @@ static int soundcard_open_ctl(snd_ctl_t **ctlhandle, struct soundcard *soundcard return 0; } -static int soundcard_open_mix(snd_mixer_t **mixhandle, struct soundcard *soundcard, struct mixer *mixer) -{ - int err; - - if (*mixhandle) - return 0; - if ((err = snd_mixer_open(mixhandle, soundcard->no, mixer->no)) < 0) { - error("Cannot open mixer interface for soundcard #%i.", soundcard->no + 1); - return 1; - } - return 0; -} - -int soundcard_setup_process_switches(int cardno) +int soundcard_setup_process_controls(int cardno) { int err; snd_ctl_t *ctlhandle = NULL; struct soundcard *soundcard; - struct ctl_switch *ctlsw; - struct mixer *mixer; - struct pcm *pcm; - struct rawmidi *rawmidi; + struct ctl_control *ctl; for (soundcard = soundcards; soundcard; soundcard = soundcard->next) { if (cardno >= 0 && soundcard->no != cardno) continue; - for (ctlsw = soundcard->control.switches; ctlsw; ctlsw = ctlsw->next) { - if (ctlsw->change) + for (ctl = soundcard->control.controls; ctl; ctl = ctl->next) { + if (ctl->change) if (!soundcard_open_ctl(&ctlhandle, soundcard)) { - if ((err = snd_ctl_switch_write(ctlhandle, &ctlsw->s)) < 0) - error("Control switch '%s' write error: %s", ctlsw->s.name, snd_strerror(err)); + if ((err = snd_ctl_cwrite(ctlhandle, &ctl->c)) < 0) + error("Control '%s' write error: %s", control_id(&ctl->c.id), snd_strerror(err)); } } - for (mixer = soundcard->mixers; mixer; mixer = mixer->next) { - for (ctlsw = mixer->switches; ctlsw; ctlsw = ctlsw->next) - if (ctlsw->change) - if (!soundcard_open_ctl(&ctlhandle, soundcard)) { - if ((err = snd_ctl_switch_write(ctlhandle, &ctlsw->s)) < 0) - error("Mixer switch '%s' write error: %s", ctlsw->s.name, snd_strerror(err)); - } - } - for (pcm = soundcard->pcms; pcm; pcm = pcm->next) { - for (ctlsw = pcm->pswitches; ctlsw; ctlsw = ctlsw->next) { - if (ctlsw->change) - if (!soundcard_open_ctl(&ctlhandle, soundcard)) { - if ((err = snd_ctl_switch_write(ctlhandle, &ctlsw->s)) < 0) - error("PCM playback switch '%s' write error: %s", ctlsw->s.name, snd_strerror(err)); - } - } - for (ctlsw = pcm->rswitches; ctlsw; ctlsw = ctlsw->next) { - if (ctlsw->change) - if (!soundcard_open_ctl(&ctlhandle, soundcard)) { - if ((err = snd_ctl_switch_write(ctlhandle, &ctlsw->s)) < 0) - error("PCM capture switch '%s' write error: %s", ctlsw->s.name, snd_strerror(err)); - } - } - } - for (rawmidi = soundcard->rawmidis; rawmidi; rawmidi = rawmidi->next) { - for (ctlsw = rawmidi->oswitches; ctlsw; ctlsw = ctlsw->next) { - if (ctlsw->change) - if (!soundcard_open_ctl(&ctlhandle, soundcard)) { - if ((err = snd_ctl_switch_write(ctlhandle, &ctlsw->s)) < 0) - error("RAWMIDI output switch '%s' write error: %s", ctlsw->s.name, snd_strerror(err)); - } - } - for (ctlsw = rawmidi->iswitches; ctlsw; ctlsw = ctlsw->next) { - if (ctlsw->change) - if (!soundcard_open_ctl(&ctlhandle, soundcard)) { - if ((err = snd_ctl_switch_write(ctlhandle, &ctlsw->s)) < 0) - error("RAWMIDI input switch '%s' write error: %s", ctlsw->s.name, snd_strerror(err)); - } - } - } - if (ctlhandle) { - snd_ctl_close(ctlhandle); - ctlhandle = NULL; - } - } - return 0; -} - -int soundcard_setup_process_data(int cardno) -{ - int err; - snd_ctl_t *ctlhandle = NULL; - snd_mixer_t *mixhandle = NULL; - struct soundcard *soundcard; - struct mixer *mixer; - struct mixer_element *element; - - for (soundcard = soundcards; soundcard; soundcard = soundcard->next) { - if (cardno >= 0 && soundcard->no != cardno) - continue; - for (mixer = soundcard->mixers; mixer; mixer = mixer->next) { - for (element = mixer->elements; element; element = element->next) - if (snd_mixer_element_has_control(&element->element.eid) == 1) { - if (!soundcard_open_mix(&mixhandle, soundcard, mixer)) { - if ((err = snd_mixer_element_write(mixhandle, &element->element)) < 0) - error("Mixer element %s write error: %s", mixer_element_id(&element->element.eid), snd_strerror(err)); - } - } - if (mixhandle) { - snd_mixer_close(mixhandle); - mixhandle = NULL; - } - } if (ctlhandle) { snd_ctl_close(ctlhandle); ctlhandle = NULL; diff --git a/alsactl/setup.c b/alsactl/setup.c index d854cd6..b909aed 100644 --- a/alsactl/setup.c +++ b/alsactl/setup.c @@ -37,24 +37,13 @@ struct soundcard *rsoundcards = NULL; * misc functions */ -static char *mixer_element_name(snd_mixer_eid_t *eid) +char *control_id(snd_control_id_t *id) { - static char str[32]; + static char str[128]; - if (!eid) + if (!id) return "???"; - strncpy(str, eid->name, sizeof(eid->name)); - str[sizeof(eid->name)] = '\0'; - return str; -} - -char *mixer_element_id(snd_mixer_eid_t *eid) -{ - static char str[64]; - - if (!eid) - return "???"; - sprintf(str, "%s:%i:%i", mixer_element_name(eid), eid->index, eid->type); + sprintf(str, "%i,%i,%i,%s,%i", id->iface, id->device, id->subdevice, id->name, id->index); return str; } @@ -62,9 +51,9 @@ char *mixer_element_id(snd_mixer_eid_t *eid) * free functions */ -static void soundcard_ctl_switch_free(struct ctl_switch *first) +static void soundcard_ctl_control_free(struct ctl_control *first) { - struct ctl_switch *next; + struct ctl_control *next; while (first) { next = first->next; @@ -73,87 +62,11 @@ static void soundcard_ctl_switch_free(struct ctl_switch *first) } } -static void soundcard_mixer_element_free(struct mixer_element *first) -{ - struct mixer_element *next; - - while (first) { - next = first->next; - snd_mixer_element_info_free(&first->info); - snd_mixer_element_free(&first->element); - free(first); - first = next; - } -} - -static void soundcard_mixer_free1(struct mixer *mixer) -{ - if (!mixer) - return; - soundcard_mixer_element_free(mixer->elements); - soundcard_ctl_switch_free(mixer->switches); - free(mixer); -} - -static void soundcard_mixer_free(struct mixer *first) -{ - struct mixer *next; - - while (first) { - next = first->next; - soundcard_mixer_free1(first); - first = next; - } -} - -static void soundcard_pcm_free1(struct pcm *pcm) -{ - if (!pcm) - return; - soundcard_ctl_switch_free(pcm->pswitches); - soundcard_ctl_switch_free(pcm->rswitches); - free(pcm); -} - -static void soundcard_pcm_free(struct pcm *first) -{ - struct pcm *next; - - while (first) { - next = first->next; - soundcard_pcm_free1(first); - first = next; - } -} - -static void soundcard_rawmidi_free1(struct rawmidi *rawmidi) -{ - if (!rawmidi) - return; - soundcard_ctl_switch_free(rawmidi->iswitches); - soundcard_ctl_switch_free(rawmidi->oswitches); - free(rawmidi); -} - -static void soundcard_rawmidi_free(struct rawmidi *first) -{ - struct rawmidi *next; - - while (first) { - next = first->next; - soundcard_rawmidi_free1(first); - first = next; - } -} - static void soundcard_free1(struct soundcard *soundcard) { if (!soundcard) return; - soundcard_ctl_switch_free(soundcard->control.switches); - soundcard_mixer_free(soundcard->mixers); - soundcard_pcm_free(soundcard->pcms); - soundcard_rawmidi_free(soundcard->rawmidis); + soundcard_ctl_control_free(soundcard->control.controls); free(soundcard); } @@ -205,77 +118,74 @@ void soundcard_setup_done(void) soundcards = NULL; } -static int determine_switches(void *handle, struct ctl_switch **csw, int iface, int device, int stream) +static int determine_controls(void *handle, struct ctl_control **cctl) { int err, idx; - snd_switch_list_t list; - snd_switch_list_item_t *item; - snd_switch_t sw; - struct ctl_switch *prev_csw; - struct ctl_switch *new_csw; + snd_control_list_t list; + snd_control_id_t *item; + snd_control_t ctl; + struct ctl_control *prev_control; + struct ctl_control *new_control; - *csw = NULL; + *cctl = NULL; bzero(&list, sizeof(list)); - list.iface = iface; - list.device = device; - list.stream = stream; - if ((err = snd_ctl_switch_list(handle, &list)) < 0) { - error("Cannot determine switches for interface %i and device %i and stream %i: %s", iface, device, stream, snd_strerror(err)); + if ((err = snd_ctl_clist(handle, &list)) < 0) { + error("Cannot determine controls: %s", snd_strerror(err)); return 1; } - if (list.switches_over <= 0) + if (list.controls <= 0) return 0; - list.switches_size = list.switches_over + 16; - list.switches = list.switches_over = 0; - list.pswitches = malloc(sizeof(snd_switch_list_item_t) * list.switches_size); - if (!list.pswitches) { + list.controls_request = list.controls + 16; + list.controls_offset = list.controls_count = 0; + list.pids = malloc(sizeof(snd_control_id_t) * list.controls_request); + if (!list.pids) { error("No enough memory..."); return 1; } - if ((err = snd_ctl_switch_list(handle, &list)) < 0) { - error("Cannot determine switches (2) for interface %i and device %i and stream %i: %s", iface, device, stream, snd_strerror(err)); + if ((err = snd_ctl_clist(handle, &list)) < 0) { + error("Cannot determine controls (2): %s", snd_strerror(err)); return 1; } - for (idx = 0, prev_csw = NULL; idx < list.switches; idx++) { - item = &list.pswitches[idx]; - bzero(&sw, sizeof(sw)); - sw.iface = iface; - sw.device = device; - sw.stream = stream; - strncpy(sw.name, item->name, sizeof(sw.name)); - if ((err = snd_ctl_switch_read(handle, &sw)) < 0) { - error("Cannot read switch '%s' for interface %i and device %i and stream %i: %s", sw.name, iface, device, stream, snd_strerror(err)); - free(list.pswitches); + for (idx = 0, prev_control = NULL; idx < list.controls_count; idx++) { + item = &list.pids[idx]; + bzero(&ctl, sizeof(ctl)); + ctl.id = *item; + if ((err = snd_ctl_cread(handle, &ctl)) < 0) { + error("Cannot read control '%s': %s", control_id(item), snd_strerror(err)); + free(list.pids); return 1; } - new_csw = malloc(sizeof(*new_csw)); - if (!new_csw) { + new_control = malloc(sizeof(*new_control)); + if (!new_control) { error("No enough memory..."); - free(list.pswitches); + free(list.pids); return 1; } - bzero(new_csw, sizeof(*new_csw)); - memcpy(&new_csw->s, &sw, sizeof(new_csw->s)); - if (*csw) { - prev_csw->next = new_csw; - prev_csw = new_csw; + bzero(new_control, sizeof(*new_control)); + memcpy(&new_control->c, &ctl, sizeof(new_control->c)); + new_control->info.id = ctl.id; + if ((err = snd_ctl_cinfo(handle, &new_control->info)) < 0) { + error("Cannot read control info '%s': %s", control_id(item), snd_strerror(err)); + free(new_control); + free(list.pids); + return 1; + } + if (*cctl) { + prev_control->next = new_control; + prev_control = new_control; } else { - *csw = prev_csw = new_csw; + *cctl = prev_control = new_control; } } - free(list.pswitches); + free(list.pids); return 0; } -static int soundcard_setup_collect_switches1(int cardno) +static int soundcard_setup_collect_controls1(int cardno) { snd_ctl_t *handle; - snd_mixer_t *mhandle; struct soundcard *card, *first, *prev; - int err, device; - struct mixer *mixer, *mixerprev; - struct pcm *pcm, *pcmprev; - struct rawmidi *rawmidi, *rawmidiprev; + int err; soundcard_remove(cardno); if ((err = snd_ctl_open(&handle, cardno)) < 0) { @@ -316,125 +226,28 @@ static int soundcard_setup_collect_switches1(int cardno) return 1; } /* --- */ - if (determine_switches(handle, &card->control.switches, SND_CTL_IFACE_CONTROL, 0, 0)) { + if (determine_controls(handle, &card->control.controls)) { snd_ctl_close(handle); return 1; - } - /* --- */ - for (device = 0, mixerprev = NULL; device < card->control.hwinfo.mixerdevs; device++) { - mixer = (struct mixer *) malloc(sizeof(struct mixer)); - if (!mixer) { - snd_ctl_close(handle); - error("malloc problem"); - return 1; - } - bzero(mixer, sizeof(struct mixer)); - mixer->no = device; - if (determine_switches(handle, &mixer->switches, SND_CTL_IFACE_MIXER, device, 0)) { - snd_ctl_close(handle); - return 1; - } - if (!mixerprev) { - card->mixers = mixer; - } else { - mixerprev->next = mixer; - } - mixerprev = mixer; - if ((err = snd_mixer_open(&mhandle, cardno, device)) < 0) { - snd_ctl_close(handle); - error("MIXER open error: %s", snd_strerror(err)); - return 1; - } - if ((err = snd_mixer_info(mhandle, &mixer->info)) < 0) { - snd_mixer_close(mhandle); - snd_ctl_close(handle); - error("MIXER info error: %s", snd_strerror(err)); - return 1; - } - snd_mixer_close(mhandle); - } - /* --- */ - for (device = 0, pcmprev = NULL; device < card->control.hwinfo.pcmdevs; device++) { - pcm = (struct pcm *) malloc(sizeof(struct pcm)); - if (!pcm) { - snd_ctl_close(handle); - error("malloc problem"); - return 1; - } - bzero(pcm, sizeof(struct pcm)); - pcm->no = device; - pcm->info.device = device; - pcm->info.stream = -1; - pcm->info.subdevice = -1; - if ((err = snd_ctl_pcm_info(handle, &pcm->info)) < 0) { - snd_ctl_close(handle); - error("PCM info error: %s", snd_strerror(err)); - return 1; - } - if (determine_switches(handle, &pcm->pswitches, SND_CTL_IFACE_PCM, device, SND_PCM_STREAM_PLAYBACK)) { - snd_ctl_close(handle); - return 1; - } - if (determine_switches(handle, &pcm->rswitches, SND_CTL_IFACE_PCM, device, SND_PCM_STREAM_CAPTURE)) { - snd_ctl_close(handle); - return 1; - } - if (!pcmprev) { - card->pcms = pcm; - } else { - pcmprev->next = pcm; - } - pcmprev = pcm; - } - /* --- */ - for (device = 0, rawmidiprev = NULL; device < card->control.hwinfo.mididevs; device++) { - rawmidi = (struct rawmidi *) malloc(sizeof(struct rawmidi)); - if (!rawmidi) { - snd_ctl_close(handle); - error("malloc problem"); - return 1; - } - bzero(rawmidi, sizeof(struct rawmidi)); - rawmidi->no = device; - rawmidi->info.device = device; - if ((err = snd_ctl_rawmidi_info(handle, &rawmidi->info)) < 0) { - snd_ctl_close(handle); - error("RAWMIDI info error: %s", snd_strerror(err)); - return 1; - } - if (determine_switches(handle, &rawmidi->oswitches, SND_CTL_IFACE_RAWMIDI, device, SND_RAWMIDI_STREAM_OUTPUT)) { - snd_ctl_close(handle); - return 1; - } - if (determine_switches(handle, &rawmidi->iswitches, SND_CTL_IFACE_RAWMIDI, device, SND_RAWMIDI_STREAM_INPUT)) { - snd_ctl_close(handle); - return 1; - } - if (!rawmidiprev) { - card->rawmidis = rawmidi; - } else { - rawmidiprev->next = rawmidi; - } - rawmidiprev = rawmidi; - } + } /* --- */ snd_ctl_close(handle); return 0; } -int soundcard_setup_collect_switches(int cardno) +int soundcard_setup_collect_controls(int cardno) { int err; unsigned int mask; if (cardno >= 0) { - return soundcard_setup_collect_switches1(cardno); + return soundcard_setup_collect_controls1(cardno); } else { mask = snd_cards_mask(); for (cardno = 0; cardno < SND_CARDS; cardno++) { if (!(mask & (1 << cardno))) continue; - err = soundcard_setup_collect_switches1(cardno); + err = soundcard_setup_collect_controls1(cardno); if (err) return err; } @@ -442,120 +255,14 @@ int soundcard_setup_collect_switches(int cardno) } } -static int soundcard_setup_collect_data1(int cardno) -{ - snd_ctl_t *handle; - snd_mixer_t *mhandle; - struct soundcard *card; - int err, idx; - struct mixer *mixer; - snd_mixer_elements_t elements; - struct mixer_element *mixerelement, *mixerelementprev; - - if ((err = snd_ctl_open(&handle, cardno)) < 0) { - error("SND CTL open error: %s", snd_strerror(err)); - return 1; - } - /* --- */ - for (card = soundcards; card && card->no != cardno; card = card->next); - if (!card) { - snd_ctl_close(handle); - error("The soundcard %i does not exist.", cardno); - return 1; - } - for (mixer = card->mixers; mixer; mixer = mixer->next) { - if ((err = snd_mixer_open(&mhandle, cardno, mixer->no)) < 0) { - snd_ctl_close(handle); - error("MIXER open error: %s", snd_strerror(err)); - return 1; - } - if (mixer->elements) - soundcard_mixer_element_free(mixer->elements); - mixer->elements = NULL; - bzero(&elements, sizeof(elements)); - if ((err = snd_mixer_elements(mhandle, &elements)) < 0) { - snd_mixer_close(mhandle); - snd_ctl_close(handle); - error("MIXER elements error: %s", snd_strerror(err)); - return 1; - } - elements.elements_size = elements.elements_over + 16; - elements.elements = elements.elements_over = 0; - elements.pelements = (snd_mixer_eid_t *)malloc(elements.elements_size * sizeof(snd_mixer_eid_t)); - if ((err = snd_mixer_elements(mhandle, &elements)) < 0) { - snd_mixer_close(mhandle); - snd_ctl_close(handle); - error("MIXER elements (2) error: %s", snd_strerror(err)); - return 1; - } - for (idx = 0, mixerelementprev = NULL; idx < elements.elements; idx++) { - mixerelement = (struct mixer_element *) malloc(sizeof(struct mixer_element)); - if (!mixerelement) { - snd_mixer_close(mhandle); - snd_ctl_close(handle); - error("malloc problem"); - return 1; - } - bzero(mixerelement, sizeof(*mixerelement)); - mixerelement->info.eid = elements.pelements[idx]; - mixerelement->element.eid = elements.pelements[idx]; - if (snd_mixer_element_has_info(&elements.pelements[idx]) == 1) { - if ((err = snd_mixer_element_info_build(mhandle, &mixerelement->info)) < 0) { - free(mixerelement); - error("MIXER element %s info error (%s) - skipping", mixer_element_id(&mixerelement->info.eid), snd_strerror(err)); - break; - } - } - if (snd_mixer_element_has_control(&elements.pelements[idx]) == 1) { - if ((err = snd_mixer_element_build(mhandle, &mixerelement->element)) < 0) { - free(mixerelement); - error("MIXER element %s build error (%s) - skipping", mixer_element_id(&mixerelement->element.eid), snd_strerror(err)); - break; - } - } - if (!mixerelementprev) { - mixer->elements = mixerelement; - } else { - mixerelementprev->next = mixerelement; - } - mixerelementprev = mixerelement; - } - free(elements.pelements); - snd_mixer_close(mhandle); - } - /* --- */ - snd_ctl_close(handle); - return 0; -} - -int soundcard_setup_collect_data(int cardno) -{ - int err; - unsigned int mask; - - if (cardno >= 0) { - return soundcard_setup_collect_data1(cardno); - } else { - mask = snd_cards_mask(); - for (cardno = 0; cardno < SND_CARDS; cardno++) { - if (!(mask & (1 << cardno))) - continue; - err = soundcard_setup_collect_data1(cardno); - if (err) - return err; - } - return 0; - } -} - - - int soundcard_setup_load(const char *cfgfile, int skip) { extern int yyparse(void); extern int linecount; extern FILE *yyin; +#ifdef YYDEBUG extern int yydebug; +#endif int xtry; #ifdef YYDEBUG @@ -579,268 +286,98 @@ int soundcard_setup_load(const char *cfgfile, int skip) return 0; } -static void soundcard_setup_write_switch(FILE * out, const char *space, int card, int interface, snd_switch_t *sw) +static void soundcard_setup_write_control(FILE * out, const char *space, int card, struct ctl_control *control) { char *s, v[16]; - int idx, first, switchok = 0; + int err, idx; + snd_ctl_t *handle; + snd_control_info_t info; + memcpy(&info, &control->info, sizeof(info)); v[0] = '\0'; - switch (sw->type) { - case SND_SW_TYPE_BOOLEAN: - s = "bool"; - strcpy(v, sw->value.enable ? "true" : "false"); - break; - case SND_SW_TYPE_BYTE: - s = "byte"; - if (sw->subtype == SND_SW_SUBTYPE_HEXA) { - sprintf(v, "0x%x", (unsigned int) sw->value.data8[0]); - } else { - sprintf(v, "%u", (unsigned int) sw->value.data8[0]); - } - break; - case SND_SW_TYPE_WORD: - s = "word"; - if (sw->subtype == SND_SW_SUBTYPE_HEXA) { - sprintf(v, "0x%x", (unsigned int) sw->value.data16[0]); - } else { - sprintf(v, "%u", (unsigned int) sw->value.data16[0]); - } - break; - case SND_SW_TYPE_DWORD: - s = "dword"; - if (sw->subtype == SND_SW_SUBTYPE_HEXA) { - sprintf(v, "0x%x", sw->value.data32[0]); - } else { - sprintf(v, "%u", sw->value.data32[0]); - } - break; - case SND_SW_TYPE_USER: - s = "user"; - break; - case SND_SW_TYPE_LIST: - s = "list"; - sprintf(v, "%u", sw->value.item_number); - break; - case SND_SW_TYPE_USER_READ_ONLY: - return; - default: - s = "unknown"; + switch (info.type) { + case SND_CONTROL_TYPE_BOOLEAN: s = "bool"; break; + case SND_CONTROL_TYPE_INTEGER: s = "integer"; break; + case SND_CONTROL_TYPE_ENUMERATED: s = "enumerated"; break; + case SND_CONTROL_TYPE_BYTES: s = "bytes"; break; + default: s = "unknown"; } - fprintf(out, "%s; The type is '%s'.\n", space, s); - if (sw->low != 0 || sw->high != 0) - fprintf(out, "%s; The accepted switch range is from %u to %u.\n", space, sw->low, sw->high); - if (sw->type == SND_SW_TYPE_LIST) { - snd_ctl_t *handle; - snd_switch_t swi; - memset(&swi, 0, sizeof(swi)); - swi.iface = sw->iface; - swi.device = sw->device; - swi.stream = sw->stream; - strncpy(swi.name, sw->name, sizeof(swi.name)); - swi.type = SND_SW_TYPE_LIST_ITEM; - if (snd_ctl_open(&handle, card) >= 0) { - for (idx = sw->low; idx <= sw->high; idx++) { - swi.low = swi.high = idx; - if (snd_ctl_switch_read(handle, &swi) >= 0) - fprintf(out, "%s; Item #%i - %s\n", space, swi.low, swi.value.item); + fprintf(out, "\n%s; The type is '%s'. Access:", space, s); + if (info.access & SND_CONTROL_ACCESS_READ) + fprintf(out, " read"); + if (info.access & SND_CONTROL_ACCESS_WRITE) + fprintf(out, " write"); + if (info.access & SND_CONTROL_ACCESS_INACTIVE) + fprintf(out, " inactive"); + fprintf(out, ". Count is %i.\n", info.values_count); + switch (info.type) { + case SND_CONTROL_TYPE_BOOLEAN: + if (info.value.integer.min != 0 || info.value.integer.max != 1 || + info.value.integer.step != 0) + error("Wrong control '%s' (boolean)\n", control_id(&info.id)); + break; + case SND_CONTROL_TYPE_INTEGER: + fprintf(out, "%s; The range is %li-%li (step %li)\n", space, info.value.integer.min, info.value.integer.max, info.value.integer.step); + break; + case SND_CONTROL_TYPE_ENUMERATED: + if ((err = snd_ctl_open(&handle, card)) >= 0) { + for (idx = 0; idx < info.value.enumerated.items; idx++) { + info.value.enumerated.item = idx; + if (snd_ctl_cinfo(handle, &info) >= 0) + fprintf(out, "%s; Item #%i - %s\n", space, idx, info.value.enumerated.name); } snd_ctl_close(handle); } + break; + default: + break; } - if (interface == SND_INTERFACE_CONTROL && sw->type == SND_SW_TYPE_WORD && - !strcmp(sw->name, SND_CTL_SW_JOYSTICK_ADDRESS)) { - for (idx = 1, first = 1; idx < 16; idx++) { - if (sw->value.data16[idx]) { - if (first) { - fprintf(out, "%s; Available addresses - 0x%x", space, sw->value.data16[idx]); - first = 0; - } else { - fprintf(out, ", 0x%x", sw->value.data16[idx]); - } - } + switch (info.id.iface) { + case SND_CONTROL_IFACE_CARD: s = "global"; break; + case SND_CONTROL_IFACE_HWDEP: s = "hwdep"; break; + case SND_CONTROL_IFACE_MIXER: s = "mixer"; break; + case SND_CONTROL_IFACE_PCM: s = "pcm"; break; + case SND_CONTROL_IFACE_RAWMIDI: s = "rawmidi"; break; + case SND_CONTROL_IFACE_TIMER: s = "timer"; break; + case SND_CONTROL_IFACE_SEQUENCER: s = "sequencer"; break; + default: sprintf(v, "%i", info.id.iface); s = v; break; + } + fprintf(out, "%scontrol(%s, %i, %i, \"%s\", %i", space, s, info.id.device, info.id.subdevice, info.id.name, info.id.index); + if (info.type == SND_CONTROL_TYPE_BYTES) + fprintf(out, "rawdata(@"); + for (idx = 0; idx < info.values_count; idx++) { + switch (info.type) { + case SND_CONTROL_TYPE_BOOLEAN: + fprintf(out, ", %s", control->c.value.integer.value[idx] ? "true" : "false"); + break; + case SND_CONTROL_TYPE_INTEGER: + fprintf(out, ", %li", control->c.value.integer.value[idx]); + break; + case SND_CONTROL_TYPE_ENUMERATED: + fprintf(out, ", %u", control->c.value.enumerated.item[idx]); + break; + case SND_CONTROL_TYPE_BYTES: + if (idx > 0) + fprintf(out, ":"); + fprintf(out, "%02x", control->c.value.bytes.data[idx]); + break; + default: + break; } - if (!first) - fprintf(out, "\n"); - } - if (interface == SND_INTERFACE_MIXER && sw->type == SND_SW_TYPE_BOOLEAN && - !strcmp(sw->name, SND_MIXER_SW_IEC958_OUTPUT)) { - fprintf(out, "%sswitch(\"%s\",", space, sw->name); - if (sw->value.data32[1] == (('C' << 8) | 'S')) { /* Cirrus Crystal */ - switchok = 0; - fprintf(out, "iec958ocs(%s", sw->value.enable ? "enable" : "disable"); - if (sw->value.data16[4] & 0x2000) - fprintf(out, ",3d"); - if (sw->value.data16[4] & 0x0040) - fprintf(out, ",reset"); - if (sw->value.data16[4] & 0x0020) - fprintf(out, ",user"); - if (sw->value.data16[4] & 0x0010) - fprintf(out, ",valid"); - if (sw->value.data16[5] & 0x0002) - fprintf(out, ",data"); - if (!(sw->value.data16[5] & 0x0004)) - fprintf(out, ",protect"); - switch (sw->value.data16[5] & 0x0018) { - case 0x0008: - fprintf(out, ",pre2"); - break; - default: - break; - } - if (sw->value.data16[5] & 0x0020) - fprintf(out, ",fsunlock"); - fprintf(out, ",type(0x%x)", (sw->value.data16[5] >> 6) & 0x7f); - if (sw->value.data16[5] & 0x2000) - fprintf(out, ",gstatus"); - fprintf(out, ")"); - goto __end; - } - } - fprintf(out, "%sswitch(\"%s\", ", space, sw->name); - if (!switchok) { - fprintf(out, v); - if (sw->type < 0 || sw->type > SND_SW_TYPE_LAST) { - /* TODO: some well known types should be verbose */ - fprintf(out, "rawdata(@"); - for (idx = 0; idx < 31; idx++) { - fprintf(out, "%02x:", sw->value.data8[idx]); - } - fprintf(out, "%02x@)", sw->value.data8[31]); - } - } - __end: + } + if (info.type == SND_CONTROL_TYPE_BYTES) + fprintf(out, ")"); fprintf(out, ")\n"); } -static void soundcard_setup_write_switches(FILE *out, const char *space, int card, int interface, struct ctl_switch **switches) +static void soundcard_setup_write_controls(FILE *out, const char *space, int card, struct ctl_control **controls) { - struct ctl_switch *sw; + struct ctl_control *ctl; - if (!(*switches)) + if (!(*controls)) return; - for (sw = *switches; sw; sw = sw->next) - soundcard_setup_write_switch(out, space, card, interface, &sw->s); -} - -static void soundcard_setup_write_mixer_element(FILE * out, struct mixer_element * xelement) -{ - snd_mixer_element_info_t *info; - snd_mixer_element_t *element; - int idx; - - info = &xelement->info; - element = &xelement->element; - if (snd_mixer_element_has_control(&element->eid) != 1) - return; - switch (element->eid.type) { - case SND_MIXER_ETYPE_SWITCH1: - fprintf(out, " element(\"%s\",%i,%i,Switch1(", mixer_element_name(&element->eid), element->eid.index, element->eid.type); - for (idx = 0; idx < element->data.switch1.sw; idx++) - fprintf(out, "%s%s", idx > 0 ? "," : "", snd_mixer_get_bit(element->data.switch1.psw, idx) ? "on" : "off"); - fprintf(out, "))\n"); - break; - case SND_MIXER_ETYPE_SWITCH2: - fprintf(out, " element(\"%s\",%i,%i,Switch2(%s))\n", mixer_element_name(&element->eid), element->eid.index, element->eid.type, element->data.switch2.sw ? "on" : "off"); - break; - case SND_MIXER_ETYPE_SWITCH3: - fprintf(out, " element(\"%s\",%i,%i,Switch3(", mixer_element_name(&element->eid), element->eid.index, element->eid.type); - for (idx = 0; idx < element->data.switch3.rsw; idx++) - fprintf(out, "%s%s", idx > 0 ? "," : "", snd_mixer_get_bit(element->data.switch3.prsw, idx) ? "on" : "off"); - fprintf(out, "))\n"); - break; - case SND_MIXER_ETYPE_VOLUME1: - for (idx = 0; idx < info->data.volume1.range; idx++) - fprintf(out, " ; Channel %i : Min %i Max %i\n", idx, info->data.volume1.prange[idx].min, info->data.volume1.prange[idx].max); - fprintf(out, " element(\"%s\",%i,%i,Volume1(", mixer_element_name(&element->eid), element->eid.index, element->eid.type); - for (idx = 0; idx < element->data.volume1.channels; idx++) - fprintf(out, "%s%i", idx > 0 ? "," : "", element->data.volume1.pchannels[idx]); - fprintf(out, "))\n"); - break; - case SND_MIXER_ETYPE_ACCU3: - for (idx = 0; idx < info->data.accu3.range; idx++) - fprintf(out, " ; Channel %i : Min %i Max %i\n", idx, info->data.accu3.prange[idx].min, info->data.accu3.prange[idx].max); - fprintf(out, " element(\"%s\",%i,%i,Accu3(", mixer_element_name(&element->eid), element->eid.index, element->eid.type); - for (idx = 0; idx < element->data.accu3.channels; idx++) - fprintf(out, "%s%i", idx > 0 ? "," : "", element->data.accu3.pchannels[idx]); - fprintf(out, "))\n"); - break; - case SND_MIXER_ETYPE_MUX1: - fprintf(out, " element(\"%s\",%i,%i,Mux1(", mixer_element_name(&element->eid), element->eid.index, element->eid.type); - for (idx = 0; idx < element->data.mux1.sel; idx++) { - fprintf(out, "%selement(\"%s\",%i,%i)", idx > 0 ? "," : "", mixer_element_name(&element->data.mux1.psel[idx]), element->data.mux1.psel[idx].index, element->data.mux1.psel[idx].type); - } - fprintf(out, "))\n"); - break; - case SND_MIXER_ETYPE_MUX2: - fprintf(out, " element(\"%s\",%i,%i,Mux2(", mixer_element_name(&element->eid), element->eid.index, element->eid.type); - fprintf(out, "element(\"%s\",%i,%i)", mixer_element_name(&element->data.mux2.sel), element->data.mux2.sel.index, element->data.mux2.sel.type); - fprintf(out, "))\n"); - break; - case SND_MIXER_ETYPE_TONE_CONTROL1: - if (info->data.tc1.tc & SND_MIXER_TC1_SW) - fprintf(out, " ; The tone control has an on/off switch.\n"); - if (info->data.tc1.tc & SND_MIXER_TC1_BASS) - fprintf(out, " ; Bass : Min %i Max %i\n", info->data.tc1.min_bass, info->data.tc1.max_bass); - if (info->data.tc1.tc & SND_MIXER_TC1_TREBLE) - fprintf(out, " ; Treble : Min %i Max %i\n", info->data.tc1.min_treble, info->data.tc1.max_treble); - fprintf(out, " element(\"%s\",%i,%i,ToneControl1(", mixer_element_name(&element->eid), element->eid.index, element->eid.type); - idx = 0; - if (element->data.tc1.tc & SND_MIXER_TC1_SW) - fprintf(out, "%ssw=%s", idx++ > 0 ? "," : "", element->data.tc1.sw ? "on" : "off"); - if (element->data.tc1.tc & SND_MIXER_TC1_BASS) - fprintf(out, "%sbass=%i", idx++ > 0 ? "," : "", element->data.tc1.bass); - if (element->data.tc1.tc & SND_MIXER_TC1_TREBLE) - fprintf(out, "%streble=%i", idx++ > 0 ? "," : "", element->data.tc1.treble); - fprintf(out, "))\n"); - break; - case SND_MIXER_ETYPE_3D_EFFECT1: - if (info->data.teffect1.effect & SND_MIXER_EFF1_SW) - fprintf(out, " ; The 3D effect has an on/off switch.\n"); - if (info->data.teffect1.effect & SND_MIXER_EFF1_MONO_SW) - fprintf(out, " ; The 3D effect has an mono processing on/off switch.\n"); - if (info->data.teffect1.effect & SND_MIXER_EFF1_WIDE) - fprintf(out, " ; Wide : Min %i Max %i\n", info->data.teffect1.min_wide, info->data.teffect1.max_wide); - if (info->data.teffect1.effect & SND_MIXER_EFF1_VOLUME) - fprintf(out, " ; Volume : Min %i Max %i\n", info->data.teffect1.min_volume, info->data.teffect1.max_volume); - if (info->data.teffect1.effect & SND_MIXER_EFF1_CENTER) - fprintf(out, " ; Center : Min %i Max %i\n", info->data.teffect1.min_center, info->data.teffect1.max_center); - if (info->data.teffect1.effect & SND_MIXER_EFF1_SPACE) - fprintf(out, " ; Space : Min %i Max %i\n", info->data.teffect1.min_space, info->data.teffect1.max_space); - if (info->data.teffect1.effect & SND_MIXER_EFF1_DEPTH) - fprintf(out, " ; Depth : Min %i Max %i\n", info->data.teffect1.min_depth, info->data.teffect1.max_depth); - if (info->data.teffect1.effect & SND_MIXER_EFF1_DELAY) - fprintf(out, " ; Delay : Min %i Max %i\n", info->data.teffect1.min_delay, info->data.teffect1.max_delay); - if (info->data.teffect1.effect & SND_MIXER_EFF1_FEEDBACK) - fprintf(out, " ; Feedback : Min %i Max %i\n", info->data.teffect1.min_feedback, info->data.teffect1.max_feedback); - if (info->data.teffect1.effect & SND_MIXER_EFF1_DEPTH_REAR) - fprintf(out, " ; Depth rear : Min %i Max %i\n", info->data.teffect1.min_depth_rear, info->data.teffect1.max_depth_rear); - fprintf(out, " element(\"%s\",%i,%i,_3D_Effect1(", mixer_element_name(&element->eid), element->eid.index, element->eid.type); - idx = 0; - if (element->data.teffect1.effect & SND_MIXER_EFF1_SW) - fprintf(out, "%ssw=%s", idx++ > 0 ? "," : "", element->data.teffect1.sw ? "on" : "off"); - if (element->data.teffect1.effect & SND_MIXER_EFF1_MONO_SW) - fprintf(out, "%smono_sw=%s", idx++ > 0 ? "," : "", element->data.teffect1.mono_sw ? "on" : "off"); - if (element->data.teffect1.effect & SND_MIXER_EFF1_WIDE) - fprintf(out, "%swide=%i", idx++ > 0 ? "," : "", element->data.teffect1.wide); - if (element->data.teffect1.effect & SND_MIXER_EFF1_VOLUME) - fprintf(out, "%svolume=%i", idx++ > 0 ? "," : "", element->data.teffect1.volume); - if (element->data.teffect1.effect & SND_MIXER_EFF1_CENTER) - fprintf(out, "%scenter=%i", idx++ > 0 ? "," : "", element->data.teffect1.center); - if (element->data.teffect1.effect & SND_MIXER_EFF1_SPACE) - fprintf(out, "%sspace=%i", idx++ > 0 ? "," : "", element->data.teffect1.space); - if (element->data.teffect1.effect & SND_MIXER_EFF1_DEPTH) - fprintf(out, "%sdepth=%i", idx++ > 0 ? "," : "", element->data.teffect1.depth); - if (element->data.teffect1.effect & SND_MIXER_EFF1_DELAY) - fprintf(out, "%sdelay=%i", idx++ > 0 ? "," : "", element->data.teffect1.delay); - if (element->data.teffect1.effect & SND_MIXER_EFF1_FEEDBACK) - fprintf(out, "%sfeedback=%i", idx++ > 0 ? "," : "", element->data.teffect1.feedback); - if (element->data.teffect1.effect & SND_MIXER_EFF1_DEPTH_REAR) - fprintf(out, "%sdepth_rear=%i", idx++ > 0 ? "," : "", element->data.teffect1.depth_rear); - fprintf(out, "))\n"); - break; - default: - fprintf(out, " ; Unknown element %s\n", mixer_element_id(&element->eid)); - } + for (ctl = *controls; ctl; ctl = ctl->next) + soundcard_setup_write_control(out, space, card, ctl); } #define MAX_LINE (32 * 1024) @@ -850,10 +387,6 @@ int soundcard_setup_write(const char *cfgfile, int cardno) FILE *out, *out1, *out2, *in; char *tmpfile1, *tmpfile2; struct soundcard *first, *sel = NULL; - struct mixer *mixer; - struct mixer_element *mixerelement; - struct pcm *pcm; - struct rawmidi *rawmidi; char *line, cardname[sizeof(first->control.hwinfo.name)+16], *ptr1; int mark, size, ok; @@ -904,49 +437,8 @@ int soundcard_setup_write(const char *cfgfile, int cardno) continue; sel = first; fprintf(out, "soundcard(\"%s\") {\n", first->control.hwinfo.id); - if (first->control.switches) { - fprintf(out, " control {\n"); - soundcard_setup_write_switches(out, " ", first->no, SND_INTERFACE_CONTROL, &first->control.switches); - fprintf(out, " }\n"); - } - for (mixer = first->mixers; mixer; mixer = mixer->next) { - fprintf(out, " mixer(\"%s\") {\n", mixer->info.name); - soundcard_setup_write_switches(out, " ", first->no, SND_INTERFACE_MIXER, &mixer->switches); - for (mixerelement = mixer->elements; mixerelement; mixerelement = mixerelement->next) - soundcard_setup_write_mixer_element(out, mixerelement); - fprintf(out, " }\n"); - } - for (pcm = first->pcms; pcm; pcm = pcm->next) { - if (!pcm->pswitches && !pcm->rswitches) - continue; - fprintf(out, " pcm(\"%s\") {\n", pcm->info.name); - if (pcm->pswitches) { - fprintf(out, " playback {\n"); - soundcard_setup_write_switches(out, " ", first->no, SND_INTERFACE_PCM, &pcm->pswitches); - fprintf(out, " }\n"); - } - if (pcm->rswitches) { - fprintf(out, " capture {\n"); - soundcard_setup_write_switches(out, " ", first->no, SND_INTERFACE_PCM, &pcm->rswitches); - fprintf(out, " }\n"); - } - fprintf(out, " }\n"); - } - for (rawmidi = first->rawmidis; rawmidi; rawmidi = rawmidi->next) { - if (!rawmidi->oswitches && !rawmidi->iswitches) - continue; - fprintf(out, " rawmidi(\"%s\") {\n", rawmidi->info.name); - if (rawmidi->oswitches) { - fprintf(out, " output {\n"); - soundcard_setup_write_switches(out, " ", first->no, SND_INTERFACE_RAWMIDI, &rawmidi->oswitches); - fprintf(out, " }\n"); - } - if (rawmidi->iswitches) { - fprintf(out, " input {\n"); - soundcard_setup_write_switches(out, " ", first->no, SND_INTERFACE_RAWMIDI, &rawmidi->iswitches); - fprintf(out, " }\n"); - } - fprintf(out, " }\n"); + if (first->control.controls) { + soundcard_setup_write_controls(out, " ", first->no, &first->control.controls); } fprintf(out, "}\n%s", cardno < 0 && first->next ? "\n" : ""); } diff --git a/alsamixer/alsamixer.c b/alsamixer/alsamixer.c index ca7a63e..b8dfaac 100644 --- a/alsamixer/alsamixer.c +++ b/alsamixer/alsamixer.c @@ -18,6 +18,11 @@ * * ChangeLog: * + * Fri Jun 23 14:10:00 MEST 2000 Jaroslav Kysela + * + * * ported to new mixer 0.6.x API (simple control) + * * improved error handling (mixer_abort) + * * Thu Mar 9 22:54:16 MET 2000 Takashi iwai * * * a group is split into front, rear, center and woofer elements. @@ -26,7 +31,7 @@ * * * version 1.00 * - * * ported to new mixer API (group control) + * * ported to new mixer API (scontrol control) * * Sun Feb 21 19:55:01 1999 Tim Janik * @@ -121,7 +126,7 @@ #define PRGNAME "alsamixer" #define PRGNAME_UPPER "AlsaMixer" #define VERSION "v1.00" -#define CHECK_ABORT(e,s) ({ if (errno != EINTR) mixer_abort ((e), (s)); }) +#define CHECK_ABORT(e,s,n) ({ if ((n) != -EINTR) mixer_abort ((e), (s), (n)); }) #define GETCH_BLOCK(w) ({ timeout ((w) ? -1 : 0); }) #undef MAX @@ -174,10 +179,9 @@ static float mixer_extra_space = 0; static int mixer_cbar_height = 0; static int card_id = 0; -static int mixer_id = 0; static snd_mixer_t *mixer_handle; -static char *mixer_card_name = NULL; -static char *mixer_device_name = NULL; +static char mixer_card_name[128]; +static char mixer_device_name[128]; /* mixer bar channel : left or right */ #define MIXER_CHN_LEFT 0 @@ -210,10 +214,10 @@ static int mixer_elem_chn[][2] = { { SND_MIXER_CHN_WOOFER, -1 }, }; -static snd_mixer_gid_t *mixer_gid = NULL; -static int mixer_n_groups = 0; +static snd_mixer_sid_t *mixer_sid = NULL; +static int mixer_n_scontrols = 0; -/* split groups */ +/* split scontrols */ static int mixer_n_elems = 0; static int mixer_n_vis_elems = 0; static int mixer_first_vis_elem = 0; @@ -349,7 +353,8 @@ typedef enum /* --- prototypes --- */ static void mixer_abort (ErrType error, - const char *err_string) + const char *err_string, + int xerrno) __attribute__ ((noreturn)); @@ -376,7 +381,8 @@ mixer_clear (int full_redraw) static void mixer_abort (ErrType error, - const char *err_string) + const char *err_string, + int xerrno) { if (mixer_window) { @@ -393,16 +399,15 @@ mixer_abort (ErrType error, { case ERR_OPEN: fprintf (stderr, - PRGNAME ": failed to open mixer #%i/#%i: %s\n", + PRGNAME ": failed to open mixer #%i: %s\n", card_id, - mixer_id, - snd_strerror (errno)); + snd_strerror (xerrno)); break; case ERR_FCN: fprintf (stderr, PRGNAME ": function %s failed: %s\n", err_string, - snd_strerror (errno)); + snd_strerror (xerrno)); break; case ERR_SIGNAL: fprintf (stderr, @@ -464,23 +469,23 @@ mixer_conv(int val, int omin, int omax, int nmin, int nmax) } static int -mixer_calc_volume(snd_mixer_group_t *group, int vol, int chn) +mixer_calc_volume(snd_mixer_simple_control_t *scontrol, int vol, int chn) { int vol1; vol1 = (vol < 0) ? -vol : vol; if (vol1 > 0) { if (vol1 > 100) - vol1 = group->max; + vol1 = scontrol->max; else - vol1 = mixer_conv(vol1, 0, 100, group->min, group->max); + vol1 = mixer_conv(vol1, 0, 100, scontrol->min, scontrol->max); if (vol1 <= 0) vol1 = 1; if (vol < 0) vol1 = -vol1; } - vol1 += group->volume.values[chn]; - return CLAMP(vol1, group->min, group->max); + vol1 += scontrol->volume.values[chn]; + return CLAMP(vol1, scontrol->min, scontrol->max); } /* set new channel values @@ -488,22 +493,24 @@ mixer_calc_volume(snd_mixer_group_t *group, int vol, int chn) static void mixer_write_cbar (int elem_index) { - snd_mixer_group_t group; + snd_mixer_simple_control_t scontrol; int vleft, vright, vbalance; int type, chn_left, chn_right; - int i, changed; + int i, err, changed; - bzero(&group, sizeof(group)); - group.gid = mixer_gid[mixer_grpidx[elem_index]]; - if (snd_mixer_group_read (mixer_handle, &group) < 0) - CHECK_ABORT (ERR_FCN, "snd_mixer_group_read()"); + bzero(&scontrol, sizeof(scontrol)); + if (mixer_sid == NULL) + return; + scontrol.sid = mixer_sid[mixer_grpidx[elem_index]]; + if ((err = snd_mixer_simple_control_read (mixer_handle, &scontrol)) < 0) + CHECK_ABORT (ERR_FCN, "snd_mixer_simple_control_read()", err); type = mixer_type[elem_index]; chn_left = mixer_elem_chn[type][MIXER_CHN_LEFT]; - if (! (group.channels & (1 << chn_left))) + if (! (scontrol.channels & (1 << chn_left))) return; /* ..??.. */ chn_right = mixer_elem_chn[type][MIXER_CHN_RIGHT]; - if (chn_right >= 0 && ! (group.channels & (1 << chn_right))) + if (chn_right >= 0 && ! (scontrol.channels & (1 << chn_right))) chn_right = -1; changed = 0; @@ -513,31 +520,31 @@ mixer_write_cbar (int elem_index) if ((mixer_volume_delta[MIXER_CHN_LEFT] || mixer_volume_delta[MIXER_CHN_RIGHT] || mixer_balance_volumes) && - (group.caps & SND_MIXER_GRPCAP_VOLUME)) { + (scontrol.caps & SND_MIXER_SCTCAP_VOLUME)) { int mono = - (chn_right < 0 || (group.caps & SND_MIXER_GRPCAP_JOINTLY_VOLUME)); + (chn_right < 0 || (scontrol.caps & SND_MIXER_SCTCAP_JOINTLY_VOLUME)); if (mono && !mixer_volume_delta[MIXER_CHN_LEFT]) mixer_volume_delta[MIXER_CHN_LEFT] = mixer_volume_delta[MIXER_CHN_RIGHT]; - vleft = mixer_calc_volume(&group, mixer_volume_delta[MIXER_CHN_LEFT], chn_left); + vleft = mixer_calc_volume(&scontrol, mixer_volume_delta[MIXER_CHN_LEFT], chn_left); vbalance = vleft; if (! mono) { - vright = mixer_calc_volume(&group, mixer_volume_delta[MIXER_CHN_RIGHT], chn_right); + vright = mixer_calc_volume(&scontrol, mixer_volume_delta[MIXER_CHN_RIGHT], chn_right); vbalance += vright; vbalance /= 2; } else vright = vleft; if (vleft >= 0 && vright >= 0) { - if (group.caps & SND_MIXER_GRPCAP_JOINTLY_VOLUME) { + if (scontrol.caps & SND_MIXER_SCTCAP_JOINTLY_VOLUME) { for (i = 0; i < SND_MIXER_CHN_LAST; i++) { - if (group.channels & (1 << i)) - group.volume.values[i] = vleft; + if (scontrol.channels & (1 << i)) + scontrol.volume.values[i] = vleft; } } else { if (mixer_balance_volumes) vleft = vright = vbalance; - group.volume.values[chn_left] = vleft; + scontrol.volume.values[chn_left] = vleft; if (! mono) - group.volume.values[chn_right] = vright; + scontrol.volume.values[chn_right] = vright; } changed = 1; } @@ -547,15 +554,15 @@ mixer_write_cbar (int elem_index) /* mute */ - if (mixer_toggle_mute && (group.caps & SND_MIXER_GRPCAP_MUTE)) { - group.mute &= group.channels; - if (group.caps & SND_MIXER_GRPCAP_JOINTLY_MUTE) - group.mute = group.mute ? 0 : group.channels; + if (mixer_toggle_mute && (scontrol.caps & SND_MIXER_SCTCAP_MUTE)) { + scontrol.mute &= scontrol.channels; + if (scontrol.caps & SND_MIXER_SCTCAP_JOINTLY_MUTE) + scontrol.mute = scontrol.mute ? 0 : scontrol.channels; else { if (mixer_toggle_mute & MIXER_MASK_LEFT) - group.mute ^= (1 << chn_left); + scontrol.mute ^= (1 << chn_left); if (chn_right >= 0 && (mixer_toggle_mute & MIXER_MASK_RIGHT)) - group.mute ^= (1 << chn_right); + scontrol.mute ^= (1 << chn_right); } changed = 1; } @@ -563,23 +570,23 @@ mixer_write_cbar (int elem_index) /* capture */ - if (mixer_toggle_capture && (group.caps & SND_MIXER_GRPCAP_CAPTURE)) { - group.capture &= group.channels; - if (group.caps & SND_MIXER_GRPCAP_JOINTLY_CAPTURE) - group.capture = group.capture ? 0 : group.channels; + if (mixer_toggle_capture && (scontrol.caps & SND_MIXER_SCTCAP_CAPTURE)) { + scontrol.capture &= scontrol.channels; + if (scontrol.caps & SND_MIXER_SCTCAP_JOINTLY_CAPTURE) + scontrol.capture = scontrol.capture ? 0 : scontrol.channels; else { if (mixer_toggle_capture & MIXER_MASK_LEFT) - group.capture ^= (1 << chn_left); + scontrol.capture ^= (1 << chn_left); if (chn_right >= 0 && (mixer_toggle_capture & MIXER_MASK_RIGHT)) - group.capture ^= (1 << chn_right); + scontrol.capture ^= (1 << chn_right); } changed = 1; } mixer_toggle_capture = 0; if (changed) { - if (snd_mixer_group_write (mixer_handle, &group) < 0) - CHECK_ABORT (ERR_FCN, "snd_mixer_group_write()"); + if ((err = snd_mixer_simple_control_write (mixer_handle, &scontrol)) < 0) + CHECK_ABORT (ERR_FCN, "snd_mixer_simple_control_write()", err); } } @@ -588,37 +595,42 @@ static void mixer_update_cbar (int elem_index) { char string[64], string1[64]; - int dc; - snd_mixer_group_t group; + int err, dc; + snd_mixer_simple_control_t scontrol; int vleft, vright; int type, chn_left, chn_right; int x, y, i; - /* set new group indices and read info + fprintf(stderr, "update cbar\n"); + + /* set new scontrol indices and read info */ - bzero(&group, sizeof(group)); - group.gid = mixer_gid[mixer_grpidx[elem_index]]; - if (snd_mixer_group_read (mixer_handle, &group) < 0) - CHECK_ABORT (ERR_FCN, "snd_mixer_group_read()"); + bzero(&scontrol, sizeof(scontrol)); + if (mixer_sid == NULL) + return; + scontrol.sid = mixer_sid[mixer_grpidx[elem_index]]; + if ((err = snd_mixer_simple_control_read (mixer_handle, &scontrol)) < 0) + CHECK_ABORT (ERR_FCN, "snd_mixer_simple_control_read()", err); + fprintf(stderr, "scontrol.channels = 0x%x\n", scontrol.channels); type = mixer_type[elem_index]; chn_left = mixer_elem_chn[type][MIXER_CHN_LEFT]; - if (! (group.channels & (1 << chn_left))) + if (! (scontrol.channels & (1 << chn_left))) return; /* ..??.. */ chn_right = mixer_elem_chn[type][MIXER_CHN_RIGHT]; - if (chn_right >= 0 && ! (group.channels & (1 << chn_right))) + if (chn_right >= 0 && ! (scontrol.channels & (1 << chn_right))) chn_right = -1; /* first, read values for the numbers to be displayed */ - if (snd_mixer_group_read (mixer_handle, &group) < 0) - CHECK_ABORT (ERR_FCN, "snd_mixer_group_read()"); + if ((err = snd_mixer_simple_control_read (mixer_handle, &scontrol)) < 0) + CHECK_ABORT (ERR_FCN, "snd_mixer_simple_control_read()", err); - vleft = group.volume.values[chn_left]; - vleft = mixer_conv(vleft, group.min, group.max, 0, 100); + vleft = scontrol.volume.values[chn_left]; + vleft = mixer_conv(vleft, scontrol.min, scontrol.max, 0, 100); if (chn_right >= 0) { - vright = group.volume.values[chn_right]; - vright = mixer_conv(vright, group.min, group.max, 0, 100); + vright = scontrol.volume.values[chn_right]; + vright = mixer_conv(vright, scontrol.min, scontrol.max, 0, 100); } else { vright = vleft; } @@ -631,10 +643,10 @@ mixer_update_cbar (int elem_index) /* channel bar name */ mixer_dc (elem_index == mixer_focus_elem ? DC_CBAR_FOCUS_LABEL : DC_CBAR_LABEL); - if (group.gid.index > 0) - sprintf(string1, "%s %d", group.gid.name, group.gid.index); + if (scontrol.sid.index > 0) + sprintf(string1, "%s %d", scontrol.sid.name, scontrol.sid.index); else - strcpy(string1, group.gid.name); + strcpy(string1, scontrol.sid.name); string1[8] = 0; for (i = 0; i < 8; i++) { @@ -695,10 +707,10 @@ mixer_update_cbar (int elem_index) mvaddstr (y, x, " "); mixer_dc (DC_CBAR_FRAME); mvaddch (y, x + 2, ACS_ULCORNER); - dc = group.mute & (1 << chn_left) ? DC_CBAR_MUTE : DC_CBAR_NOMUTE; + dc = scontrol.mute & (1 << chn_left) ? DC_CBAR_MUTE : DC_CBAR_NOMUTE; mvaddch (y, x + 3, mixer_dc (dc)); if (chn_right >= 0) - dc = group.mute & (1 << chn_right) ? DC_CBAR_MUTE : DC_CBAR_NOMUTE; + dc = scontrol.mute & (1 << chn_right) ? DC_CBAR_MUTE : DC_CBAR_NOMUTE; mvaddch (y, x + 4, mixer_dc (dc)); mixer_dc (DC_CBAR_FRAME); mvaddch (y, x + 5, ACS_URCORNER); @@ -706,20 +718,20 @@ mixer_update_cbar (int elem_index) /* capture input? */ - if ((group.capture & (1 << chn_left)) || - (chn_right >= 0 && (group.capture & (1 << chn_right)))) + if ((scontrol.capture & (1 << chn_left)) || + (chn_right >= 0 && (scontrol.capture & (1 << chn_right)))) { mixer_dc (DC_CBAR_CAPTURE); mvaddstr (y, x + 1, "CAPTUR"); - if (group.capture & (1 << chn_left)) { + if (scontrol.capture & (1 << chn_left)) { mvaddstr (y + 1, x + 1, "L"); if (chn_right < 0) mvaddstr (y + 1, x + 6, "R"); } - if (chn_right >= 0 && (group.capture & (1 << chn_right))) + if (chn_right >= 0 && (scontrol.capture & (1 << chn_right))) mvaddstr (y + 1, x + 6, "R"); } - else if (group.caps & SND_MIXER_GRPCAP_CAPTURE) + else if (scontrol.caps & SND_MIXER_SCTCAP_CAPTURE) for (i = 0; i < 6; i++) mvaddch (y, x + 1 + i, mixer_dc (DC_CBAR_NOCAPTURE)); else @@ -746,6 +758,7 @@ mixer_update_cbars (void) mixer_cbar_get_pos (mixer_focus_elem, &x, &y); } mixer_write_cbar(mixer_focus_elem); + fprintf(stderr, "mixer_n_vis_elems = %i\n", mixer_n_vis_elems); for (i = 0; i < mixer_n_vis_elems; i++) mixer_update_cbar (i + mixer_first_vis_elem); @@ -1178,75 +1191,78 @@ mixer_show_procinfo (void) static void mixer_init (void) { - static snd_mixer_info_t mixer_info = { 0, }; - static struct snd_ctl_hw_info hw_info; + snd_ctl_hw_info_t hw_info; snd_ctl_t *ctl_handle; + int err; - if (snd_ctl_open (&ctl_handle, card_id) < 0) - mixer_abort (ERR_OPEN, "snd_ctl_open"); - if (snd_ctl_hw_info (ctl_handle, &hw_info) < 0) - mixer_abort (ERR_FCN, "snd_ctl_hw_info"); + if ((err = snd_ctl_open (&ctl_handle, card_id)) < 0) + mixer_abort (ERR_OPEN, "snd_ctl_open", err); + if ((err = snd_ctl_hw_info (ctl_handle, &hw_info)) < 0) + mixer_abort (ERR_FCN, "snd_ctl_hw_info", err); snd_ctl_close (ctl_handle); /* open mixer device */ - if (snd_mixer_open (&mixer_handle, card_id, mixer_id) < 0) - mixer_abort (ERR_OPEN, "snd_mixer_open"); + if ((err = snd_mixer_open (&mixer_handle, card_id)) < 0) + mixer_abort (ERR_OPEN, "snd_mixer_open", err); /* setup global variables */ - if (snd_mixer_info (mixer_handle, &mixer_info) < 0) - mixer_abort (ERR_FCN, "snd_mixer_info"); - mixer_card_name = hw_info.name; - mixer_device_name = mixer_info.name; + strcpy(mixer_card_name, hw_info.name); + strcpy(mixer_device_name, hw_info.mixername); } static void mixer_reinit (void) { - snd_mixer_groups_t groups; - int idx, elem_index, i; - snd_mixer_gid_t focus_gid; + snd_mixer_simple_control_list_t scontrols; + int idx, err, elem_index, i; + snd_mixer_sid_t focus_gid; int focus_type = -1; - if (mixer_gid) { - focus_gid = mixer_gid[mixer_grpidx[mixer_focus_elem]]; + if (mixer_sid) { + focus_gid = mixer_sid[mixer_grpidx[mixer_focus_elem]]; focus_type = mixer_type[mixer_focus_elem]; } while (1) { - bzero(&groups, sizeof(groups)); - if (snd_mixer_groups(mixer_handle, &groups) < 0) - mixer_abort (ERR_FCN, "snd_mixer_groups"); - mixer_n_groups = groups.groups_over; - if (mixer_n_groups > 0) { - groups.groups_size = mixer_n_groups; - groups.pgroups = (snd_mixer_gid_t *)malloc(sizeof(snd_mixer_gid_t) * mixer_n_groups); - if (groups.pgroups == NULL) - mixer_abort (ERR_FCN, "malloc"); - groups.groups_over = 0; - groups.groups = 0; - if (snd_mixer_groups(mixer_handle, &groups) < 0) - mixer_abort (ERR_FCN, "snd_mixer_groups"); - if (groups.groups_over > 0) { - free(groups.pgroups); + bzero(&scontrols, sizeof(scontrols)); + if ((err = snd_mixer_simple_control_list(mixer_handle, &scontrols)) < 0) + mixer_abort (ERR_FCN, "snd_mixer_simple_control_list", err); + mixer_n_scontrols = scontrols.controls; + fprintf(stderr, "controls = %i\n", scontrols.controls); + if (mixer_n_scontrols > 0) { + scontrols.controls_request = mixer_n_scontrols; + scontrols.pids = (snd_mixer_sid_t *)malloc(sizeof(snd_mixer_sid_t) * mixer_n_scontrols); + if (scontrols.pids == NULL) + mixer_abort (ERR_FCN, "malloc", 0); + scontrols.controls_offset = 0; + scontrols.controls_count = 0; + if ((err = snd_mixer_simple_control_list(mixer_handle, &scontrols)) < 0) + mixer_abort (ERR_FCN, "snd_mixer_simple_control_list", err); + if (scontrols.controls > scontrols.controls_count) { + free(scontrols.pids); continue; } } - if (mixer_gid) - free(mixer_gid); - mixer_gid = groups.pgroups; + if (mixer_sid) + free(mixer_sid); + mixer_sid = scontrols.pids; + fprintf(stderr, "mixer_sid = 0x%x\n", (int)mixer_sid); break; } - snd_mixer_sort_gid_table(mixer_gid, mixer_n_groups, snd_mixer_default_weights); +#if 0 + snd_mixer_sort_gid_table(mixer_sid, mixer_n_scontrols, snd_mixer_default_weights); +#endif mixer_n_elems = 0; - for (idx = 0; idx < mixer_n_groups; idx++) { - snd_mixer_group_t group; - bzero(&group, sizeof(group)); - group.gid = mixer_gid[idx]; - if (snd_mixer_group_read(mixer_handle, &group) < 0) - CHECK_ABORT (ERR_FCN, "snd_mixer_group_read()"); + for (idx = 0; idx < mixer_n_scontrols; idx++) { + snd_mixer_simple_control_t scontrol; + bzero(&scontrol, sizeof(scontrol)); + scontrol.sid = mixer_sid[idx]; + if ((err = snd_mixer_simple_control_read(mixer_handle, &scontrol)) < 0) + CHECK_ABORT (ERR_FCN, "snd_mixer_simple_control_read()", 0); + fprintf(stderr, "scontrol.channels = 0x%x\n", scontrol.channels); for (i = 0; i < MIXER_ELEM_END; i++) { - if (group.channels & mixer_elem_mask[i]) + if (scontrol.channels & mixer_elem_mask[i]) mixer_n_elems++; } } @@ -1255,21 +1271,21 @@ mixer_reinit (void) free(mixer_type); mixer_type = (int *)malloc(sizeof(int) * mixer_n_elems); if (mixer_type == NULL) - mixer_abort(ERR_FCN, "malloc"); + mixer_abort(ERR_FCN, "malloc", 0); if (mixer_grpidx) free(mixer_grpidx); mixer_grpidx = (int *)malloc(sizeof(int) * mixer_n_elems); if (mixer_grpidx == NULL) - mixer_abort(ERR_FCN, "malloc"); + mixer_abort(ERR_FCN, "malloc", 0); elem_index = 0; - for (idx = 0; idx < mixer_n_groups; idx++) { - snd_mixer_group_t group; - bzero(&group, sizeof(group)); - group.gid = mixer_gid[idx]; - if (snd_mixer_group_read(mixer_handle, &group) < 0) - CHECK_ABORT (ERR_FCN, "snd_mixer_group_read()"); + for (idx = 0; idx < mixer_n_scontrols; idx++) { + snd_mixer_simple_control_t scontrol; + bzero(&scontrol, sizeof(scontrol)); + scontrol.sid = mixer_sid[idx]; + if ((err = snd_mixer_simple_control_read(mixer_handle, &scontrol)) < 0) + CHECK_ABORT (ERR_FCN, "snd_mixer_simple_control_read()", err); for (i = 0; i < MIXER_ELEM_END; i++) { - if (group.channels & mixer_elem_mask[i]) { + if (scontrol.channels & mixer_elem_mask[i]) { mixer_grpidx[elem_index] = idx; mixer_type[elem_index] = i; elem_index++; @@ -1282,7 +1298,7 @@ mixer_reinit (void) mixer_focus_elem = 0; if (focus_type >= 0) { for (elem_index = 0; elem_index < mixer_n_elems; elem_index++) { - if (!memcmp(&focus_gid, &mixer_gid[mixer_grpidx[elem_index]], sizeof(focus_gid)) && + if (!memcmp(&focus_gid, &mixer_sid[mixer_grpidx[elem_index]], sizeof(focus_gid)) && mixer_type[elem_index] == focus_type) { mixer_focus_elem = elem_index; break; @@ -1371,7 +1387,7 @@ mixer_resize (void) } static void -mixer_callback_rebuild (void *private_data) +mixer_callback_rebuild (snd_mixer_t *handle, void *private_data) { /* we don't actually need to update the individual channels because * we redraw the whole screen upon every main iteration anyways. @@ -1380,7 +1396,7 @@ mixer_callback_rebuild (void *private_data) } static void -mixer_callback_group (void *private_data, int cmd, snd_mixer_gid_t *gid) +mixer_callback_scontrol (snd_mixer_t *handle, void *private_data, snd_mixer_sid_t *gid) { mixer_reinit (); } @@ -1407,7 +1423,7 @@ static int mixer_iteration (void) { struct timeval delay = { 0, }; - snd_mixer_callbacks_t callbacks = { 0, }; + snd_mixer_simple_callbacks_t callbacks = { 0, }; int mixer_fd; fd_set rfds; int finished = 0; @@ -1415,7 +1431,10 @@ mixer_iteration (void) int old_view; callbacks.rebuild = mixer_callback_rebuild; - callbacks.group = mixer_callback_group; + callbacks.value = mixer_callback_scontrol; + callbacks.change = mixer_callback_scontrol; + callbacks.add = mixer_callback_scontrol; + callbacks.remove = mixer_callback_scontrol; /* setup for select on stdin and the mixer fd */ mixer_fd = snd_mixer_file_descriptor (mixer_handle); @@ -1438,7 +1457,7 @@ mixer_iteration (void) mixer_resize (); if (FD_ISSET (mixer_fd, &rfds)) - snd_mixer_read (mixer_handle, &callbacks); + snd_mixer_simple_read (mixer_handle, &callbacks); if (FD_ISSET (fileno (stdin), &rfds)) key = getch (); @@ -1676,7 +1695,7 @@ static void mixer_signal_handler (int signal) { if (signal != SIGSEGV) - mixer_abort (ERR_SIGNAL, sys_siglist[signal]); + mixer_abort (ERR_SIGNAL, sys_siglist[signal], 0); else { fprintf (stderr, "\nSegmentation fault.\n"); @@ -1694,23 +1713,20 @@ main (int argc, */ do { - opt = getopt (argc, argv, "c:m:shg"); + opt = getopt (argc, argv, "c:shg"); switch (opt) { case '?': case 'h': fprintf (stderr, "%s %s\n", PRGNAME_UPPER, VERSION); - fprintf (stderr, "Usage: %s [-c ] [-m ] [-z]\n", PRGNAME, snd_cards ()); - mixer_abort (ERR_NONE, ""); + fprintf (stderr, "Usage: %s [-c ] [-z]\n", PRGNAME, snd_cards () - 1); + mixer_abort (ERR_NONE, "", 0); case 'c': card_id = snd_card_name (optarg); break; case 'g': mixer_do_color = !mixer_do_color; break; - case 'm': - mixer_id = CLAMP (optarg[0], '0', '1') - '0'; - break; case 's': mixer_minimize = 1; break; @@ -1766,5 +1782,5 @@ main (int argc, } while (!mixer_iteration ()); - mixer_abort (ERR_NONE, ""); + mixer_abort (ERR_NONE, "", 0); }; diff --git a/amixer/amixer.c b/amixer/amixer.c index b82ea3b..e03829d 100644 --- a/amixer/amixer.c +++ b/amixer/amixer.c @@ -1,6 +1,6 @@ /* * ALSA command line mixer utility - * Copyright (c) 1999 by Jaroslav Kysela + * Copyright (c) 1999-2000 by Jaroslav Kysela * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,47 +30,14 @@ #define HELPID_HELP 1000 #define HELPID_CARD 1001 -#define HELPID_DEVICE 1002 -#define HELPID_QUIET 1003 -#define HELPID_DEBUG 1004 -#define HELPID_VERSION 1005 +#define HELPID_QUIET 1002 +#define HELPID_DEBUG 1003 +#define HELPID_VERSION 1004 int quiet = 0; int debugflag = 0; int card; -int device; -int group_contents_is_on = 0; - -struct mixer_types { - int type; - char *name; -}; - -struct mixer_types mixer_types[] = { - { SND_MIXER_ETYPE_INPUT, "Input" }, - { SND_MIXER_ETYPE_OUTPUT, "Output" }, - { SND_MIXER_ETYPE_CAPTURE1, "Capture Stream" }, - { SND_MIXER_ETYPE_CAPTURE2, "Capture Subchannel" }, - { SND_MIXER_ETYPE_PLAYBACK1, "Playback Stream" }, - { SND_MIXER_ETYPE_PLAYBACK2, "Playback Subchannel" }, - { SND_MIXER_ETYPE_ADC, "ADC" }, - { SND_MIXER_ETYPE_DAC, "DAC" }, - { SND_MIXER_ETYPE_SWITCH1, "Switch1" }, - { SND_MIXER_ETYPE_SWITCH2, "Switch2" }, - { SND_MIXER_ETYPE_SWITCH3, "Switch3" }, - { SND_MIXER_ETYPE_VOLUME1, "Volume1" }, - { SND_MIXER_ETYPE_VOLUME2, "Volume2" }, - { SND_MIXER_ETYPE_ACCU1, "Accumulator1" }, - { SND_MIXER_ETYPE_ACCU2, "Accumulator2" }, - { SND_MIXER_ETYPE_ACCU3, "Accumulator3" }, - { SND_MIXER_ETYPE_MUX1, "Mux1" }, - { SND_MIXER_ETYPE_MUX2, "Mux2" }, - { SND_MIXER_ETYPE_TONE_CONTROL1, "ToneControl1" }, - { SND_MIXER_ETYPE_EQUALIZER1, "Equalizer1" }, - { SND_MIXER_ETYPE_3D_EFFECT1, "3D-Effect1" }, - { SND_MIXER_ETYPE_PRE_EFFECT1, "PredefinedEffect1" }, - { -1, NULL } -}; +int scontrol_contents_is_on = 0; void error(const char *fmt,...) { @@ -89,11 +56,9 @@ static void help(void) printf("\nAvailable options:\n"); printf(" -h,--help this help\n"); printf(" -c,--card # use a card number (0-%i) or the card name, default %i\n", snd_cards() - 1, card); - printf(" -d,--device # use a device number, default %i\n", device); printf(" -D,--debug debug mode\n"); printf(" -v,--version print version of this program\n"); printf("\nAvailable commands:\n"); - printf(" info show useful information for the selected mixer\n"); printf(" groups show all mixer groups\n"); printf(" gcontents show contents of all mixer groups (default command)\n"); printf(" set G P set group contents for one mixer group\n"); @@ -107,22 +72,40 @@ static void help(void) int info(void) { int err; - snd_mixer_t *handle; - snd_mixer_info_t info; + snd_ctl_t *handle; + snd_mixer_t *mhandle; + snd_ctl_hw_info_t info; + snd_control_list_t clist; + snd_mixer_simple_control_list_t slist; - if ((err = snd_mixer_open(&handle, card, device)) < 0) { - error("Mixer %i/%i open error: %s", card, device, snd_strerror(err)); + if ((err = snd_ctl_open(&handle, card)) < 0) { + error("Control device %i open error: %s", card, snd_strerror(err)); return -1; } - if ((err = snd_mixer_info(handle, &info)) < 0) { - error("Mixer %i/%i info error: %s", card, device, snd_strerror(err)); + if ((err = snd_ctl_hw_info(handle, &info)) < 0) { + error("Control device %i hw info error: %s", card, snd_strerror(err)); return -1; } - printf("Mixer '%s/%s':\n", info.id, info.name); - printf(" Elements : %i\n", info.elements); - printf(" Groups : %i\n", info.groups); - printf(" Attribute : 0x%x\n", info.attrib); - snd_mixer_close(handle); + printf("Card '%s/%s':\n", info.id, info.longname); + printf(" Mixer ID : '%s'\n", info.mixerid); + printf(" Mixer name : '%s'\n", info.mixername); + memset(&clist, 0, sizeof(clist)); + if ((err = snd_ctl_clist(handle, &clist)) < 0) { + error("snd_ctl_clist failure: %s", snd_strerror(err)); + } else { + printf(" Controls : %i\n", clist.controls); + } + snd_ctl_close(handle); + if ((err = snd_mixer_open(&mhandle, card)) < 0) { + error("Mixer device %i open error: %s", card, snd_strerror(err)); + return -1; + } + if ((err = snd_mixer_simple_control_list(mhandle, &slist)) < 0) { + error("snd_mixer_simple_control_list failure: %s\n", snd_strerror(err)); + } else { + printf(" Simple ctrls : %i\n", clist.controls); + } + snd_mixer_close(mhandle); return 0; } @@ -135,18 +118,6 @@ static const char *element_name(const char *name) return res; } -static const char *element_type(int type) -{ - int idx; - static char str[32]; - - for (idx = 0; mixer_types[idx].type >= 0; idx++) - if (type == mixer_types[idx].type) - return mixer_types[idx].name; - sprintf(str, "Type%i", type); - return str; -} - static int check_range(int val, int min, int max) { if (val < min) @@ -302,489 +273,9 @@ static int get_volume_simple(char **ptr, int min, int max, int orig) return tmp1; } -int show_element(void *handle, snd_mixer_eid_t *eid, const char *space) -{ - int err, idx; - snd_mixer_routes_t routes; - snd_mixer_eid_t *element; - - bzero(&routes, sizeof(routes)); - routes.eid = *eid; - if ((err = snd_mixer_routes(handle, &routes)) < 0) { - error("Mixer %i/%i route error: %s", card, device, snd_strerror(err)); - return -1; - } - if (!routes.routes_over) - return 0; - routes.proutes = (snd_mixer_eid_t *)malloc(routes.routes_over * sizeof(snd_mixer_eid_t)); - if (!routes.proutes) { - error("Not enough memory..."); - return -1; - } - routes.routes_size = routes.routes_over; - routes.routes = routes.routes_over = 0; - if ((err = snd_mixer_routes(handle, &routes)) < 0) { - error("Mixer %i/%i group (2) error: %s", card, device, snd_strerror(err)); - return -1; - } - for (idx = 0; idx < routes.routes; idx++) { - element = &routes.proutes[idx]; - printf("%sRoute to element '%s',%i,%s\n", space, element_name(element->name), element->index, element_type(element->type)); - } - free(routes.proutes); - return 0; -} - -static const char *speaker_position(int position) -{ - static char str[32]; - - switch (position) { - case SND_MIXER_CHANNEL_UNKNOWN: - return "Unknown"; - case SND_MIXER_CHANNEL_MONO: - return "Mono"; - case SND_MIXER_CHANNEL_LEFT: - return "Left"; - case SND_MIXER_CHANNEL_RIGHT: - return "Right"; - case SND_MIXER_CHANNEL_CENTER: - return "Center"; - case SND_MIXER_CHANNEL_REAR_LEFT: - return "Rear-Left"; - case SND_MIXER_CHANNEL_REAR_RIGHT: - return "Rear-Right"; - case SND_MIXER_CHANNEL_WOOFER: - return "Woofer"; - default: - sprintf(str, "Speaker%i", position); - return str; - } -} - -int show_mux1_info(void *handle, snd_mixer_element_info_t *info, const char *space) -{ - int idx, idx1, err; - snd_mixer_elements_t elements; - snd_mixer_routes_t routes; - snd_mixer_eid_t *element; - - printf("%sMux supports none input: %s\n", space, (info->data.mux1.attrib & SND_MIXER_MUX1_NONE) ? "YES" : "NO"); - bzero(&elements, sizeof(elements)); - if ((err = snd_mixer_elements(handle, &elements)) < 0) { - error("Mixer %i/%i elements error: %s", card, device, snd_strerror(err)); - return -1; - } - elements.pelements = (snd_mixer_eid_t *)malloc(elements.elements_over * sizeof(snd_mixer_eid_t)); - if (!elements.pelements) { - error("Not enough memory"); - return -1; - } - elements.elements_size = elements.elements_over; - elements.elements_over = elements.elements = 0; - if ((err = snd_mixer_elements(handle, &elements)) < 0) { - error("Mixer %i/%i elements (2) error: %s", card, device, snd_strerror(err)); - return -1; - } - for (idx = 0; idx < elements.elements; idx++) { - bzero(&routes, sizeof(routes)); - routes.eid = elements.pelements[idx]; - if ((err = snd_mixer_routes(handle, &routes)) < 0) { - error("Mixer %i/%i route error: %s", card, device, snd_strerror(err)); - free(elements.pelements); - return -1; - } - if (!routes.routes_over) - continue; - routes.proutes = (snd_mixer_eid_t *)malloc(routes.routes_over * sizeof(snd_mixer_eid_t)); - if (!routes.proutes) { - error("Not enough memory..."); - free(elements.pelements); - return -1; - } - routes.routes_size = routes.routes_over; - routes.routes = routes.routes_over = 0; - if ((err = snd_mixer_routes(handle, &routes)) < 0) { - error("Mixer %i/%i group (2) error: %s", card, device, snd_strerror(err)); - free(elements.pelements); - return -1; - } - for (idx1 = 0; idx1 < routes.routes; idx1++) { - element = &routes.proutes[idx1]; - if (!strncmp(element->name, info->eid.name, sizeof(element->name)) && - element->index == info->eid.index && - element->type == info->eid.type) - printf("%sInput element '%s',%i,%s\n", space, element_name(routes.eid.name), routes.eid.index, element_type(routes.eid.type)); - } - free(routes.proutes); - } - free(elements.pelements); - return 0; -} - -int show_mux2_info(void *handle, snd_mixer_element_info_t *info, const char *space) -{ - int idx, idx1, err; - snd_mixer_elements_t elements; - snd_mixer_routes_t routes; - snd_mixer_eid_t *element; - - printf("%sMux supports none input: %s\n", space, (info->data.mux2.attrib & SND_MIXER_MUX2_NONE) ? "YES" : "NO"); - bzero(&elements, sizeof(elements)); - if ((err = snd_mixer_elements(handle, &elements)) < 0) { - error("Mixer %i/%i elements error: %s", card, device, snd_strerror(err)); - return -1; - } - elements.pelements = (snd_mixer_eid_t *)malloc(elements.elements_over * sizeof(snd_mixer_eid_t)); - if (!elements.pelements) { - error("Not enough memory"); - return -1; - } - elements.elements_size = elements.elements_over; - elements.elements_over = elements.elements = 0; - if ((err = snd_mixer_elements(handle, &elements)) < 0) { - error("Mixer %i/%i elements (2) error: %s", card, device, snd_strerror(err)); - return -1; - } - for (idx = 0; idx < elements.elements; idx++) { - bzero(&routes, sizeof(routes)); - routes.eid = elements.pelements[idx]; - if ((err = snd_mixer_routes(handle, &routes)) < 0) { - error("Mixer %i/%i route error: %s", card, device, snd_strerror(err)); - free(elements.pelements); - return -1; - } - if (!routes.routes_over) - continue; - routes.proutes = (snd_mixer_eid_t *)malloc(routes.routes_over * sizeof(snd_mixer_eid_t)); - if (!routes.proutes) { - error("Not enough memory..."); - free(elements.pelements); - return -1; - } - routes.routes_size = routes.routes_over; - routes.routes = routes.routes_over = 0; - if ((err = snd_mixer_routes(handle, &routes)) < 0) { - error("Mixer %i/%i group (2) error: %s", card, device, snd_strerror(err)); - free(elements.pelements); - return -1; - } - for (idx1 = 0; idx1 < routes.routes; idx1++) { - element = &routes.proutes[idx1]; - if (!strncmp(element->name, info->eid.name, sizeof(element->name)) && - element->index == info->eid.index && - element->type == info->eid.type) - printf("%sInput element '%s',%i,%s\n", space, element_name(routes.eid.name), routes.eid.index, element_type(routes.eid.type)); - } - free(routes.proutes); - } - free(elements.pelements); - return 0; -} - -int show_element_info(void *handle, snd_mixer_eid_t *eid, const char *space) -{ - int err, idx; - snd_mixer_element_info_t info; - - if (snd_mixer_element_has_info(eid) != 1) - return 0; - bzero(&info, sizeof(info)); - info.eid = *eid; - if ((err = snd_mixer_element_info_build(handle, &info)) < 0) { - error("Mixer %i/%i info error: %s", card, device, snd_strerror(err)); - return -1; - } - printf("%sInput/output channels: %i/%i\n", space, info.input_channels, info.output_channels); - switch (info.eid.type) { - case SND_MIXER_ETYPE_INPUT: - case SND_MIXER_ETYPE_OUTPUT: - if (info.data.io.attrib) { - printf("%sAttributes%s\n", space, - info.data.io.attrib & SND_MIXER_EIO_DIGITAL ? " digital" : ""); - } - for (idx = 0; idx < info.data.io.channels; idx++) { - printf("%sChannel %i: %s\n", - space, - idx, - speaker_position(info.data.io.pchannels[idx].position)); - } - break; - case SND_MIXER_ETYPE_CAPTURE1: - case SND_MIXER_ETYPE_PLAYBACK1: - for (idx = 0; idx < info.data.pcm1.devices; idx++) { - printf("%sPCM device %i: %i\n", - space, - idx, - info.data.pcm1.pdevices[idx]); - } - break; - case SND_MIXER_ETYPE_CAPTURE2: - case SND_MIXER_ETYPE_PLAYBACK2: - printf("%sPCM subdevice %i %i\n", - space, - info.data.pcm2.device, - info.data.pcm2.subdevice); - break; - case SND_MIXER_ETYPE_ADC: - case SND_MIXER_ETYPE_DAC: - printf("%sResolution %i-bits\n", space, info.data.converter.resolution); - break; - case SND_MIXER_ETYPE_SWITCH3: - printf("%sSwitch type is ", space); - switch (info.data.switch3.type) { - case SND_MIXER_SWITCH3_FULL_FEATURED: - printf("full featured\n"); - break; - case SND_MIXER_SWITCH3_ALWAYS_DESTINATION: - printf("always destination\n"); - break; - case SND_MIXER_SWITCH3_ONE_DESTINATION: - printf("one destination\n"); - break; - case SND_MIXER_SWITCH3_ALWAYS_ONE_DESTINATION: - printf("always one destination\n"); - break; - default: - printf("unknown %i\n", info.data.switch3.type); - } - break; - case SND_MIXER_ETYPE_VOLUME1: - for (idx = 0; idx < info.data.volume1.range; idx++) { - struct snd_mixer_element_volume1_range *range = &info.data.volume1.prange[idx]; - printf("%sChannel %i: Min %i (%i.%02idB), Max %i (%i.%02idB)\n", - space, - idx, - range->min, range->min_dB / 100, abs(range->min_dB % 100), - range->max, range->max_dB / 100, abs(range->max_dB % 100)); - } - break; - case SND_MIXER_ETYPE_ACCU1: - printf("%sAttenuation %i.%02idB\n", space, - info.data.accu1.attenuation / 100, - abs(info.data.accu1.attenuation % 100)); - break; - case SND_MIXER_ETYPE_ACCU2: - printf("%sAttenuation %i.%02idB\n", space, - info.data.accu2.attenuation / 100, - abs(info.data.accu1.attenuation % 100)); - break; - case SND_MIXER_ETYPE_ACCU3: - for (idx = 0; idx < info.data.accu3.range; idx++) { - struct snd_mixer_element_accu3_range *range = &info.data.accu3.prange[idx]; - printf("%sChannel %i: Min %i (%i.%02idB), Max %i (%i.%02idB)\n", - space, - idx, - range->min, range->min_dB / 100, abs(range->min_dB % 100), - range->max, range->max_dB / 100, abs(range->max_dB % 100)); - } - break; - case SND_MIXER_ETYPE_MUX1: - show_mux1_info(handle, &info, space); - break; - case SND_MIXER_ETYPE_MUX2: - show_mux2_info(handle, &info, space); - break; - case SND_MIXER_ETYPE_TONE_CONTROL1: - if (info.data.tc1.tc & SND_MIXER_TC1_SW) - printf("%sOn/Off switch\n", space); - if (info.data.tc1.tc & SND_MIXER_TC1_BASS) - printf("%sBass control: Min %i (%i.%02idB), Max %i (%i.%02idB)\n", - space, - info.data.tc1.min_bass, - info.data.tc1.min_bass_dB / 100, - abs(info.data.tc1.min_bass_dB % 100), - info.data.tc1.max_bass, - info.data.tc1.max_bass_dB / 100, - abs(info.data.tc1.max_bass_dB % 100)); - if (info.data.tc1.tc & SND_MIXER_TC1_TREBLE) - printf("%sTreble control: Min %i (%i.%02idB), Max %i (%i.%02idB)\n", - space, - info.data.tc1.min_treble, - info.data.tc1.min_treble_dB / 100, - abs(info.data.tc1.min_treble_dB % 100), - info.data.tc1.max_treble, - info.data.tc1.max_treble_dB / 100, - abs(info.data.tc1.max_treble_dB % 100)); - break; - case SND_MIXER_ETYPE_3D_EFFECT1: - if (info.data.teffect1.effect & SND_MIXER_EFF1_SW) - printf("%sOn/Off switch\n", space); - if (info.data.teffect1.effect & SND_MIXER_EFF1_MONO_SW) - printf("%sMono processing switch\n", space); - if (info.data.teffect1.effect & SND_MIXER_EFF1_WIDE) - printf("%sWide: Min %i, Max %i\n", space, - info.data.teffect1.min_wide, - info.data.teffect1.max_wide); - if (info.data.teffect1.effect & SND_MIXER_EFF1_VOLUME) - printf("%sVolume: Min %i, Max %i\n", space, - info.data.teffect1.min_volume, - info.data.teffect1.max_volume); - if (info.data.teffect1.effect & SND_MIXER_EFF1_CENTER) - printf("%sCenter: Min %i, Max %i\n", space, - info.data.teffect1.min_center, - info.data.teffect1.max_center); - if (info.data.teffect1.effect & SND_MIXER_EFF1_SPACE) - printf("%sSpace: Min %i, Max %i\n", space, - info.data.teffect1.min_space, - info.data.teffect1.max_space); - if (info.data.teffect1.effect & SND_MIXER_EFF1_DEPTH) - printf("%sDepth: Min %i, Max %i\n", space, - info.data.teffect1.min_depth, - info.data.teffect1.max_depth); - if (info.data.teffect1.effect & SND_MIXER_EFF1_DELAY) - printf("%sDelay: Min %i, Max %i\n", space, - info.data.teffect1.min_delay, - info.data.teffect1.max_delay); - if (info.data.teffect1.effect & SND_MIXER_EFF1_FEEDBACK) - printf("%sFeedback: Min %i, Max %i\n", space, - info.data.teffect1.min_feedback, - info.data.teffect1.max_feedback); - if (info.data.teffect1.effect & SND_MIXER_EFF1_DEPTH_REAR) - printf("%sDepth rear: Min %i, Max %i\n", space, - info.data.teffect1.min_depth_rear, - info.data.teffect1.max_depth_rear); - break; - default: - printf("%sInfo handler for type %i is not available\n", space, info.eid.type); - } - snd_mixer_element_info_free(&info); - return 0; -} - -int show_element_contents(void *handle, snd_mixer_eid_t *eid, const char *space) -{ - int err, idx; - snd_mixer_element_t element; - snd_mixer_element_info_t info; - - if (snd_mixer_element_has_control(eid) != 1) - return 0; - bzero(&element, sizeof(element)); - bzero(&info, sizeof(info)); - element.eid = info.eid = *eid; - if ((err = snd_mixer_element_build(handle, &element)) < 0) { - error("Mixer %i/%i element error: %s", card, device, snd_strerror(err)); - return -1; - } - if (snd_mixer_element_has_info(eid) == 1) { - if ((err = snd_mixer_element_info_build(handle, &info)) < 0) { - error("Mixer %i/%i element error: %s", card, device, snd_strerror(err)); - return -1; - } - } - switch (element.eid.type) { - case SND_MIXER_ETYPE_SWITCH1: - for (idx = 0; idx < element.data.switch1.sw; idx++) { - int val = snd_mixer_get_bit(element.data.switch1.psw, idx); - printf("%sChannel %i: Switch is %s\n", space, idx, val ? "ON" : "OFF"); - } - break; - case SND_MIXER_ETYPE_SWITCH2: - printf("%sSwitch is %s\n", space, element.data.switch2.sw ? "ON" : "OFF"); - break; - case SND_MIXER_ETYPE_SWITCH3: - if (element.data.switch3.rsw != info.input_channels * info.output_channels) { - error("Switch3 !!!\n"); - goto __end; - } - for (idx = 0; idx < element.data.switch3.rsw; idx++) { - int val = snd_mixer_get_bit(element.data.switch3.prsw, idx); - printf("%sInput <%i> Output <%i>: Switch is %s\n", - space, - idx / info.input_channels, - idx % info.output_channels, - val ? "ON" : "OFF"); - } - break; - case SND_MIXER_ETYPE_VOLUME1: - for (idx = 0; idx < element.data.volume1.channels; idx++) { - int val = element.data.volume1.pchannels[idx]; - printf("%sChannel %i: Value %s\n", space, idx, - get_percent1(val, info.data.volume1.prange[idx].min, - info.data.volume1.prange[idx].max, - info.data.volume1.prange[idx].min_dB, - info.data.volume1.prange[idx].max_dB)); - } - break; - case SND_MIXER_ETYPE_ACCU3: - for (idx = 0; idx < element.data.accu3.channels; idx++) { - int val = element.data.accu3.pchannels[idx]; - printf("%sChannel %i: Value %s\n", space, idx, - get_percent1(val, info.data.accu3.prange[idx].min, - info.data.accu3.prange[idx].max, - info.data.accu3.prange[idx].min_dB, - info.data.accu3.prange[idx].max_dB)); - } - break; - case SND_MIXER_ETYPE_MUX1: - for (idx = 0; idx < element.data.mux1.sel; idx++) { - snd_mixer_eid_t *eid = &element.data.mux1.psel[idx]; - printf("%sChannel %i: Element ", space, idx); - if (eid->name[0] == '\0') { - printf("NONE\n"); - } else { - printf("'%s',%i,%i\n", - element_name(eid->name), - eid->index, eid->type); - } - } - break; - case SND_MIXER_ETYPE_MUX2: - { - printf("%sAll channels: Element ", space); - if (element.data.mux2.sel.name[0] == '\0') { - printf("NONE\n"); - } else { - printf("'%s',%i,%i\n", - element_name(element.data.mux2.sel.name), - element.data.mux2.sel.index, - element.data.mux2.sel.type); - } - } - break; - case SND_MIXER_ETYPE_TONE_CONTROL1: - if (element.data.tc1.tc & SND_MIXER_TC1_SW) - printf("%sOn/Off switch is %s\n", space, element.data.tc1.sw ? "ON" : "OFF"); - if (element.data.tc1.tc & SND_MIXER_TC1_BASS) - printf("%sBass: %s\n", space, get_percent1(element.data.tc1.bass, info.data.tc1.min_bass, info.data.tc1.max_bass, info.data.tc1.min_bass_dB, info.data.tc1.max_bass_dB)); - if (element.data.tc1.tc & SND_MIXER_TC1_TREBLE) - printf("%sTreble: %s\n", space, get_percent1(element.data.tc1.treble, info.data.tc1.min_treble, info.data.tc1.max_treble, info.data.tc1.min_treble_dB, info.data.tc1.max_treble_dB)); - break; - case SND_MIXER_ETYPE_3D_EFFECT1: - if (element.data.teffect1.effect & SND_MIXER_EFF1_SW) - printf("%sOn/Off switch is %s\n", space, element.data.teffect1.sw ? "ON" : "OFF"); - if (element.data.teffect1.effect & SND_MIXER_EFF1_MONO_SW) - printf("%sMono processing switch is %s\n", space, element.data.teffect1.mono_sw ? "ON" : "OFF"); - if (element.data.teffect1.effect & SND_MIXER_EFF1_WIDE) - printf("%sWide: %s\n", space, get_percent(element.data.teffect1.wide, info.data.teffect1.min_wide, info.data.teffect1.max_wide)); - if (element.data.teffect1.effect & SND_MIXER_EFF1_VOLUME) - printf("%sVolume: %s\n", space, get_percent(element.data.teffect1.volume, info.data.teffect1.min_volume, info.data.teffect1.max_volume)); - if (element.data.teffect1.effect & SND_MIXER_EFF1_CENTER) - printf("%sCenter: %s\n", space, get_percent(element.data.teffect1.center, info.data.teffect1.min_center, info.data.teffect1.max_center)); - if (element.data.teffect1.effect & SND_MIXER_EFF1_SPACE) - printf("%sSpace: %s\n", space, get_percent(element.data.teffect1.space, info.data.teffect1.min_space, info.data.teffect1.max_space)); - if (element.data.teffect1.effect & SND_MIXER_EFF1_DEPTH) - printf("%sDepth: %s\n", space, get_percent(element.data.teffect1.depth, info.data.teffect1.min_depth, info.data.teffect1.max_depth)); - if (element.data.teffect1.effect & SND_MIXER_EFF1_DELAY) - printf("%sDelay: %s\n", space, get_percent(element.data.teffect1.delay, info.data.teffect1.min_delay, info.data.teffect1.max_delay)); - if (element.data.teffect1.effect & SND_MIXER_EFF1_FEEDBACK) - printf("%sFeedback: %s\n", space, get_percent(element.data.teffect1.feedback, info.data.teffect1.min_feedback, info.data.teffect1.max_feedback)); - if (element.data.teffect1.effect & SND_MIXER_EFF1_DEPTH_REAR) - printf("%sDepth rear: %s\n", space, get_percent(element.data.teffect1.depth_rear, info.data.teffect1.min_depth_rear, info.data.teffect1.max_depth_rear)); - break; - default: - printf("%sRead handler for type %i is not available\n", space, element.eid.type); - } - __end: - snd_mixer_element_free(&element); - if (snd_mixer_element_has_info(eid)) - snd_mixer_element_info_free(&info); - return 0; -} - -int elements(void) +int controls(void) { +#if 0 int err, idx; snd_mixer_t *handle; snd_mixer_elements_t elements; @@ -818,11 +309,13 @@ int elements(void) } free(elements.pelements); snd_mixer_close(handle); +#endif return 0; } -int elements_contents(void) +int controls_contents(void) { +#if 0 int err, idx; snd_mixer_t *handle; snd_mixer_elements_t elements; @@ -856,6 +349,7 @@ int elements_contents(void) } free(elements.pelements); snd_mixer_close(handle); +#endif return 0; } @@ -868,193 +362,124 @@ static const char *group_name(const char *name) return res; } -int show_group(void *handle, snd_mixer_gid_t *gid, const char *space) +int show_group(void *handle, snd_mixer_sid_t *sid, const char *space) { - int err, idx, chn; - snd_mixer_group_t group; - snd_mixer_eid_t *element; + int err, chn; + snd_mixer_simple_control_t scontrol; - bzero(&group, sizeof(group)); - group.gid = *gid; - if ((err = snd_mixer_group_read(handle, &group)) < 0) { - error("Mixer %i/%i group error: %s", card, device, snd_strerror(err)); + bzero(&scontrol, sizeof(scontrol)); + scontrol.sid = *sid; + if ((err = snd_mixer_simple_control_read(handle, &scontrol)) < 0) { + error("Mixer %i simple_control error: %s", card, snd_strerror(err)); return -1; } - if (group_contents_is_on && group.channels) { + if (scontrol_contents_is_on && scontrol.channels) { printf("%sCapabilities:", space); - if (group.caps & SND_MIXER_GRPCAP_VOLUME) + if (scontrol.caps & SND_MIXER_SCTCAP_VOLUME) printf(" volume"); - if (group.caps & SND_MIXER_GRPCAP_MUTE) + if (scontrol.caps & SND_MIXER_SCTCAP_MUTE) printf(" mute"); - if (group.caps & SND_MIXER_GRPCAP_JOINTLY_MUTE) + if (scontrol.caps & SND_MIXER_SCTCAP_JOINTLY_MUTE) printf(" jointly-mute"); - if (group.caps & SND_MIXER_GRPCAP_CAPTURE) { + if (scontrol.caps & SND_MIXER_SCTCAP_CAPTURE) { printf(" capture"); } else { - group.capture = 0; + scontrol.capture = 0; } - if (group.caps & SND_MIXER_GRPCAP_JOINTLY_CAPTURE) + if (scontrol.caps & SND_MIXER_SCTCAP_JOINTLY_CAPTURE) printf(" jointly-capture"); - if (group.caps & SND_MIXER_GRPCAP_EXCL_CAPTURE) + if (scontrol.caps & SND_MIXER_SCTCAP_EXCL_CAPTURE) printf(" exclusive-capture"); printf("\n"); - if ((group.caps & SND_MIXER_GRPCAP_CAPTURE) && - (group.caps & SND_MIXER_GRPCAP_EXCL_CAPTURE)) - printf("%sCapture exclusive group: %i\n", space, group.capture_group); + if ((scontrol.caps & SND_MIXER_SCTCAP_CAPTURE) && + (scontrol.caps & SND_MIXER_SCTCAP_EXCL_CAPTURE)) + printf("%sCapture exclusive scontrol: %i\n", space, scontrol.capture_group); printf("%sChannels: ", space); - if (group.channels == SND_MIXER_CHN_MASK_MONO) { + if (scontrol.channels == SND_MIXER_CHN_MASK_MONO) { printf("Mono"); } else { for (chn = 0; chn <= SND_MIXER_CHN_LAST; chn++) { - if (!(group.channels & (1<name), element->index, element_type(element->type)); - } - free(group.pelements); return 0; } -int groups(void) +int scontrols(void) { +#if 0 int err, idx; snd_mixer_t *handle; - snd_mixer_groups_t groups; - snd_mixer_gid_t *group; + snd_mixer_scontrols_t scontrols; + snd_mixer_sid_t *scontrol; if ((err = snd_mixer_open(&handle, card, device)) < 0) { error("Mixer %i/%i open error: %s", card, device, snd_strerror(err)); return -1; } - bzero(&groups, sizeof(groups)); - if ((err = snd_mixer_groups(handle, &groups)) < 0) { - error("Mixer %i/%i groups error: %s", card, device, snd_strerror(err)); + bzero(&scontrols, sizeof(scontrols)); + if ((err = snd_mixer_scontrols(handle, &scontrols)) < 0) { + error("Mixer %i/%i scontrols error: %s", card, device, snd_strerror(err)); return -1; } - groups.pgroups = (snd_mixer_gid_t *)malloc(groups.groups_over * sizeof(snd_mixer_eid_t)); - if (!groups.pgroups) { + scontrols.pscontrols = (snd_mixer_sid_t *)malloc(scontrols.scontrols_over * sizeof(snd_mixer_eid_t)); + if (!scontrols.pscontrols) { error("Not enough memory"); return -1; } - groups.groups_size = groups.groups_over; - groups.groups_over = groups.groups = 0; - if ((err = snd_mixer_groups(handle, &groups)) < 0) { - error("Mixer %i/%i groups (2) error: %s", card, device, snd_strerror(err)); + scontrols.scontrols_size = scontrols.scontrols_over; + scontrols.scontrols_over = scontrols.scontrols = 0; + if ((err = snd_mixer_scontrols(handle, &scontrols)) < 0) { + error("Mixer %i/%i scontrols (2) error: %s", card, device, snd_strerror(err)); return -1; } - for (idx = 0; idx < groups.groups; idx++) { - group = &groups.pgroups[idx]; - printf("Group '%s',%i\n", group_name(group->name), group->index); - show_group(handle, group, " "); + for (idx = 0; idx < scontrols.scontrols; idx++) { + scontrol = &scontrols.pscontrols[idx]; + printf("Group '%s',%i\n", scontrol_name(scontrol->name), scontrol->index); + show_scontrol(handle, scontrol, " "); } - free(groups.pgroups); + free(scontrols.pscontrols); snd_mixer_close(handle); +#endif return 0; } -int groups_contents(void) +int scontrols_contents(void) { +#if 0 int err; - group_contents_is_on = 1; - err = groups(); - group_contents_is_on = 0; + scontrol_contents_is_on = 1; + err = scontrols(); + scontrol_contents_is_on = 0; return err; +#else + return 0; +#endif } -static int parse_eid(const char *str, snd_mixer_eid_t *eid) -{ - int c, size, idx; - char *ptr; - - while (*str == ' ' || *str == '\t') - str++; - if (!(*str)) - return 1; - bzero(eid, sizeof(*eid)); - if (!strncmp(str, "none", 4) || !strncmp(str, "NONE", 4)) - return 0; - ptr = eid->name; - size = 0; - if (*str != '"' && *str != '\'') { - while (*str && *str != ',') { - if (size < sizeof(eid->name)) { - *ptr++ = *str; - size++; - } - str++; - } - } else { - c = *str++; - while (*str && *str != c) { - if (size < sizeof(eid->name)) { - *ptr++ = *str; - size++; - } - str++; - } - if (*str == c) - str++; - } - if (*str != ',') - return 1; - str++; - if (!isdigit(*str)) - return 1; - eid->index = atoi(str); - while (isdigit(*str)) - str++; - if (*str != ',') - return 1; - str++; - if (isdigit(*str)) { - eid->type = atoi(str); - return 0; - } else { - for (idx = 0; mixer_types[idx].type >= 0; idx++) - if (!strncmp(mixer_types[idx].name, str, strlen(mixer_types[idx].name))) { - eid->type = mixer_types[idx].type; - return 0; - } - } - return 1; -} - -static int parse_gid(const char *str, snd_mixer_gid_t *gid) +static int parse_sid(const char *str, snd_mixer_sid_t *sid) { int c, size; char *ptr; @@ -1063,12 +488,12 @@ static int parse_gid(const char *str, snd_mixer_gid_t *gid) str++; if (!(*str)) return 1; - bzero(gid, sizeof(*gid)); - ptr = gid->name; + bzero(sid, sizeof(*sid)); + ptr = sid->name; size = 0; if (*str != '"' && *str != '\'') { while (*str && *str != ',') { - if (size < sizeof(gid->name)) { + if (size < sizeof(sid->name)) { *ptr++ = *str; size++; } @@ -1077,7 +502,7 @@ static int parse_gid(const char *str, snd_mixer_gid_t *gid) } else { c = *str++; while (*str && *str != c) { - if (size < sizeof(gid->name)) { + if (size < sizeof(sid->name)) { *ptr++ = *str; size++; } @@ -1093,292 +518,13 @@ static int parse_gid(const char *str, snd_mixer_gid_t *gid) str++; if (!isdigit(*str)) return 1; - gid->index = atoi(str); + sid->index = atoi(str); return 0; } -int eset_switch1(int argc, char *argv[], void *handle, snd_mixer_eid_t *eid) -{ - int err, tmp, idx = 0; - snd_mixer_element_t element; - char *ptr; - - if (argc != 1) { - fprintf(stderr, "The set Switch1 command requires an argument:\n"); - fprintf(stderr, " on/off[,on/off] ...\n"); - return 1; - } - bzero(&element, sizeof(element)); - element.eid = *eid; - if ((err = snd_mixer_element_build(handle, &element)) < 0) { - error("Mixer element build error: %s", snd_strerror(err)); - return 1; - } - if (!strcmp(argv[0], "on") || !strcmp(argv[0], "off")) { - tmp = !strcmp(argv[0], "on"); - for (idx = 0; idx < element.data.switch1.sw; idx++) - snd_mixer_set_bit(element.data.switch1.psw, idx, tmp); - } else { - ptr = argv[idx]; - for (idx = 0; idx < element.data.switch1.sw; idx++) { - tmp = !strncmp(ptr, "on", 2); - snd_mixer_set_bit(element.data.switch1.psw, idx, tmp); - while (*ptr && *ptr != ',') - ptr++; - if (*ptr == ',') - ptr++; - } - } - if ((err = snd_mixer_element_write(handle, &element)) < 0) { - error("Mixer element write error: %s\n", snd_strerror(err)); - snd_mixer_element_free(&element); - return 1; - } - snd_mixer_element_free(&element); - return 0; -} - -int eset_switch2(int argc, char *argv[], void *handle, snd_mixer_eid_t *eid) -{ - int err; - snd_mixer_element_t element; - - if (argc != 1) { - fprintf(stderr, "The set Switch2 command requires an argument:\n"); - fprintf(stderr, " on/off\n"); - return 1; - } - bzero(&element, sizeof(element)); - element.eid = *eid; - if ((err = snd_mixer_element_build(handle, &element)) < 0) { - error("Mixer element build error: %s", snd_strerror(err)); - return 1; - } - element.data.switch2.sw = !strcmp(argv[0], "on") ? 1 : 0; - if ((err = snd_mixer_element_write(handle, &element)) < 0) { - error("Mixer element write error: %s\n", snd_strerror(err)); - snd_mixer_element_free(&element); - return 1; - } - snd_mixer_element_free(&element); - return 0; -} - -int eset_volume1(int argc, char *argv[], void *handle, snd_mixer_eid_t *eid) -{ - int err, tmp, idx = 0; - snd_mixer_element_t element; - snd_mixer_element_info_t info; - char *ptr; - - if (argc != 1 || (!isdigit(*argv[0]) && *argv[0] != ':')) { - fprintf(stderr, "The set Volume1 command requires an argument:\n"); - fprintf(stderr, " vol[,vol] ...\n"); - return 1; - } - bzero(&info, sizeof(info)); - info.eid = *eid; - if ((err = snd_mixer_element_info_build(handle, &info)) < 0) { - error("Mixer element read error: %s", snd_strerror(err)); - return 1; - } - bzero(&element, sizeof(element)); - element.eid = *eid; - if ((err = snd_mixer_element_build(handle, &element)) < 0) { - error("Mixer element read error: %s", snd_strerror(err)); - snd_mixer_element_info_free(&info); - return 1; - } - if (!strchr(argv[0], ',')) { - for (idx = 0; idx < element.data.volume1.channels; idx++) { - ptr = argv[0]; - tmp = get_volume(&ptr, - info.data.volume1.prange[idx].min, - info.data.volume1.prange[idx].max, - info.data.volume1.prange[idx].min_dB, - info.data.volume1.prange[idx].max_dB); - element.data.volume1.pchannels[idx] = tmp; - } - } else { - ptr = argv[idx]; - for (idx = 0; idx < element.data.volume1.channels; idx++) { - tmp = get_volume(&ptr, - info.data.volume1.prange[idx].min, - info.data.volume1.prange[idx].max, - info.data.volume1.prange[idx].min_dB, - info.data.volume1.prange[idx].max_dB); - element.data.volume1.pchannels[idx] = tmp; - } - } - if ((err = snd_mixer_element_write(handle, &element)) < 0) { - error("Mixer element write error: %s\n", snd_strerror(err)); - snd_mixer_element_free(&element); - snd_mixer_element_info_free(&info); - return 1; - } - snd_mixer_element_free(&element); - snd_mixer_element_info_free(&info); - return 0; -} - -int eset_accu3(int argc, char *argv[], void *handle, snd_mixer_eid_t *eid) -{ - int err, tmp, idx = 0; - snd_mixer_element_t element; - snd_mixer_element_info_t info; - char *ptr; - - if (argc != 1 || (!isdigit(*argv[0]) && *argv[0] != ':')) { - fprintf(stderr, "The set Accu3 command requires an argument:\n"); - fprintf(stderr, " vol[,vol] ...\n"); - return 1; - } - bzero(&info, sizeof(info)); - info.eid = *eid; - if ((err = snd_mixer_element_info_build(handle, &info)) < 0) { - error("Mixer element read error: %s", snd_strerror(err)); - return 1; - } - bzero(&element, sizeof(element)); - element.eid = *eid; - if ((err = snd_mixer_element_build(handle, &element)) < 0) { - error("Mixer element read error: %s", snd_strerror(err)); - snd_mixer_element_info_free(&info); - return 1; - } - if (!strchr(argv[0], ',')) { - for (idx = 0; idx < element.data.accu3.channels; idx++) { - ptr = argv[0]; - tmp = get_volume(&ptr, - info.data.accu3.prange[idx].min, - info.data.accu3.prange[idx].max, - info.data.accu3.prange[idx].min_dB, - info.data.accu3.prange[idx].max_dB); - element.data.accu3.pchannels[idx] = tmp; - } - } else { - ptr = argv[idx]; - for (idx = 0; idx < element.data.volume1.channels; idx++) { - tmp = get_volume(&ptr, - info.data.accu3.prange[idx].min, - info.data.accu3.prange[idx].max, - info.data.accu3.prange[idx].min_dB, - info.data.accu3.prange[idx].max_dB); - element.data.accu3.pchannels[idx] = tmp; - } - } - if ((err = snd_mixer_element_write(handle, &element)) < 0) { - error("Mixer element write error: %s\n", snd_strerror(err)); - snd_mixer_element_free(&element); - snd_mixer_element_info_free(&info); - return 1; - } - snd_mixer_element_free(&element); - snd_mixer_element_info_free(&info); - return 0; -} - -int eset_mux1(int argc, char *argv[], void *handle, snd_mixer_eid_t *eid) -{ - int err, idx = 0; - snd_mixer_element_t element; - snd_mixer_element_info_t info; - snd_mixer_eid_t xeid; - - if (argc < 1) { - fprintf(stderr, "The set Mux1 command requires an argument:\n"); - fprintf(stderr, " element[ element] ...\n"); - return 1; - } - bzero(&info, sizeof(info)); - info.eid = *eid; - if ((err = snd_mixer_element_info_build(handle, &info)) < 0) { - error("Mixer element read error: %s", snd_strerror(err)); - return 1; - } - bzero(&element, sizeof(element)); - element.eid = *eid; - if ((err = snd_mixer_element_build(handle, &element)) < 0) { - error("Mixer element read error: %s", snd_strerror(err)); - snd_mixer_element_info_free(&info); - return 1; - } - if (argc == 1) { - if (parse_eid(argv[0], &xeid)) { - fprintf(stderr, "Wrong element identifier: %s\n", argv[0]); - snd_mixer_element_free(&element); - snd_mixer_element_info_free(&info); - return 1; - } - for (idx = 0; idx < element.data.mux1.sel; idx++) - element.data.mux1.psel[idx] = xeid; - } else { - for (idx = 0; idx < element.data.volume1.channels; idx++) { - if (parse_eid(argv[idx >= argc ? argc - 1 : idx], &xeid)) { - fprintf(stderr, "Wrong element identifier: %s\n", argv[0]); - snd_mixer_element_free(&element); - snd_mixer_element_info_free(&info); - return 1; - } - element.data.mux1.psel[idx] = xeid; - } - } - if ((err = snd_mixer_element_write(handle, &element)) < 0) { - error("Mixer element write error: %s\n", snd_strerror(err)); - snd_mixer_element_free(&element); - snd_mixer_element_info_free(&info); - return 1; - } - snd_mixer_element_free(&element); - snd_mixer_element_info_free(&info); - return 0; -} - -int eset_mux2(int argc, char *argv[], void *handle, snd_mixer_eid_t *eid) -{ - int err; - snd_mixer_element_t element; - snd_mixer_element_info_t info; - snd_mixer_eid_t xeid; - - if (argc != 1) { - fprintf(stderr, "The set Mux2 command requires an argument:\n"); - fprintf(stderr, " element\n"); - return 1; - } - bzero(&info, sizeof(info)); - info.eid = *eid; - if ((err = snd_mixer_element_info_build(handle, &info)) < 0) { - error("Mixer element read error: %s", snd_strerror(err)); - return 1; - } - bzero(&element, sizeof(element)); - element.eid = *eid; - if ((err = snd_mixer_element_build(handle, &element)) < 0) { - error("Mixer element read error: %s", snd_strerror(err)); - snd_mixer_element_info_free(&info); - return 1; - } - if (parse_eid(argv[0], &xeid)) { - fprintf(stderr, "Wrong element identifier: %s\n", argv[0]); - snd_mixer_element_free(&element); - snd_mixer_element_info_free(&info); - return 1; - } - element.data.mux2.sel = xeid; - if ((err = snd_mixer_element_write(handle, &element)) < 0) { - error("Mixer element write error: %s\n", snd_strerror(err)); - snd_mixer_element_free(&element); - snd_mixer_element_info_free(&info); - return 1; - } - snd_mixer_element_free(&element); - snd_mixer_element_info_free(&info); - return 0; -} - -int eset(int argc, char *argv[]) +int cset(int argc, char *argv[]) { +#if 0 int err; snd_mixer_t *handle; snd_mixer_eid_t eid; @@ -1434,11 +580,13 @@ int eset(int argc, char *argv[]) } __end: snd_mixer_close(handle); +#endif return 0; } -int eget(int argc, char *argv[]) +int cget(int argc, char *argv[]) { +#if 0 int err; snd_mixer_t *handle; snd_mixer_eid_t eid; @@ -1465,9 +613,12 @@ int eget(int argc, char *argv[]) } } snd_mixer_close(handle); +#endif return 0; } +#if 0 + typedef struct channel_mask { char *name; unsigned int mask; @@ -1498,20 +649,23 @@ static int check_channels(char *arg, unsigned int mask, unsigned int *mask_retur return 0; } -int gset(int argc, char *argv[]) +#endif + +int sset(int argc, char *argv[]) { +#if 0 int err, idx, chn; unsigned int channels; snd_mixer_t *handle; - snd_mixer_gid_t gid; - snd_mixer_group_t group; + snd_mixer_sid_t sid; + snd_mixer_scontrol_t scontrol; if (argc < 1) { - fprintf(stderr, "Specify a group identifier: 'name',index\n"); + fprintf(stderr, "Specify a scontrol identifier: 'name',index\n"); return 1; } - if (parse_gid(argv[0], &gid)) { - fprintf(stderr, "Wrong group identifier: %s\n", argv[0]); + if (parse_sid(argv[0], &sid)) { + fprintf(stderr, "Wrong scontrol identifier: %s\n", argv[0]); return 1; } if (argc < 2) { @@ -1522,33 +676,33 @@ int gset(int argc, char *argv[]) error("Mixer %i/%i open error: %s\n", card, device, snd_strerror(err)); return -1; } - bzero(&group, sizeof(group)); - group.gid = gid; - if (snd_mixer_group_read(handle, &group)<0) { - error("Unable to read group '%s',%i: %s\n", group_name(gid.name), gid.index, snd_strerror(err)); + bzero(&scontrol, sizeof(scontrol)); + scontrol.sid = sid; + if (snd_mixer_scontrol_read(handle, &scontrol)<0) { + error("Unable to read scontrol '%s',%i: %s\n", scontrol_name(sid.name), sid.index, snd_strerror(err)); snd_mixer_close(handle); return -1; } - channels = group.channels; /* all channels */ + channels = scontrol.channels; /* all channels */ for (idx = 1; idx < argc; idx++) { if (!strncmp(argv[idx], "mute", 4) || !strncmp(argv[idx], "off", 3)) { - group.mute = group.channels; + scontrol.mute = scontrol.channels; continue; } else if (!strncmp(argv[idx], "unmute", 6) || !strncmp(argv[idx], "on", 2)) { - group.mute = 0; + scontrol.mute = 0; continue; } else if (!strncmp(argv[idx], "cap", 3) || !strncmp(argv[idx], "rec", 3)) { - group.capture = group.channels; + scontrol.capture = scontrol.channels; continue; } else if (!strncmp(argv[idx], "nocap", 5) || !strncmp(argv[idx], "norec", 5)) { - group.capture = 0; + scontrol.capture = 0; continue; } - if (check_channels(argv[idx], group.channels, &channels)) + if (check_channels(argv[idx], scontrol.channels, &channels)) continue; if (isdigit(argv[idx][0]) || argv[idx][0] == '+' || @@ -1559,13 +713,13 @@ int gset(int argc, char *argv[]) multi = (strchr(argv[idx], ',') != NULL); ptr = argv[idx]; for (chn = 0; chn <= SND_MIXER_CHN_LAST; chn++) { - if (!(group.channels & (1< 32) { - fprintf(stderr, "Error: device %i is invalid\n", device); - return 1; - } - break; case 'q': case HELPID_QUIET: quiet = 1; @@ -1681,26 +828,26 @@ int main(int argc, char *argv[]) return 1; } if (argc - optind <= 0) { - return groups_contents() ? 1 : 0; + return scontrols_contents() ? 1 : 0; } if (!strcmp(argv[optind], "info")) { return info() ? 1 : 0; - } else if (!strcmp(argv[optind], "elements")) { - return elements() ? 1 : 0; + } else if (!strcmp(argv[optind], "controls")) { + return controls() ? 1 : 0; } else if (!strcmp(argv[optind], "contents")) { - return elements_contents() ? 1 : 0; - } else if (!strcmp(argv[optind], "groups")) { - return groups() ? 1 : 0; - } else if (!strcmp(argv[optind], "gcontents")) { - return groups_contents() ? 1 : 0; - } else if (!strcmp(argv[optind], "set")) { - return gset(argc - optind - 1, argc - optind > 1 ? argv + optind + 1 : NULL) ? 1 : 0; - } else if (!strcmp(argv[optind], "get")) { - return gget(argc - optind - 1, argc - optind > 1 ? argv + optind + 1 : NULL) ? 1 : 0; - } else if (!strcmp(argv[optind], "eset")) { - return eset(argc - optind - 1, argc - optind > 1 ? argv + optind + 1 : NULL) ? 1 : 0; - } else if (!strcmp(argv[optind], "eget")) { - return eget(argc - optind - 1, argc - optind > 1 ? argv + optind + 1 : NULL) ? 1 : 0; + return controls_contents() ? 1 : 0; + } else if (!strcmp(argv[optind], "simple")) { + return scontrols() ? 1 : 0; + } else if (!strcmp(argv[optind], "scontents")) { + return scontrols_contents() ? 1 : 0; + } else if (!strcmp(argv[optind], "sset")) { + return sset(argc - optind - 1, argc - optind > 1 ? argv + optind + 1 : NULL) ? 1 : 0; + } else if (!strcmp(argv[optind], "sget")) { + return sget(argc - optind - 1, argc - optind > 1 ? argv + optind + 1 : NULL) ? 1 : 0; + } else if (!strcmp(argv[optind], "cset")) { + return cset(argc - optind - 1, argc - optind > 1 ? argv + optind + 1 : NULL) ? 1 : 0; + } else if (!strcmp(argv[optind], "cget")) { + return cget(argc - optind - 1, argc - optind > 1 ? argv + optind + 1 : NULL) ? 1 : 0; } else { fprintf(stderr, "amixer: Unknown command '%s'...\n", argv[optind]); }