[MPlayer-dev-eng] [PATCH 2/2] alsa: Better volume control handling, especially for S/PDIF.

Reimar Döffinger Reimar.Doeffinger at gmx.de
Sat Apr 5 14:53:03 CEST 2014


If no mixer channel was specified and PCM does not exist, just
pick the first.
If no volume control is available, at least support mute and full
volume switching if a playback switch exists.
This is also useful for being able to unmute S/PDIF devices.
Especially useful since there seem to be several driver/ALSA bugs
that mean these devices often start as muted after every boot.
---
 libao2/ao_alsa.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/libao2/ao_alsa.c b/libao2/ao_alsa.c
index 091bd00..2ec96f4 100644
--- a/libao2/ao_alsa.c
+++ b/libao2/ao_alsa.c
@@ -169,13 +169,50 @@ static int control(int cmd, void *arg)
       }
 
       elem = snd_mixer_find_selem(handle, sid);
+      if (!elem && !mixer_channel) {
+        // if nothing specified just try picking the first
+        elem = snd_mixer_first_elem(handle);
+        if (elem)
+            mp_msg(MSGT_AO, MSGL_V, "[AO_ALSA] Auto-selected element %s\n", snd_mixer_selem_get_name(elem));
+      }
       if (!elem) {
 	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToFindSimpleControl,
 	       snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
+        mp_msg(MSGT_AO, MSGL_INFO, "[AO_ALSA] Available elements for device:\n");
+        for (elem = snd_mixer_first_elem(handle); elem; elem = snd_mixer_elem_next(elem))
+            mp_msg(MSGT_AO, MSGL_INFO, "[AO_ALSA]  %s\n", snd_mixer_selem_get_name(elem));
+        mp_msg(MSGT_AO, MSGL_INFO, "\n");
 	snd_mixer_close(handle);
 	return CONTROL_ERROR;
 	}
 
+      if (!snd_mixer_selem_has_playback_volume(elem) &&
+          !snd_mixer_selem_has_playback_volume_joined(elem))
+      {
+          if (!snd_mixer_selem_has_playback_switch(elem))
+              return CONTROL_FALSE;
+          if (cmd == AOCONTROL_GET_VOLUME) {
+              int v;
+              snd_mixer_selem_get_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, &v);
+              vol->left = v ? 100 : 0;
+              snd_mixer_selem_get_playback_switch(elem, SND_MIXER_SCHN_FRONT_RIGHT, &v);
+              vol->right = v ? 100 : 0;
+              return CONTROL_TRUE;
+          }
+          // special case: only mute supported
+          if (vol->left != 0 && vol->left != 100 ||
+              vol->right != 0 && vol->right != 100)
+              return CONTROL_FALSE;
+          if (snd_mixer_selem_has_playback_switch_joined(elem)) {
+              if (vol->left != vol->right)
+                  return CONTROL_FALSE;
+          } else {
+              snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_RIGHT, vol->right != 0);
+          }
+          snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, vol->left != 0);
+          return CONTROL_TRUE;
+      }
+
       snd_mixer_selem_get_playback_volume_range(elem,&pmin,&pmax);
       f_multi = (100 / (float)(pmax - pmin));
 
-- 
1.9.1



More information about the MPlayer-dev-eng mailing list