]> git.alsa-project.org Git - alsa-utils.git/commitdiff
Changes reflecting the new control API and kernel mixer API removal.
authorJaroslav Kysela <perex@perex.cz>
Sat, 15 Jul 2000 10:21:59 +0000 (10:21 +0000)
committerJaroslav Kysela <perex@perex.cz>
Sat, 15 Jul 2000 10:21:59 +0000 (10:21 +0000)
alsactl/alsactl.c
alsactl/alsactl.h
alsactl/alsactl_lexer.l
alsactl/alsactl_parser.y
alsactl/merge.c
alsactl/setup.c
alsamixer/alsamixer.c
amixer/amixer.c

index 44f6f86bfdfde994c776193b840370f70a6fac83..cdd81f74966ca64d274fea74814172cc9815d413 100644 (file)
@@ -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))) {
-               soundcard_setup_done();
-               return err;
-       }
-       if ((err = soundcard_setup_merge_switches(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))) {
+       if ((err = soundcard_setup_collect_controls(cardno))) {
                soundcard_setup_done();
                return err;
        }
-       if ((err = soundcard_setup_merge_data(cardno))) {
+       if ((err = soundcard_setup_merge_controls(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;
        }
index 9b80f8677f2980dfbaebe976259b33de97f8db9b..89df00a0f1d455cd29996f5e082bf8c5a098ebe9 100644 (file)
@@ -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);
index 69c396db0d88fcf6989a8a14d7b94b7cc12a20b5..77be63c29e59fda8d038ab5dc033646025ef609e 100644 (file)
@@ -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 */
 
index 7e9e4193897ebcf0ea9cd04864ac7ea196482d93..586127a13f6020e36f59618a1abe687425b0b65c 100644 (file)
@@ -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 <b_value> boolean
-%type <i_value> integer
+%type <i_value> integer iface
 %type <s_value> string
 %type <a_value> 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)
-{
-       struct mixer *mixer;
-
-       if (!name) {
-               Xmixer = NULL;
-               return;
-       }
-       Xmixer = (struct mixer *)malloc(sizeof(struct pcm));
-       if (!Xmixer) {
-               free(name);
-               error_nomem();
-               return;
-       }
-       bzero(Xmixer, sizeof(*Xmixer));
-       for (mixer = Xsoundcard->mixers; mixer && mixer->next; mixer = mixer->next);
-       if (mixer) {
-               mixer->next = Xmixer;
-       } else {
-               Xsoundcard->mixers = Xmixer;
-       }
-       strncpy(Xmixer->info.name, name, sizeof(Xmixer->info.name));
-       free(name);
-}
-
-static void build_pcm(char *name)
-{
-       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);
-}
-
-static void build_rawmidi(char *name)
-{
-       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)
+static void build_control_begin(int iface, unsigned int device, unsigned int subdevice, char *name, unsigned int index)
 {
-       struct mixer_element *element;
+       struct ctl_control **first;
+       struct ctl_control *ctl;
 
-       if (!name) {
-               Xelement = NULL;
-               return;
-       }
-       Xelement = (struct mixer_element *)malloc(sizeof(struct mixer_element));
-       if (!Xelement) {
+       first = &Xsoundcard->control.controls;
+       Xcontrol = (struct ctl_control *)malloc(sizeof(struct ctl_control));
+       if (!Xcontrol) {
                free(name);
                error_nomem();
                return;
        }
-       bzero(Xelement, sizeof(*Xelement));     
-       for (element = Xmixer->elements; element && element->next; element = element->next);
-       if (element) {
-               element->next = Xelement;
+       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 {
-               Xmixer->elements = Xelement;
+               *first = Xcontrol;
        }
-       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;
+       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 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)
+static void build_control_end(void)
 {
-       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);
+       Xcontrol = NULL;
 }
 
-static void mixer_3d_effect1_value(unsigned int effect, int val)
+static void set_control_boolean(int val)
 {
-       switch (effect) {
-       case SND_MIXER_EFF1_SW:
-               Xelement->element.data.teffect1.sw = val ? 1 : 0;
-               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;
+       switch (Xtype) {
+       case SND_CONTROL_TYPE_NONE:
+       case SND_CONTROL_TYPE_BOOLEAN:
+               Xtype = Xcontrol->type = SND_CONTROL_TYPE_BOOLEAN;
                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);
-       }
-} 
-
-static void mixer_accu3(int end)
-{
-       mixer_type_check(SND_MIXER_ETYPE_ACCU3);
-}
-
-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;
+               yyerror("Unexpected previous type (%i).\n", Xtype);
        }
-       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);
+       if (Xposition < 512)
+               Xcontrol->c.value.integer.value[Xposition++] = val ? 1 : 0;
+       else
+               yyerror("Array overflow.");
 }
 
-static void mixer_mux2_value(char *name, int index, int type)
+static void set_control_integer(long val)
 {
-       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);
-}
+       unsigned int xx;
 
-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;
+       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("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;
+               yyerror("Unexpected previous type (%i).\n", Xtype);
        }
-       Xswitch = (struct ctl_switch *)malloc(sizeof(struct ctl_switch));
-       if (!Xswitch) {
-               free(name);
-               error_nomem();
-               return;
+       if (Xposition < 512) {
+               xx = val;
+               Xcontrol->c.value.integer.value[Xposition++] = val;
        }
-       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)
-{
-       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)
+static void set_control_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);
-}
+       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;
 
-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;
-       }
-       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 */
-}
+       if (val.datalen + Xposition > 512)
+               yyerror("Byte array too large for control.");
 
-static void set_switch_iec958ocs(int idx, unsigned short val, unsigned short mask)
-{
-       if (idx == 0) {
-               Xswitchiec958ocs = val ? 1 : 0;
-               return;
-       }
-       Xswitchiec958ocs1[idx] &= mask;
-       Xswitchiec958ocs1[idx] |= val;
+       memcpy(&Xcontrol->c.value.bytes.data[Xposition], val.data, val.datalen);
+       Xposition += val.datalen;
 }
index 11e829a0f63dffc9f45f40112e8f85e298fab9db..f276b1a607d5ea64a6d2c11c421fd9ee54de59af 100644 (file)
 
 #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));
-                       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];
-               }
-               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));
-                       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];
-               }
-               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_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.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);
-               }
-               break;
-       default:
-               error("The switch type %i is not known.", csw->s.type);
-       }
-       return 0;
-}
-
-static int soundcard_setup_merge_sw(struct ctl_switch *csw, struct ctl_switch *usw, int cardno, int devno, const char *id)
-{
-       struct ctl_switch *csw1;
-       
-       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);
-                               break;
-                       }
-               }
-               if (!csw1) {
-                       error("Cannot find the switch %s...", sw_id(usw->s.name, cardno, devno, id));
-               }
-       }
-       return 0;
-}
-
-int soundcard_setup_merge_switches(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) {
-                       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;
-               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;
+               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 (!rrawmidi) {
-                               error("The rawmidi device '%s' from the soundcard %i was not found...\n", rrawmidi->info.name, soundcard->no);
-                               continue;
+                       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];
                        }
-                       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));
+       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;
                }
-               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...");
+               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;
                        }
-                       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;
+                       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];
+                       }
                }
-               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));
+       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;
                }
-               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);
+               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 element type %i for the element %s is not known.", celement->element.eid.type, mixer_element_id(&celement->element.eid));
+               error("The control type %i is not known.", cctl->type);
        }
        return 0;
 }
 
-static int soundcard_setup_merge_element(struct mixer_element *celement, struct mixer_element *uelement, int cardno, int devno, const char *id)
+static int soundcard_setup_merge_control(struct ctl_control *cctl, struct ctl_control *uctl, int cardno)
 {
-       struct mixer_element *element;
+       struct ctl_control *cctl1;
        
-       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);
+       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 (!element) {
-                       error("Cannot find the element %s...", element_id(&uelement->element.eid, cardno, devno, id));
+               if (!cctl1) {
+                       error("Cannot find the control %s...", control_id(&uctl->c.id));
                }
        }
        return 0;
 }
 
-int soundcard_setup_merge_data(int cardno)
+int soundcard_setup_merge_controls(int cardno)
 {
        struct soundcard *soundcard, *rsoundcard;
-       struct mixer *mixer, *rmixer;
 
        for (rsoundcard = rsoundcards; rsoundcard; rsoundcard = rsoundcard->next) {
                for (soundcard = soundcards; soundcard; soundcard = soundcard->next) {
@@ -377,17 +125,7 @@ int soundcard_setup_merge_data(int cardno)
                }
                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,111 +143,22 @@ 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));
-                               }
-               }
-               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 ((err = snd_ctl_cwrite(ctlhandle, &ctl->c)) < 0)
+                                               error("Control '%s' write error: %s", control_id(&ctl->c.id), snd_strerror(err));
                                }
-                       if (mixhandle) {
-                               snd_mixer_close(mixhandle);
-                               mixhandle = NULL;
-                       }
                }
                if (ctlhandle) {
                        snd_ctl_close(ctlhandle);
index d854cd6bbfd856476da1f6dcd25ee855e7305d22..b909aed882bd38150ca4dd12b0d7b3899aaeaae3 100644 (file)
@@ -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,98 +51,22 @@ char *mixer_element_id(snd_mixer_eid_t *eid)
  *  free functions
  */
 
-static void soundcard_ctl_switch_free(struct ctl_switch *first)
-{
-       struct ctl_switch *next;
-
-       while (first) {
-               next = first->next;
-               free(first);
-               first = next;
-       }
-}
-
-static void soundcard_mixer_element_free(struct mixer_element *first)
+static void soundcard_ctl_control_free(struct ctl_control *first)
 {
-       struct mixer_element *next;
+       struct ctl_control *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_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;
                }
-               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;
+               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]);
-               }
+       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, "\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_SW_TYPE_USER:
-               s = "user";
+       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_SW_TYPE_LIST:
-               s = "list";
-               sprintf(v, "%u", sw->value.item_number);
-               break;
-       case SND_SW_TYPE_USER_READ_ONLY:
-               return;
-       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);
+       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]);
-                               }
-                       }
-               }
-               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]);
+       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;
                }
-       }
-      __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" : "");
        }
index ca7a63e372ee0a1c1e577dbb3e90ac11a643cc7c..b8dfaacd69543dc1b4c9db9a66841576907e4c4e 100644 (file)
  *
  * ChangeLog:
  *
+ * Fri Jun 23 14:10:00 MEST 2000  Jaroslav Kysela <perex@suse.cz>
+ *
+ *      * 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 <iwai@ww.uni-erlangen.de>
  *
  *     * 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  <timj@gtk.org>
  *
 #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 <card: 1..%i>] [-m <mixer: 0..1>] [-z]\n", PRGNAME, snd_cards ());
-         mixer_abort (ERR_NONE, "");
+         fprintf (stderr, "Usage: %s [-c <card: 0..%i>] [-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);
 };
index b82ea3beadb7cfca0d5455c40694ae2faa29b6a0..e03829dfa0010a15e09777e9e6207a437709f18d 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *   ALSA command line mixer utility
- *   Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
+ *   Copyright (c) 1999-2000 by Jaroslav Kysela <perex@suse.cz>
  *
  *   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
 
 #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<<chn)))
+                               if (!(scontrol.channels & (1<<chn)))
                                        continue;
-                               printf("%s ", snd_mixer_channel_name(chn));
+                               printf("%s ", snd_mixer_simple_channel_name(chn));
                        }
                }
                printf("\n");
-               printf("%sLimits: min = %i, max = %i\n", space, group.min, group.max);
-               if (group.channels == SND_MIXER_CHN_MASK_MONO) {
-                       printf("%sMono: %s [%s]\n", space, get_percent(group.volume.names.front_left, group.min, group.max), group.mute & SND_MIXER_CHN_MASK_MONO ? "mute" : "on");
+               printf("%sLimits: min = %i, max = %i\n", space, scontrol.min, scontrol.max);
+               if (scontrol.channels == SND_MIXER_CHN_MASK_MONO) {
+                       printf("%sMono: %s [%s]\n", space, get_percent(scontrol.volume.names.front_left, scontrol.min, scontrol.max), scontrol.mute & SND_MIXER_CHN_MASK_MONO ? "mute" : "on");
                } else {
                        for (chn = 0; chn <= SND_MIXER_CHN_LAST; chn++) {
-                               if (!(group.channels & (1<<chn)))
+                               if (!(scontrol.channels & (1<<chn)))
                                        continue;
                                printf("%s%s: %s [%s] [%s]\n",
                                                space,
-                                               snd_mixer_channel_name(chn),
-                                               get_percent(group.volume.values[chn], group.min, group.max),
-                                               group.mute & (1<<chn) ? "mute" : "on",
-                                               group.capture & (1<<chn) ? "capture" : "---");
+                                               snd_mixer_simple_channel_name(chn),
+                                               get_percent(scontrol.volume.values[chn], scontrol.min, scontrol.max),
+                                               scontrol.mute & (1<<chn) ? "mute" : "on",
+                                               scontrol.capture & (1<<chn) ? "capture" : "---");
                        }
                }
        }
-       if (group_contents_is_on)
+       if (scontrol_contents_is_on)
                return 0;
-       group.pelements = (snd_mixer_eid_t *)malloc(group.elements_over * sizeof(snd_mixer_eid_t));
-       if (!group.pelements) {
-               error("Not enough memory...");
-               return -1;
-       }
-       group.elements_size = group.elements_over;
-       group.elements = group.elements_over = 0;
-       if ((err = snd_mixer_group_read(handle, &group)) < 0) {
-               error("Mixer %i/%i group (2) error: %s", card, device, snd_strerror(err));
-               return -1;
-       }
-       for (idx = 0; idx < group.elements; idx++) {
-               element = &group.pelements[idx];
-               printf("%sElement '%s',%i,%s\n", space, element_name(element->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);
-       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);
+       sid->index = atoi(str);
        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<<chn)) ||
+                               if (!(scontrol.channels & (1<<chn)) ||
                                    !(channels & (1<<chn)))
                                        continue;
 
                                if (! multi)
                                        ptr = argv[idx];
-                               group.volume.values[chn] = get_volume_simple(&ptr, group.min, group.max, group.volume.values[chn]);
+                               scontrol.volume.values[chn] = get_volume_simple(&ptr, scontrol.min, scontrol.max, scontrol.volume.values[chn]);
                        }
                } else {
                        error("Unknown setup '%s'..\n", argv[idx]);
@@ -1573,33 +727,35 @@ int gset(int argc, char *argv[])
                        return -1;
                }
        } 
-       if (snd_mixer_group_write(handle, &group)<0) {
-               error("Unable to write group '%s',%i: %s\n", group_name(gid.name), gid.index, snd_strerror(err));
+       if (snd_mixer_scontrol_write(handle, &scontrol)<0) {
+               error("Unable to write scontrol '%s',%i: %s\n", scontrol_name(sid.name), sid.index, snd_strerror(err));
                snd_mixer_close(handle);
                return -1;
        }
        if (!quiet) {
-               printf("Group '%s',%i\n", group_name(gid.name), gid.index);
-               group_contents_is_on = 1;
-               show_group(handle, &gid, "  ");
-               group_contents_is_on = 0;
+               printf("Group '%s',%i\n", scontrol_name(sid.name), sid.index);
+               scontrol_contents_is_on = 1;
+               show_scontrol(handle, &sid, "  ");
+               scontrol_contents_is_on = 0;
        }
        snd_mixer_close(handle);
+#endif
        return 0;
 }
 
-int gget(int argc, char *argv[])
+int sget(int argc, char *argv[])
 {
+#if 0
        int err;
        snd_mixer_t *handle;
-       snd_mixer_gid_t gid;
+       snd_mixer_sid_t sid;
 
        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 ((err = snd_mixer_open(&handle, card, device)) < 0) {
@@ -1607,12 +763,13 @@ int gget(int argc, char *argv[])
                return -1;
        }
        if (!quiet) {
-               printf("Group '%s',%i\n", group_name(gid.name), gid.index);
-               group_contents_is_on = 1;
-               show_group(handle, &gid, "  ");
-               group_contents_is_on = 0;
+               printf("Group '%s',%i\n", scontrol_name(sid.name), sid.index);
+               scontrol_contents_is_on = 1;
+               show_scontrol(handle, &sid, "  ");
+               scontrol_contents_is_on = 0;
        }
        snd_mixer_close(handle);
+#endif
        return 0;
 }
 
@@ -1623,7 +780,6 @@ int main(int argc, char *argv[])
        {
                {"help", 0, NULL, HELPID_HELP},
                {"card", 1, NULL, HELPID_CARD},
-               {"device", 1, NULL, HELPID_DEVICE},
                {"quiet", 0, NULL, HELPID_QUIET},
                {"debug", 0, NULL, HELPID_DEBUG},
                {"version", 0, NULL, HELPID_VERSION},
@@ -1632,15 +788,14 @@ int main(int argc, char *argv[])
 
        morehelp = 0;
        card = snd_defaults_mixer_card();
-       device = snd_defaults_mixer_device();
-       if (card < 0 || device < 0) {
+       if (card < 0) {
                fprintf(stderr, "The ALSA sound driver was not detected in this system.\n");
                return 1;
        }
        while (1) {
                int c;
 
-               if ((c = getopt_long(argc, argv, "hc:d:qDv", long_option, NULL)) < 0)
+               if ((c = getopt_long(argc, argv, "hc:qDv", long_option, NULL)) < 0)
                        break;
                switch (c) {
                case 'h':
@@ -1651,14 +806,6 @@ int main(int argc, char *argv[])
                case HELPID_CARD:
                        card = snd_card_name(optarg);
                        break;
-               case 'd':
-               case HELPID_DEVICE:
-                       device = atoi(optarg);
-                       if (device < 0 || device > 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]);
        }