comparison libao2/ao_alsa.c @ 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 36820f219892
children
comparison
equal deleted inserted replaced
37088:3a9a804e488b 37089:86893b300a45
167 snd_mixer_close(handle); 167 snd_mixer_close(handle);
168 return CONTROL_ERROR; 168 return CONTROL_ERROR;
169 } 169 }
170 170
171 elem = snd_mixer_find_selem(handle, sid); 171 elem = snd_mixer_find_selem(handle, sid);
172 if (!elem && !mixer_channel) {
173 // if nothing specified just try picking the first
174 elem = snd_mixer_first_elem(handle);
175 if (elem)
176 mp_msg(MSGT_AO, MSGL_V, "[AO_ALSA] Auto-selected element %s\n", snd_mixer_selem_get_name(elem));
177 }
172 if (!elem) { 178 if (!elem) {
173 mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToFindSimpleControl, 179 mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToFindSimpleControl,
174 snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid)); 180 snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
181 mp_msg(MSGT_AO, MSGL_INFO, "[AO_ALSA] Available elements for device:\n");
182 for (elem = snd_mixer_first_elem(handle); elem; elem = snd_mixer_elem_next(elem))
183 mp_msg(MSGT_AO, MSGL_INFO, "[AO_ALSA] %s\n", snd_mixer_selem_get_name(elem));
184 mp_msg(MSGT_AO, MSGL_INFO, "\n");
175 snd_mixer_close(handle); 185 snd_mixer_close(handle);
176 return CONTROL_ERROR; 186 return CONTROL_ERROR;
177 } 187 }
188
189 if (!snd_mixer_selem_has_playback_volume(elem) &&
190 !snd_mixer_selem_has_playback_volume_joined(elem))
191 {
192 if (!snd_mixer_selem_has_playback_switch(elem))
193 return CONTROL_FALSE;
194 if (cmd == AOCONTROL_GET_VOLUME) {
195 int v;
196 snd_mixer_selem_get_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, &v);
197 vol->left = v ? 100 : 0;
198 snd_mixer_selem_get_playback_switch(elem, SND_MIXER_SCHN_FRONT_RIGHT, &v);
199 vol->right = v ? 100 : 0;
200 return CONTROL_TRUE;
201 }
202 // special case: only mute supported
203 if (vol->left != 0 && vol->left != 100 ||
204 vol->right != 0 && vol->right != 100)
205 return CONTROL_FALSE;
206 if (snd_mixer_selem_has_playback_switch_joined(elem)) {
207 if (vol->left != vol->right)
208 return CONTROL_FALSE;
209 } else {
210 snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_RIGHT, vol->right != 0);
211 }
212 snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, vol->left != 0);
213 return CONTROL_TRUE;
214 }
178 215
179 snd_mixer_selem_get_playback_volume_range(elem,&pmin,&pmax); 216 snd_mixer_selem_get_playback_volume_range(elem,&pmin,&pmax);
180 f_multi = (100 / (float)(pmax - pmin)); 217 f_multi = (100 / (float)(pmax - pmin));
181 218
182 if (cmd == AOCONTROL_SET_VOLUME) { 219 if (cmd == AOCONTROL_SET_VOLUME) {