alsa: synthesize volume values more sensibly for channels that are not controllable in hw

This commit is contained in:
Lennart Poettering 2009-06-19 02:03:03 +02:00
parent b1ea7c0d89
commit 6ad3855639

View file

@ -479,6 +479,7 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
snd_mixer_elem_t *me; snd_mixer_elem_t *me;
snd_mixer_selem_channel_id_t c; snd_mixer_selem_channel_id_t c;
pa_channel_position_mask_t mask = 0; pa_channel_position_mask_t mask = 0;
pa_volume_t max_channel_volume = PA_VOLUME_MUTED;
unsigned k; unsigned k;
pa_assert(m); pa_assert(m);
@ -545,6 +546,9 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
f = from_alsa_volume(value, e->min_volume, e->max_volume); f = from_alsa_volume(value, e->min_volume, e->max_volume);
} }
if (f > max_channel_volume)
max_channel_volume = f;
for (k = 0; k < cm->channels; k++) for (k = 0; k < cm->channels; k++)
if (e->masks[c][e->n_channels-1] & PA_CHANNEL_POSITION_MASK(cm->map[k])) if (e->masks[c][e->n_channels-1] & PA_CHANNEL_POSITION_MASK(cm->map[k]))
if (v->values[k] < f) if (v->values[k] < f)
@ -555,7 +559,7 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
for (k = 0; k < cm->channels; k++) for (k = 0; k < cm->channels; k++)
if (!(mask & PA_CHANNEL_POSITION_MASK(cm->map[k]))) if (!(mask & PA_CHANNEL_POSITION_MASK(cm->map[k])))
v->values[k] = PA_VOLUME_NORM; v->values[k] = max_channel_volume;
return 0; return 0;
} }
@ -677,6 +681,7 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
snd_mixer_elem_t *me; snd_mixer_elem_t *me;
snd_mixer_selem_channel_id_t c; snd_mixer_selem_channel_id_t c;
pa_channel_position_mask_t mask = 0; pa_channel_position_mask_t mask = 0;
pa_volume_t max_channel_volume = PA_VOLUME_MUTED;
unsigned k; unsigned k;
pa_assert(m); pa_assert(m);
@ -696,11 +701,21 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
for (c = 0; c <= SND_MIXER_SCHN_LAST; c++) { for (c = 0; c <= SND_MIXER_SCHN_LAST; c++) {
int r; int r;
pa_volume_t f = PA_VOLUME_MUTED; pa_volume_t f = PA_VOLUME_MUTED;
pa_bool_t found = FALSE;
for (k = 0; k < cm->channels; k++) for (k = 0; k < cm->channels; k++)
if (e->masks[c][e->n_channels-1] & PA_CHANNEL_POSITION_MASK(cm->map[k])) if (e->masks[c][e->n_channels-1] & PA_CHANNEL_POSITION_MASK(cm->map[k])) {
found = TRUE;
if (v->values[k] > f) if (v->values[k] > f)
f = v->values[k]; f = v->values[k];
}
if (!found) {
/* Hmm, so this channel does not exist in the volume
* struct, so let's bind it to the overall max of the
* volume. */
f = pa_cvolume_max(v);
}
if (e->has_dB) { if (e->has_dB) {
long value = to_alsa_dB(f); long value = to_alsa_dB(f);
@ -756,6 +771,9 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
f = from_alsa_volume(value, e->min_volume, e->max_volume); f = from_alsa_volume(value, e->min_volume, e->max_volume);
} }
if (f > max_channel_volume)
max_channel_volume = f;
for (k = 0; k < cm->channels; k++) for (k = 0; k < cm->channels; k++)
if (e->masks[c][e->n_channels-1] & PA_CHANNEL_POSITION_MASK(cm->map[k])) if (e->masks[c][e->n_channels-1] & PA_CHANNEL_POSITION_MASK(cm->map[k]))
if (rv.values[k] < f) if (rv.values[k] < f)
@ -766,7 +784,7 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
for (k = 0; k < cm->channels; k++) for (k = 0; k < cm->channels; k++)
if (!(mask & PA_CHANNEL_POSITION_MASK(cm->map[k]))) if (!(mask & PA_CHANNEL_POSITION_MASK(cm->map[k])))
rv.values[k] = PA_VOLUME_NORM; rv.values[k] = max_channel_volume;
*v = rv; *v = rv;
return 0; return 0;