Mercurial > mplayer.hg
changeset 37089:86893b300a45
alsa: Better volume control handling, especially for S/PDIF.
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.
author | reimar |
---|---|
date | Tue, 06 May 2014 19:02:03 +0000 |
parents | 3a9a804e488b |
children | 91628537e24e |
files | libao2/ao_alsa.c |
diffstat | 1 files changed, 37 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/libao2/ao_alsa.c Tue May 06 19:02:02 2014 +0000 +++ b/libao2/ao_alsa.c Tue May 06 19:02:03 2014 +0000 @@ -169,13 +169,50 @@ } 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));