Fall back to software volume if hardware mixer cannot control all channels.
authorPierre Ossman <ossman@cendio.se>
Tue, 25 Apr 2006 07:54:49 +0000 (07:54 +0000)
committerPierre Ossman <ossman@cendio.se>
Tue, 25 Apr 2006 07:54:49 +0000 (07:54 +0000)
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@796 fefdeb5f-60dc-0310-8127-8f9354f1896f

src/modules/module-alsa-sink.c
src/modules/module-alsa-source.c

index e2e593d..ecdf8cb 100644 (file)
@@ -201,25 +201,18 @@ static int sink_get_hw_volume_cb(pa_sink *s) {
     struct userdata *u = s->userdata;
     long vol;
     int err;
+    int i;
 
     assert(u && u->mixer_elem);
 
-    if (snd_mixer_selem_has_playback_volume_joined(u->mixer_elem)) {
-        err = snd_mixer_selem_get_playback_volume(u->mixer_elem, 0, &vol);
+    for (i = 0;i < s->hw_volume.channels;i++) {
+        assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i));
+
+        err = snd_mixer_selem_get_playback_volume(u->mixer_elem, i, &vol);
         if (err < 0)
             goto fail;
-        pa_cvolume_set(&s->hw_volume, s->hw_volume.channels,
-            (vol - u->hw_volume_min) * PA_VOLUME_NORM / (u->hw_volume_max - u->hw_volume_min));
-    } else {
-        int i;
-
-        for (i = 0;i < s->hw_volume.channels;i++) {
-            err = snd_mixer_selem_get_playback_volume(u->mixer_elem, i, &vol);
-            if (err < 0)
-                goto fail;
-            s->hw_volume.values[i] =
-                (vol - u->hw_volume_min) * PA_VOLUME_NORM / (u->hw_volume_max - u->hw_volume_min);
-        }
+        s->hw_volume.values[i] =
+            (vol - u->hw_volume_min) * PA_VOLUME_NORM / (u->hw_volume_max - u->hw_volume_min);
     }
 
     return 0;
@@ -234,37 +227,25 @@ fail:
 static int sink_set_hw_volume_cb(pa_sink *s) {
     struct userdata *u = s->userdata;
     int err;
+    int i;
     pa_volume_t vol;
 
     assert(u && u->mixer_elem);
 
-    if (snd_mixer_selem_has_playback_volume_joined(u->mixer_elem)) {
-        vol = pa_cvolume_avg(&s->hw_volume);
+    for (i = 0;i < s->hw_volume.channels;i++) {
+        assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i));
+
+        vol = s->hw_volume.values[i];
 
         if (vol > PA_VOLUME_NORM)
             vol = PA_VOLUME_NORM;
         
         vol = (vol * (u->hw_volume_max - u->hw_volume_min)) /
             PA_VOLUME_NORM + u->hw_volume_min;
-        
-        err = snd_mixer_selem_set_playback_volume_all(u->mixer_elem, vol);
+
+        err = snd_mixer_selem_set_playback_volume(u->mixer_elem, i, vol);
         if (err < 0)
             goto fail;
-    } else {
-        int i;
-
-        for (i = 0;i < s->hw_volume.channels;i++) {
-            vol = s->hw_volume.values[i];
-
-            if (vol > PA_VOLUME_NORM)
-                vol = PA_VOLUME_NORM;
-            
-             vol = (vol * (u->hw_volume_max - u->hw_volume_min)) /
-                PA_VOLUME_NORM + u->hw_volume_min;
-            err = snd_mixer_selem_set_playback_volume(u->mixer_elem, i, vol);
-            if (err < 0)
-                goto fail;
-        }
     }
 
     return 0;
@@ -383,10 +364,19 @@ int pa__init(pa_core *c, pa_module*m) {
     if (u->mixer_handle) {
         assert(u->mixer_elem);
         if (snd_mixer_selem_has_playback_volume(u->mixer_elem)) {
-            u->sink->get_hw_volume = sink_get_hw_volume_cb;
-            u->sink->set_hw_volume = sink_set_hw_volume_cb;
-            snd_mixer_selem_get_playback_volume_range(
-                u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max);
+            int i;
+
+            for (i = 0;i < ss.channels;i++) {
+                if (!snd_mixer_selem_has_playback_channel(u->mixer_elem, i))
+                    break;
+            }
+
+            if (i == ss.channels) {
+                u->sink->get_hw_volume = sink_get_hw_volume_cb;
+                u->sink->set_hw_volume = sink_set_hw_volume_cb;
+                snd_mixer_selem_get_playback_volume_range(
+                    u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max);
+            }
         }
         if (snd_mixer_selem_has_playback_switch(u->mixer_elem)) {
             u->sink->get_hw_mute = sink_get_hw_mute_cb;
index 2ee1619..7a36528 100644 (file)
@@ -190,25 +190,18 @@ static int source_get_hw_volume_cb(pa_source *s) {
     struct userdata *u = s->userdata;
     long vol;
     int err;
+    int i;
 
     assert(u && u->mixer_elem);
 
-    if (snd_mixer_selem_has_capture_volume_joined(u->mixer_elem)) {
-        err = snd_mixer_selem_get_capture_volume(u->mixer_elem, 0, &vol);
+    for (i = 0;i < s->hw_volume.channels;i++) {
+        assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, i));
+
+        err = snd_mixer_selem_get_capture_volume(u->mixer_elem, i, &vol);
         if (err < 0)
             goto fail;
-        pa_cvolume_set(&s->hw_volume, s->hw_volume.channels,
-            (vol - u->hw_volume_min) * PA_VOLUME_NORM / (u->hw_volume_max - u->hw_volume_min));
-    } else {
-        int i;
-
-        for (i = 0;i < s->hw_volume.channels;i++) {
-            err = snd_mixer_selem_get_capture_volume(u->mixer_elem, i, &vol);
-            if (err < 0)
-                goto fail;
-            s->hw_volume.values[i] =
-                (vol - u->hw_volume_min) * PA_VOLUME_NORM / (u->hw_volume_max - u->hw_volume_min);
-        }
+        s->hw_volume.values[i] =
+            (vol - u->hw_volume_min) * PA_VOLUME_NORM / (u->hw_volume_max - u->hw_volume_min);
     }
 
     return 0;
@@ -224,35 +217,23 @@ static int source_set_hw_volume_cb(pa_source *s) {
     struct userdata *u = s->userdata;
     int err;
     pa_volume_t vol;
+    int i;
 
     assert(u && u->mixer_elem);
 
-    if (snd_mixer_selem_has_capture_volume_joined(u->mixer_elem)) {
-        vol = pa_cvolume_avg(&s->hw_volume);
+    for (i = 0;i < s->hw_volume.channels;i++) {
+        assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, i));
+
+        vol = s->hw_volume.values[i];
 
         if (vol > PA_VOLUME_NORM)
             vol = PA_VOLUME_NORM;
 
         vol = vol * (u->hw_volume_max - u->hw_volume_min) /
             PA_VOLUME_NORM + u->hw_volume_min;
-        err = snd_mixer_selem_set_capture_volume_all(u->mixer_elem, vol);
+        err = snd_mixer_selem_set_capture_volume(u->mixer_elem, i, vol);
         if (err < 0)
             goto fail;
-    } else {
-        int i;
-
-        for (i = 0;i < s->hw_volume.channels;i++) {
-            vol = s->hw_volume.values[i];
-
-            if (vol > PA_VOLUME_NORM)
-                vol = PA_VOLUME_NORM;
-
-            vol = vol * (u->hw_volume_max - u->hw_volume_min) /
-                PA_VOLUME_NORM + u->hw_volume_min;
-            err = snd_mixer_selem_set_capture_volume(u->mixer_elem, i, vol);
-            if (err < 0)
-                goto fail;
-        }
     }
 
     return 0;
@@ -372,10 +353,19 @@ int pa__init(pa_core *c, pa_module*m) {
     if (u->mixer_handle) {
         assert(u->mixer_elem);
         if (snd_mixer_selem_has_capture_volume(u->mixer_elem)) {
-            u->source->get_hw_volume = source_get_hw_volume_cb;
-            u->source->set_hw_volume = source_set_hw_volume_cb;
-            snd_mixer_selem_get_capture_volume_range(
-                u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max);
+            int i;
+
+            for (i = 0;i < ss.channels;i++) {
+                if (!snd_mixer_selem_has_capture_channel(u->mixer_elem, i))
+                    break;
+            }
+
+            if (i == ss.channels) {
+                u->source->get_hw_volume = source_get_hw_volume_cb;
+                u->source->set_hw_volume = source_set_hw_volume_cb;
+                snd_mixer_selem_get_capture_volume_range(
+                    u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max);
+            }
         }
         if (snd_mixer_selem_has_capture_switch(u->mixer_elem)) {
             u->source->get_hw_mute = source_get_hw_mute_cb;