]> code.delx.au - pulseaudio/commitdiff
alsa: synthesize volume values more sensibly for channels that are not controllable...
authorLennart Poettering <lennart@poettering.net>
Fri, 19 Jun 2009 00:03:03 +0000 (02:03 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 19 Jun 2009 00:03:03 +0000 (02:03 +0200)
src/modules/alsa/alsa-mixer.c

index def262213ab109bcd039dfc1b862f6f71a9594e7..a5515e1b15c4e8da4b6b8126f826b5818328bfac 100644 (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_selem_channel_id_t c;
     pa_channel_position_mask_t mask = 0;
+    pa_volume_t max_channel_volume = PA_VOLUME_MUTED;
     unsigned k;
 
     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);
         }
 
+        if (f > max_channel_volume)
+            max_channel_volume = f;
+
         for (k = 0; k < cm->channels; k++)
             if (e->masks[c][e->n_channels-1] & PA_CHANNEL_POSITION_MASK(cm->map[k]))
                 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++)
         if (!(mask & PA_CHANNEL_POSITION_MASK(cm->map[k])))
-            v->values[k] = PA_VOLUME_NORM;
+            v->values[k] = max_channel_volume;
 
     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_selem_channel_id_t c;
     pa_channel_position_mask_t mask = 0;
+    pa_volume_t max_channel_volume = PA_VOLUME_MUTED;
     unsigned k;
 
     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++) {
         int r;
         pa_volume_t f = PA_VOLUME_MUTED;
+        pa_bool_t found = FALSE;
 
         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)
                     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) {
             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);
         }
 
+        if (f > max_channel_volume)
+            max_channel_volume = f;
+
         for (k = 0; k < cm->channels; k++)
             if (e->masks[c][e->n_channels-1] & PA_CHANNEL_POSITION_MASK(cm->map[k]))
                 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++)
         if (!(mask & PA_CHANNEL_POSITION_MASK(cm->map[k])))
-            rv.values[k] = PA_VOLUME_NORM;
+            rv.values[k] = max_channel_volume;
 
     *v = rv;
     return 0;