]> git.alsa-project.org Git - alsa-utils.git/commitdiff
New simple mixer implementation
authorAbramo Bagnara <abramo@alsa-project.org>
Thu, 15 Feb 2001 23:05:42 +0000 (23:05 +0000)
committerAbramo Bagnara <abramo@alsa-project.org>
Thu, 15 Feb 2001 23:05:42 +0000 (23:05 +0000)
alsamixer/alsamixer.c
amixer/amixer.c

index 0e27be2e723c5875ba8a60123c8238d7d893badd..39b1bd53b8127121aae85949b103600c68d5fd30 100644 (file)
@@ -465,14 +465,14 @@ mixer_conv(int val, int omin, int omax, int nmin, int nmax)
 }
 
 static int
-mixer_calc_volume(snd_mixer_selem_info_t *info,
-                 snd_mixer_selem_value_t *value,
+mixer_calc_volume(snd_mixer_elem_t *elem,
                  int vol,
                  snd_mixer_selem_channel_id_t chn)
 {
   int vol1;
-  long min = snd_mixer_selem_info_get_min(info);
-  long max = snd_mixer_selem_info_get_max(info);
+  long v;
+  long min = snd_mixer_selem_get_playback_min(elem);
+  long max = snd_mixer_selem_get_playback_max(elem);
   vol1 = (vol < 0) ? -vol : vol;
   if (vol1 > 0) {
     if (vol1 > 100)
@@ -484,7 +484,8 @@ mixer_calc_volume(snd_mixer_selem_info_t *info,
     if (vol < 0)
       vol1 = -vol1;
   }
-  vol1 += snd_mixer_selem_value_get_volume(value, chn);
+  snd_mixer_selem_get_playback_volume(elem, chn, &v);
+  vol1 += v;
   return CLAMP(vol1, min, max);
 }
 
@@ -494,15 +495,11 @@ static void
 mixer_write_cbar (int elem_index)
 {
   snd_mixer_elem_t *elem;
-  snd_mixer_selem_info_t *info;
-  snd_mixer_selem_value_t *value;
   int vleft, vright, vbalance;
   int type;
   snd_mixer_selem_id_t *sid;
   snd_mixer_selem_channel_id_t chn_left, chn_right, chn;
-  int err, changed;
-  snd_mixer_selem_info_alloca(&info);
-  snd_mixer_selem_value_alloca(&value);
+  int sw;
 
   if (mixer_sid == NULL)
     return;
@@ -511,52 +508,59 @@ mixer_write_cbar (int elem_index)
   elem = snd_mixer_find_selem(mixer_handle, sid);
   if (elem == NULL)
     CHECK_ABORT (ERR_FCN, "snd_mixer_find_selem()", -EINVAL);
-  if ((err = snd_mixer_selem_info(elem, info)) < 0)
-    CHECK_ABORT (ERR_FCN, "snd_mixer_selem_info()", err);
-  if ((err = snd_mixer_selem_read(elem, value)) < 0)
-    CHECK_ABORT (ERR_FCN, "snd_mixer_selem_read()", err);
   type = mixer_type[elem_index];
   chn_left = mixer_elem_chn[type][MIXER_CHN_LEFT];
-  if (!snd_mixer_selem_info_has_channel(info, chn_left))
+  if (!snd_mixer_selem_has_playback_channel(elem, chn_left))
     return; /* ..??.. */
   chn_right = mixer_elem_chn[type][MIXER_CHN_RIGHT];
-  if (chn_right != SND_MIXER_SCHN_UNKNOWN && ! snd_mixer_selem_info_has_channel(info, chn_right))
+  if (chn_right != SND_MIXER_SCHN_UNKNOWN && 
+      !snd_mixer_selem_has_playback_channel(elem, chn_right))
     chn_right = SND_MIXER_SCHN_UNKNOWN;
 
-  changed = 0;
-
   /* volume
    */
   if ((mixer_volume_delta[MIXER_CHN_LEFT] ||
        mixer_volume_delta[MIXER_CHN_RIGHT] ||
        mixer_balance_volumes) &&
-       snd_mixer_selem_info_has_volume(info)) {
+       snd_mixer_selem_has_playback_volume(elem)) {
     int mono = 
       (chn_right == SND_MIXER_SCHN_UNKNOWN ||
-       snd_mixer_selem_info_has_joined_volume(info));
+       snd_mixer_selem_has_playback_volume_joined(elem));
     if (mono && !mixer_volume_delta[MIXER_CHN_LEFT])
       mixer_volume_delta[MIXER_CHN_LEFT] = mixer_volume_delta[MIXER_CHN_RIGHT];
-    vleft = mixer_calc_volume(info, value, mixer_volume_delta[MIXER_CHN_LEFT], chn_left);
+    vleft = mixer_calc_volume(elem, mixer_volume_delta[MIXER_CHN_LEFT], chn_left);
     vbalance = vleft;
     if (! mono) {
-      vright = mixer_calc_volume(info, value, mixer_volume_delta[MIXER_CHN_RIGHT], chn_right);
+      vright = mixer_calc_volume(elem, mixer_volume_delta[MIXER_CHN_RIGHT], chn_right);
       vbalance += vright;
       vbalance /= 2;
     } else
       vright = vleft;
     if (vleft >= 0 && vright >= 0) {
-      if (snd_mixer_selem_info_has_joined_volume(info)) {
+      if (snd_mixer_selem_has_playback_volume_joined(elem)) {
        for (chn = 0; chn < SND_MIXER_SCHN_LAST; snd_enum_incr(chn))
-         if (snd_mixer_selem_info_has_channel(info, chn))
-           snd_mixer_selem_value_set_volume(value, chn, vleft);
+         if (snd_mixer_selem_has_playback_channel(elem, chn))
+           snd_mixer_selem_set_playback_volume(elem, chn, vleft);
+         if (snd_mixer_selem_has_capture_channel(elem, chn))
+           snd_mixer_selem_set_capture_volume(elem, chn, vleft);
       } else {
        if (mixer_balance_volumes)
          vleft = vright = vbalance;
-       snd_mixer_selem_value_set_volume(value, chn_left, vleft);
-       if (! mono)
-         snd_mixer_selem_value_set_volume(value, chn_right, vright);
+       if (snd_mixer_selem_has_playback_volume(elem) &&
+           snd_mixer_selem_has_playback_channel(elem, chn_left))
+         snd_mixer_selem_set_playback_volume(elem, chn_left, vleft);
+       if (snd_mixer_selem_has_capture_volume(elem) &&
+           snd_mixer_selem_has_capture_channel(elem, chn_left))
+         snd_mixer_selem_set_capture_volume(elem, chn_left, vleft);
+       if (! mono) {
+         if (snd_mixer_selem_has_playback_volume(elem) &&
+           snd_mixer_selem_has_playback_channel(elem, chn_right))
+           snd_mixer_selem_set_playback_volume(elem, chn_right, vright);
+         if (snd_mixer_selem_has_capture_volume(elem) &&
+           snd_mixer_selem_has_capture_channel(elem, chn_right))
+           snd_mixer_selem_set_capture_volume(elem, chn_right, vright);
+       }
       }
-      changed = 1;
     }
   }
   mixer_volume_delta[MIXER_CHN_LEFT] = mixer_volume_delta[MIXER_CHN_RIGHT] = 0;
@@ -564,39 +568,43 @@ mixer_write_cbar (int elem_index)
 
   /* mute
    */
-  if (mixer_toggle_mute && snd_mixer_selem_info_has_mute(info)) {
-    if (snd_mixer_selem_info_has_joined_mute(info))
-      snd_mixer_selem_value_set_mute_all(value, snd_mixer_selem_value_get_mute(value, chn_left) ? 0 : 1);
-    else {
-      if (mixer_toggle_mute & MIXER_MASK_LEFT)
-        snd_mixer_selem_value_set_mute(value, chn_left, snd_mixer_selem_value_get_mute(value, chn_left) ? 0 : 1);
+  if (mixer_toggle_mute && snd_mixer_selem_has_playback_switch(elem)) {
+    if (snd_mixer_selem_has_playback_switch_joined(elem)) {
+      snd_mixer_selem_get_playback_switch(elem, chn_left, &sw);
+      snd_mixer_selem_set_playback_switch_all(elem, !sw);
+    } else {
+      if (mixer_toggle_mute & MIXER_MASK_LEFT) {
+       snd_mixer_selem_get_playback_switch(elem, chn_left, &sw);
+        snd_mixer_selem_set_playback_switch(elem, chn_left, !sw);
+      }
       if (chn_right != SND_MIXER_SCHN_UNKNOWN && 
-         (mixer_toggle_mute & MIXER_MASK_RIGHT))
-        snd_mixer_selem_value_set_mute(value, chn_right, snd_mixer_selem_value_get_mute(value, chn_right) ? 0 : 1);
+         (mixer_toggle_mute & MIXER_MASK_RIGHT)) {
+       snd_mixer_selem_get_playback_switch(elem, chn_right, &sw);
+        snd_mixer_selem_set_playback_switch(elem, chn_right, !sw);
+      }
     }
-    changed = 1;
   }
   mixer_toggle_mute = 0;
 
   /* capture
    */
-  if (mixer_toggle_capture && snd_mixer_selem_info_has_capture(info)) {
-    if (snd_mixer_selem_info_has_joined_capture(info))
-      snd_mixer_selem_value_set_capture_all(value, snd_mixer_selem_value_get_capture(value, chn_left) ? 0 : 1);
-    else {
-      if (mixer_toggle_capture & MIXER_MASK_LEFT)
-        snd_mixer_selem_value_set_capture(value, chn_left, snd_mixer_selem_value_get_capture(value, chn_left) ? 0 : 1);
-      if (chn_right != SND_MIXER_SCHN_UNKNOWN && (mixer_toggle_capture & MIXER_MASK_RIGHT))
-        snd_mixer_selem_value_set_capture(value, chn_right, snd_mixer_selem_value_get_capture(value, chn_right) ? 0 : 1);
+  if (mixer_toggle_capture && snd_mixer_selem_has_capture_switch(elem)) {
+    if (snd_mixer_selem_has_capture_switch_joined(elem)) {
+      snd_mixer_selem_get_capture_switch(elem, chn_left, &sw);
+      snd_mixer_selem_set_capture_switch_all(elem, !sw);
+    } else {
+      if (mixer_toggle_capture & MIXER_MASK_LEFT) {
+       snd_mixer_selem_get_capture_switch(elem, chn_left, &sw);
+        snd_mixer_selem_set_capture_switch(elem, chn_left, !sw);
+      }
+      if (chn_right != SND_MIXER_SCHN_UNKNOWN && 
+         (mixer_toggle_capture & MIXER_MASK_RIGHT)) {
+       snd_mixer_selem_get_capture_switch(elem, chn_right, &sw);
+        snd_mixer_selem_set_capture_switch(elem, chn_right, !sw);
+      }
     }
-    changed = 1;
   }
   mixer_toggle_capture = 0;
-      
-  if (changed) {
-    if ((err = snd_mixer_selem_write (elem, value)) < 0)
-      CHECK_ABORT (ERR_FCN, "snd_mixer_selem_write()", err);
-  }
 }
 
 
@@ -604,17 +612,14 @@ static void
 mixer_update_cbar (int elem_index)
 {
   char string[128], string1[64];
-  int err, dc;
+  int dc;
   snd_mixer_elem_t *elem;
-  snd_mixer_selem_info_t *info;
-  snd_mixer_selem_value_t *value;
-  int vleft, vright;
+  long vleft, vright;
   int type;
   snd_mixer_selem_id_t *sid;
   snd_mixer_selem_channel_id_t chn_left, chn_right;
   int x, y, i;
-  snd_mixer_selem_info_alloca(&info);
-  snd_mixer_selem_value_alloca(&value);
+  int swl, swr;
 
   /* set new scontrol indices and read info
    */
@@ -625,33 +630,33 @@ mixer_update_cbar (int elem_index)
   elem = snd_mixer_find_selem(mixer_handle, sid);
   if (elem == NULL)
     CHECK_ABORT (ERR_FCN, "snd_mixer_find_selem()", -EINVAL);
-  if ((err = snd_mixer_selem_info(elem, info)) < 0)
-    CHECK_ABORT (ERR_FCN, "snd_mixer_selem_info()", err);
-  if ((err = snd_mixer_selem_read(elem, value)) < 0)
-    CHECK_ABORT (ERR_FCN, "snd_mixer_selem_read()", err);
 
   type = mixer_type[elem_index];
   chn_left = mixer_elem_chn[type][MIXER_CHN_LEFT];
-  if (!snd_mixer_selem_info_has_channel(info, chn_left))
+  if (!snd_mixer_selem_has_playback_channel(elem, chn_left))
     return; /* ..??.. */
   chn_right = mixer_elem_chn[type][MIXER_CHN_RIGHT];
-  if (chn_right != SND_MIXER_SCHN_UNKNOWN && ! snd_mixer_selem_info_has_channel(info, chn_right))
+  if (chn_right != SND_MIXER_SCHN_UNKNOWN && 
+      !snd_mixer_selem_has_playback_channel(elem, chn_right))
     chn_right = SND_MIXER_SCHN_UNKNOWN;
 
-  vleft = snd_mixer_selem_value_get_volume(value, chn_left);
-  vleft = mixer_conv(vleft,
-                    snd_mixer_selem_info_get_min(info),
-                    snd_mixer_selem_info_get_max(info),
-                    0, 100);
-  if (chn_right != SND_MIXER_SCHN_UNKNOWN) {
-    vright = snd_mixer_selem_value_get_volume(value, chn_right);
-    vright = mixer_conv(vright,
-                       snd_mixer_selem_info_get_min(info),
-                       snd_mixer_selem_info_get_max(info),
-                       0, 100);
-  } else {
-    vright = vleft;
-  }
+  if (snd_mixer_selem_has_playback_volume(elem)) {
+    snd_mixer_selem_get_playback_volume(elem, chn_left, &vleft);
+    vleft = mixer_conv(vleft,
+                      snd_mixer_selem_get_playback_min(elem),
+                      snd_mixer_selem_get_playback_max(elem),
+                      0, 100);
+    if (chn_right != SND_MIXER_SCHN_UNKNOWN) {
+      snd_mixer_selem_get_playback_volume(elem, chn_right, &vright);
+      vright = mixer_conv(vright,
+                         snd_mixer_selem_get_playback_min(elem),
+                         snd_mixer_selem_get_playback_max(elem),
+                         0, 100);
+    } else {
+      vright = vleft;
+    }
+  } else
+    vleft = vright = 0;
   
   /* update the focused full bar name
    */
@@ -698,13 +703,13 @@ mixer_update_cbar (int elem_index)
   mixer_dc (DC_BACK);
   mvaddstr (y, x, "         ");
   mixer_dc (DC_TEXT);
-  sprintf (string, "%d", vleft);
+  sprintf (string, "%ld", vleft);
   mvaddstr (y, x + 3 - strlen (string), string);
   mixer_dc (DC_CBAR_FRAME);
   mvaddch (y, x + 3, '<');
   mvaddch (y, x + 4, '>');
   mixer_dc (DC_TEXT);
-  sprintf (string, "%d", vright);
+  sprintf (string, "%ld", vright);
   mvaddstr (y, x + 5, string);
   y--;
   
@@ -741,41 +746,46 @@ mixer_update_cbar (int elem_index)
    */
   mixer_dc (DC_BACK);
   mvaddstr (y, x, "         ");
-  mixer_dc (DC_CBAR_FRAME);
-  mvaddch (y, x + 2, ACS_ULCORNER);
-  dc = snd_mixer_selem_value_get_mute(value, chn_left) ? DC_CBAR_MUTE : DC_CBAR_NOMUTE;
-  mvaddch (y, x + 3, mixer_dc (dc));
-  if (chn_right != SND_MIXER_SCHN_UNKNOWN)
-    dc = snd_mixer_selem_value_get_mute(value, 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);
+  if (snd_mixer_selem_has_playback_switch(elem)) {
+    mixer_dc (DC_CBAR_FRAME);
+    mvaddch (y, x + 2, ACS_ULCORNER);
+    snd_mixer_selem_get_playback_switch(elem, chn_left, &swl);
+    dc = swl ? DC_CBAR_NOMUTE : DC_CBAR_MUTE;
+    mvaddch (y, x + 3, mixer_dc (dc));
+    if (chn_right != SND_MIXER_SCHN_UNKNOWN) {
+      snd_mixer_selem_get_playback_switch(elem, chn_right, &swr);
+      dc = swr ? DC_CBAR_NOMUTE : DC_CBAR_MUTE;
+    }
+    mvaddch (y, x + 4, mixer_dc (dc));
+    mixer_dc (DC_CBAR_FRAME);
+    mvaddch (y, x + 5, ACS_URCORNER);
+  }
   y--;
   
   /* capture input?
    */
-  if ((snd_mixer_selem_value_get_capture(value, chn_left)) ||
-      (chn_right != SND_MIXER_SCHN_UNKNOWN && snd_mixer_selem_value_get_capture(value, chn_right)))
-    {
+  if (snd_mixer_selem_has_capture_switch(elem)) {
+    snd_mixer_selem_get_capture_switch(elem, chn_left, &swl);
+    if (chn_right != SND_MIXER_SCHN_UNKNOWN)
+      snd_mixer_selem_get_capture_switch(elem, chn_right, &swr);
+    if (swl || (chn_right != SND_MIXER_SCHN_UNKNOWN && swr)) {
       mixer_dc (DC_CBAR_CAPTURE);
       mvaddstr (y, x + 1, "CAPTUR");
-      if (snd_mixer_selem_value_get_capture(value, chn_left)) {
+      if (swl) {
        mvaddstr (y + 1, x + 1, "L");
        if (chn_right == SND_MIXER_SCHN_UNKNOWN)
          mvaddstr (y + 1, x + 6, "R");
       }
-      if (chn_right != SND_MIXER_SCHN_UNKNOWN &&
-         snd_mixer_selem_value_get_capture(value, chn_right))
+      if (chn_right != SND_MIXER_SCHN_UNKNOWN && swr)
        mvaddstr (y + 1, x + 6, "R");
+    } else {
+      for (i = 0; i < 6; i++)
+       mvaddch (y, x + 1 + i, mixer_dc (DC_CBAR_NOCAPTURE));
     }
-  else if (snd_mixer_selem_info_has_capture(info))
-    for (i = 0; i < 6; i++)
-      mvaddch (y, x + 1 + i, mixer_dc (DC_CBAR_NOCAPTURE));
-  else
-    {
-      mixer_dc (DC_BACK);
-      mvaddstr (y, x, "         ");
-    }
+  } else {
+    mixer_dc (DC_BACK);
+    mvaddstr (y, x, "         ");
+  }
   y--;
 }
 
@@ -1243,7 +1253,7 @@ mixer_init (void)
     mixer_abort (ERR_FCN, "snd_mixer_open", err);
   if ((err = snd_mixer_attach (mixer_handle, card_id)) < 0)
     mixer_abort (ERR_FCN, "snd_mixer_attach", err);
-  if ((err = snd_mixer_selem_register (mixer_handle, NULL)) < 0)
+  if ((err = snd_mixer_selem_register (mixer_handle, NULL, NULL)) < 0)
     mixer_abort (ERR_FCN, "snd_mixer_selem_register", err);
   if ((err = snd_mixer_load (mixer_handle)) < 0)
     mixer_abort (ERR_FCN, "snd_mixer_load", err);
@@ -1258,7 +1268,7 @@ static void
 mixer_reinit (void)
 {
   snd_mixer_elem_t *elem;
-  int idx, err, elem_index, i, j;
+  int idx, elem_index, i, j;
   snd_mixer_selem_id_t *sid;
   snd_mixer_selem_id_t *focus_gid;
   int focus_type = -1;
@@ -1283,18 +1293,14 @@ mixer_reinit (void)
 
   mixer_n_elems = 0;
   for (idx = 0; idx < mixer_n_selems; idx++) {
-    snd_mixer_selem_info_t *info;
-    snd_mixer_selem_info_alloca(&info);
     sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * idx);
     elem = snd_mixer_find_selem(mixer_handle, sid);
     if (elem == NULL)
       CHECK_ABORT (ERR_FCN, "snd_mixer_find_selem()", -EINVAL);
-    if ((err = snd_mixer_selem_info(elem, info)) < 0)
-      CHECK_ABORT (ERR_FCN, "snd_mixer_selem_info()", 0);
     for (i = 0; i < MIXER_ELEM_END; i++) {
       int ok;
       for (j = ok = 0; j < 2; j++) {
-        if (snd_mixer_selem_info_has_channel(info, mixer_elem_chn[i][j]))
+        if (snd_mixer_selem_has_playback_channel(elem, mixer_elem_chn[i][j]))
          ok++;
       }
       if (ok)
@@ -1314,18 +1320,14 @@ mixer_reinit (void)
     mixer_abort(ERR_FCN, "malloc", 0);
   elem_index = 0;
   for (idx = 0; idx < mixer_n_selems; idx++) {
-    snd_mixer_selem_info_t *info;
-    snd_mixer_selem_info_alloca(&info);
     sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * idx);
     elem = snd_mixer_find_selem(mixer_handle, sid);
     if (elem == NULL)
       CHECK_ABORT (ERR_FCN, "snd_mixer_find_selem()", -EINVAL);
-    if ((err = snd_mixer_selem_info(elem, info)) < 0)
-      CHECK_ABORT (ERR_FCN, "snd_mixer_selem_info()", 0);
     for (i = 0; i < MIXER_ELEM_END; i++) {
       int ok;
       for (j = ok = 0; j < 2; j++) {
-        if (snd_mixer_selem_info_has_channel(info, mixer_elem_chn[i][j]))
+        if (snd_mixer_selem_has_playback_channel(elem, mixer_elem_chn[i][j]))
           ok++;
       }
       if (ok) {
@@ -1550,6 +1552,7 @@ mixer_iteration (void)
       mixer_view = VIEW_PROCINFO;
       key = 0;
       break;
+    case '\014':
     case 'L':
     case 'l':
       mixer_clear (TRUE);
index 40b09d31c446b317a7caeba262221c0f14bac01a..ad64dd27b051d457634ea7efd949af87d9750a1c 100644 (file)
@@ -109,7 +109,7 @@ static int info(void)
                snd_mixer_close(mhandle);
                return err;
        }
-       if ((err = snd_mixer_selem_register(mhandle, 0)) < 0) {
+       if ((err = snd_mixer_selem_register(mhandle, NULL, NULL)) < 0) {
                error("Mixer register error: %s", snd_strerror(err));
                snd_mixer_close(mhandle);
                return err;
@@ -423,14 +423,13 @@ static int controls(int level)
 
 static int show_selem(snd_mixer_t *handle, snd_mixer_selem_id_t *id, const char *space, int level)
 {
-       int err;
        snd_mixer_selem_channel_id_t chn;
-       long min, max;
+       long pmin = 0, pmax = 0;
+       long cmin = 0, cmax = 0;
+       long pvol, cvol;
+       int psw, csw;
+       int mono;
        snd_mixer_elem_t *elem;
-       snd_mixer_selem_info_t *sinfo;
-       snd_mixer_selem_value_t *scontrol;
-       snd_mixer_selem_info_alloca(&sinfo);
-       snd_mixer_selem_value_alloca(&scontrol);
        
        elem = snd_mixer_find_selem(handle, id);
        if (!elem) {
@@ -438,65 +437,122 @@ static int show_selem(snd_mixer_t *handle, snd_mixer_selem_id_t *id, const char
                return -ENOENT;
        }
 
-       if ((err = snd_mixer_selem_info(elem, sinfo)) < 0) {
-               error("Mixer %s selem info error: %s", card, snd_strerror(err));
-               return err;
-       }
-       if ((err = snd_mixer_selem_read(elem, scontrol)) < 0) {
-               error("Mixer %s selem read error: %s", card, snd_strerror(err));
-               return err;
-       }
        if ((level & 1) != 0) {
                printf("%sCapabilities:", space);
-               if (snd_mixer_selem_info_has_volume(sinfo))
+               if (snd_mixer_selem_has_common_volume(elem)) {
                        printf(" volume");
-               if (snd_mixer_selem_info_has_joined_volume(sinfo))
-                       printf(" joined-volume");
-               if (snd_mixer_selem_info_has_mute(sinfo))
-                       printf(" mute");
-               if (snd_mixer_selem_info_has_joined_mute(sinfo))
-                       printf(" joined-mute");
-               if (snd_mixer_selem_info_has_capture(sinfo)) {
-                       printf(" capture");
+                       if (snd_mixer_selem_has_playback_volume_joined(elem))
+                               printf(" volume-joined");
+               } else if (snd_mixer_selem_has_playback_volume(elem)) {
+                       printf(" pvolume");
+                       if (snd_mixer_selem_has_playback_volume_joined(elem))
+                               printf(" pvolume-joined");
+               }
+               if (snd_mixer_selem_has_common_switch(elem)) {
+                       printf(" switch");
+                       if (snd_mixer_selem_has_playback_switch_joined(elem))
+                               printf(" switch-joined");
+               } else if (snd_mixer_selem_has_playback_switch(elem)) {
+                       printf(" pswitch");
+                       if (snd_mixer_selem_has_playback_switch_joined(elem))
+                               printf(" pswitch-joined");
                }
-               if (snd_mixer_selem_info_has_joined_capture(sinfo))
-                       printf(" joined-capture");
-               if (snd_mixer_selem_info_has_exclusive_capture(sinfo))
-                       printf(" exclusive-capture");
+               if (snd_mixer_selem_has_capture_volume(elem))
+                       printf(" cvolume");
+               if (snd_mixer_selem_has_capture_volume_joined(elem))
+                       printf(" cvolume-joined");
+               if (snd_mixer_selem_has_capture_switch(elem))
+                       printf(" cswitch");
+               if (snd_mixer_selem_has_capture_switch_joined(elem))
+                       printf(" cswitch-joined");
+               if (snd_mixer_selem_has_capture_switch_exclusive(elem))
+                       printf(" cswitch_exclusive");
                printf("\n");
-               if (snd_mixer_selem_info_has_capture(sinfo) &&
-                   snd_mixer_selem_info_has_exclusive_capture(sinfo))
+               if (snd_mixer_selem_has_capture_switch_exclusive(elem))
                        printf("%sCapture exclusive group: %i\n", space,
-                              snd_mixer_selem_info_get_capture_group(sinfo));
-               printf("%sChannels: ", space);
-               if (snd_mixer_selem_info_is_mono(sinfo)) {
-                       printf("Mono");
-               } else {
-                       for (chn = 0; chn <= SND_MIXER_SCHN_LAST; snd_enum_incr(chn)){
-                               if (!snd_mixer_selem_info_has_channel(sinfo, chn))
-                                       continue;
-                               printf("%s ", snd_mixer_selem_channel_name(chn));
+                              snd_mixer_selem_get_capture_group(elem));
+               if (snd_mixer_selem_has_playback_volume(elem) ||
+                   snd_mixer_selem_has_playback_switch(elem)) {
+                       printf("%sPlayback channels: ", space);
+                       if (snd_mixer_selem_is_playback_mono(elem)) {
+                               printf("Mono");
+                       } else {
+                               for (chn = 0; chn <= SND_MIXER_SCHN_LAST; snd_enum_incr(chn)){
+                                       if (!snd_mixer_selem_has_playback_channel(elem, chn))
+                                               continue;
+                                       printf("%s ", snd_mixer_selem_channel_name(chn));
+                               }
                        }
+                       printf("\n");
                }
-               printf("\n");
-               min = snd_mixer_selem_info_get_min(sinfo);
-               max = snd_mixer_selem_info_get_max(sinfo);
-               printf("%sLimits: min = %li, max = %li\n", space, min, max);
-               if (snd_mixer_selem_info_is_mono(sinfo)) {
-                       printf("%sMono: %s [%s]\n", space, 
-                              get_percent(snd_mixer_selem_value_get_volume(scontrol, SND_MIXER_SCHN_MONO), min, max), 
-                              snd_mixer_selem_value_get_mute(scontrol, SND_MIXER_SCHN_MONO) ? "mute" : "on");
-               } else {
-                       for (chn = 0; chn <= SND_MIXER_SCHN_LAST; snd_enum_incr(chn)) {
-                               if (!snd_mixer_selem_info_has_channel(sinfo, chn))
-                                       continue;
-                               printf("%s%s: %s [%s] [%s]\n",
-                                      space,
-                                      snd_mixer_selem_channel_name(chn),
-                                      get_percent(snd_mixer_selem_value_get_volume(scontrol, chn), min, max),
-                                      snd_mixer_selem_value_get_mute(scontrol, chn) ? "mute" : "on",
-                                      snd_mixer_selem_value_get_capture(scontrol, chn) ? "capture" : "---");
+               if (snd_mixer_selem_has_capture_volume(elem) ||
+                   snd_mixer_selem_has_capture_switch(elem)) {
+                       printf("%sCapture channels: ", space);
+                       if (snd_mixer_selem_is_capture_mono(elem)) {
+                               printf("Mono");
+                       } else {
+                               for (chn = 0; chn <= SND_MIXER_SCHN_LAST; snd_enum_incr(chn)){
+                                       if (!snd_mixer_selem_has_capture_channel(elem, chn))
+                                               continue;
+                                       printf("%s ", snd_mixer_selem_channel_name(chn));
+                               }
+                       }
+                       printf("\n");
+               }
+               if (snd_mixer_selem_has_playback_volume(elem) ||
+                   snd_mixer_selem_has_capture_volume(elem)) {
+                       cmin = snd_mixer_selem_get_capture_min(elem);
+                       cmax = snd_mixer_selem_get_capture_max(elem);
+                       printf("%sLimits: ", space);
+                       if (snd_mixer_selem_has_playback_volume(elem)) {
+                               pmin = snd_mixer_selem_get_playback_min(elem);
+                               pmax = snd_mixer_selem_get_playback_max(elem);
+                               if (!snd_mixer_selem_has_common_volume(elem))
+                                       printf("Playback ");
+                               printf("%li - %li ", pmin, pmax);
+                       }
+                       if (snd_mixer_selem_has_capture_volume(elem)) {
+                               cmin = snd_mixer_selem_get_capture_min(elem);
+                               cmax = snd_mixer_selem_get_capture_max(elem);
+                               printf("Capture %li - %li", cmin, cmax);
+                       }
+                       printf("\n");
+               }
+               mono = ((snd_mixer_selem_is_playback_mono(elem) || 
+                        (!snd_mixer_selem_has_playback_volume(elem) &&
+                         !snd_mixer_selem_has_playback_switch(elem))) &&
+                       (snd_mixer_selem_is_capture_mono(elem) || 
+                        (!snd_mixer_selem_has_capture_volume(elem) &&
+                         !snd_mixer_selem_has_capture_switch(elem))));
+               for (chn = 0; chn <= SND_MIXER_SCHN_LAST; snd_enum_incr(chn)) {
+                       if (!snd_mixer_selem_has_playback_channel(elem, chn) &&
+                           !snd_mixer_selem_has_capture_channel(elem, chn))
+                               continue;
+                       printf("%s%s: ", space, mono ? "Mono" : snd_mixer_selem_channel_name(chn));
+                       if (snd_mixer_selem_has_playback_channel(elem, chn)) {
+                               if (!snd_mixer_selem_has_common_volume(elem))
+                                       printf("Playback ");
+                               if (snd_mixer_selem_has_playback_volume(elem)) {
+                                       snd_mixer_selem_get_playback_volume(elem, chn, &pvol);
+                                       printf("%s ", get_percent(pvol, pmin, pmax));
+                               }
+                               if (snd_mixer_selem_has_playback_switch(elem)) {
+                                       snd_mixer_selem_get_playback_switch(elem, chn, &psw);
+                                       printf("[%s] ", psw ? "on" : "off");
+                               }
+                       }
+                       if (snd_mixer_selem_has_capture_channel(elem, chn)) {
+                               printf("Capture ");
+                               if (snd_mixer_selem_has_capture_volume(elem)) {
+                                       snd_mixer_selem_get_capture_volume(elem, chn, &cvol);
+                                       printf("%s ", get_percent(cvol, cmin, cmax));
+                               }
+                               if (snd_mixer_selem_has_capture_switch(elem)) {
+                                       snd_mixer_selem_get_capture_switch(elem, chn, &csw);
+                                       printf("[%s] ", csw ? "on" : "off");
+                               }
                        }
+                       printf("\n");
                }
        }
        return 0;
@@ -519,7 +575,7 @@ static int selems(int level)
                snd_mixer_close(handle);
                return err;
        }
-       if ((err = snd_mixer_selem_register(handle, 0)) < 0) {
+       if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
                error("Mixer register error: %s", snd_strerror(err));
                snd_mixer_close(handle);
                return err;
@@ -825,11 +881,7 @@ static int sset(unsigned int argc, char *argv[], int roflag)
        snd_mixer_t *handle;
        snd_mixer_elem_t *elem;
        snd_mixer_selem_id_t *sid;
-       snd_mixer_selem_value_t *control;
-       snd_mixer_selem_info_t *info;
        snd_mixer_selem_id_alloca(&sid);
-       snd_mixer_selem_value_alloca(&control);
-       snd_mixer_selem_info_alloca(&info);
 
        if (argc < 1) {
                fprintf(stderr, "Specify a scontrol identifier: 'name',index\n");
@@ -852,7 +904,7 @@ static int sset(unsigned int argc, char *argv[], int roflag)
                snd_mixer_close(handle);
                return err;
        }
-       if ((err = snd_mixer_selem_register(handle, 0)) < 0) {
+       if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
                error("Mixer register error: %s", snd_strerror(err));
                snd_mixer_close(handle);
                return err;
@@ -869,36 +921,26 @@ static int sset(unsigned int argc, char *argv[], int roflag)
                snd_mixer_close(handle);
                return -ENOENT;
        }
-       if ((err = snd_mixer_selem_info(elem, info))<0) {
-               error("Unable to get simple info '%s',%i: %s\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid), snd_strerror(err));
-               snd_mixer_close(handle);
-               return err;
-       }
-       if ((err = snd_mixer_selem_read(elem, control))<0) {
-               error("Unable to read simple control '%s',%i: %s\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid), snd_strerror(err));
-               snd_mixer_close(handle);
-               return err;
-       }
-       min = snd_mixer_selem_info_get_min(info);
-       max = snd_mixer_selem_info_get_max(info);
+       min = snd_mixer_selem_get_playback_min(elem);
+       max = snd_mixer_selem_get_playback_max(elem);
        if (roflag)
                goto __skip_write;
        for (idx = 1; idx < argc; idx++) {
                if (!strncmp(argv[idx], "mute", 4) ||
                    !strncmp(argv[idx], "off", 3)) {
-                       snd_mixer_selem_value_set_mute_all(control, 1);
+                       snd_mixer_selem_set_playback_switch_all(elem, 1);
                        continue;
                } else if (!strncmp(argv[idx], "unmute", 6) ||
                           !strncmp(argv[idx], "on", 2)) {
-                       snd_mixer_selem_value_set_mute_all(control, 0);
+                       snd_mixer_selem_set_playback_switch_all(elem, 0);
                        continue;
                } else if (!strncmp(argv[idx], "cap", 3) ||
                           !strncmp(argv[idx], "rec", 3)) {
-                       snd_mixer_selem_value_set_capture_all(control, 1);
+                       snd_mixer_selem_set_capture_switch_all(elem, 1);
                        continue;
                } else if (!strncmp(argv[idx], "nocap", 5) ||
                           !strncmp(argv[idx], "norec", 5)) {
-                       snd_mixer_selem_value_set_capture_all(control, 0);
+                       snd_mixer_selem_set_capture_switch_all(elem, 0);
                        continue;
                }
                channels = channels_mask(argv[idx]);
@@ -911,13 +953,15 @@ static int sset(unsigned int argc, char *argv[], int roflag)
                        multi = (strchr(argv[idx], ',') != NULL);
                        ptr = argv[idx];
                        for (chn = 0; chn <= SND_MIXER_SCHN_LAST; snd_enum_incr(chn)) {
+                               long vol;
                                if (!(channels & (1 << chn)) ||
-                                   !snd_mixer_selem_info_has_channel(info, chn))
+                                   !snd_mixer_selem_has_playback_channel(elem, chn))
                                        continue;
 
                                if (! multi)
                                        ptr = argv[idx];
-                               snd_mixer_selem_value_set_volume(control, chn, get_volume_simple(&ptr, min, max, snd_mixer_selem_value_get_volume(control, chn)));
+                               snd_mixer_selem_get_playback_volume(elem, chn, &vol);
+                               snd_mixer_selem_set_playback_volume(elem, chn, get_volume_simple(&ptr, min, max, vol));
                        }
                } else {
                        error("Unknown setup '%s'..\n", argv[idx]);
@@ -925,11 +969,6 @@ static int sset(unsigned int argc, char *argv[], int roflag)
                        return err;
                }
        } 
-       if ((err = snd_mixer_selem_write(elem, control))<0) {
-               error("Unable to write control '%s',%i: %s\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid), snd_strerror(err));
-               snd_mixer_close(handle);
-               return err;
-       }
       __skip_write:
        if (!quiet) {
                printf("Simple mixer control '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
@@ -1093,7 +1132,7 @@ static int sevents(int argc ATTRIBUTE_UNUSED, char *argv[] ATTRIBUTE_UNUSED)
                snd_mixer_close(handle);
                return err;
        }
-       if ((err = snd_mixer_selem_register(handle, 0)) < 0) {
+       if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
                error("Mixer register error: %s", snd_strerror(err));
                snd_mixer_close(handle);
                return err;