[pulseaudio-discuss] [PATCH 4/4] alsa-mixer: Add force-hw-volume flag to alsa profile sets

oku at iki.fi oku at iki.fi
Fri Apr 8 07:18:15 PDT 2011


From: Jyri Sarha <jyri.sarha at nokia.com>

Before this patch, if any of the paths in a path set do not
support HW volume then the HW volume is disabled for the whole
set. In some cases this is a bit drastic measure. For instance,
if all but one of the paths support HW volume and dB there no
problem to pretend that we have HW volume for the whole set. The
path without any mixers to control will just always return 0 dB
and the rest is handled by SW volume. This patch adds a flag to
the mapping section of profile set file to enables this behavior.
---
 src/modules/alsa/alsa-mixer.c                    |   51 ++++++++++++++++++++++
 src/modules/alsa/alsa-mixer.h                    |    3 +
 src/modules/alsa/mixer/profile-sets/default.conf |    3 +
 3 files changed, 57 insertions(+), 0 deletions(-)

diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index f236da0..027c63a 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -2693,6 +2693,7 @@ pa_alsa_path_set *pa_alsa_path_set_new(pa_alsa_mapping *m, pa_alsa_direction_t d
 
     ps = pa_xnew0(pa_alsa_path_set, 1);
     ps->direction = direction;
+    ps->force_hw_volume = m->force_hw_volume;
 
     if (direction == PA_ALSA_DIRECTION_OUTPUT)
         pn = m->output_path_names;
@@ -2816,6 +2817,25 @@ static void path_set_unify(pa_alsa_path_set *ps) {
      * means for now we have to have all paths support volume/mute/dB
      * or none. */
 
+    if (ps->force_hw_volume) {
+        pa_bool_t force_on = TRUE;
+        PA_LLIST_FOREACH(p, ps->paths) {
+            pa_assert(p->probed);
+            if (p->has_volume && !p->has_dB) {
+                pa_log_warn("The path %s has hw volume but lacks dB information, can not apply force-hw-volume flag.",  p->name);
+                force_on = FALSE;
+            }
+        }
+        if (force_on) {
+            pa_log_debug("Successful forced HW volume on path set containing:");
+            PA_LLIST_FOREACH(p, ps->paths) {
+                pa_log_debug("%s %s", p->name, p->has_volume ? "" : "(hw volume forced)");
+                p->has_volume = TRUE;
+                p->has_dB = TRUE;
+            }
+        }
+    }
+
     PA_LLIST_FOREACH(p, ps->paths) {
         pa_assert(p->probed);
 
@@ -3188,6 +3208,36 @@ static int mapping_parse_direction(
     return 0;
 }
 
+static int mapping_parse_force_hw_volume(
+        const char *filename,
+        unsigned line,
+        const char *section,
+        const char *lvalue,
+        const char *rvalue,
+        void *data,
+        void *userdata) {
+
+    pa_alsa_profile_set *ps = userdata;
+    pa_alsa_mapping *m;
+    int b;
+
+    pa_assert(ps);
+
+    if (!(m = mapping_get(ps, section))) {
+        pa_log("[%s:%u] Section name %s invalid.", filename, line, section);
+        return -1;
+    }
+
+    if ((b = pa_parse_boolean(rvalue)) < 0) {
+        pa_log("[%s:%u] Force hw volume invalid of '%s'", filename, line, section);
+        return -1;
+    }
+
+    m->force_hw_volume = b;
+
+    return 0;
+}
+
 static int mapping_parse_description(
         const char *filename,
         unsigned line,
@@ -3778,6 +3828,7 @@ pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel
         { "element-input",          mapping_parse_element,        NULL, NULL },
         { "element-output",         mapping_parse_element,        NULL, NULL },
         { "direction",              mapping_parse_direction,      NULL, NULL },
+        { "force-hw-volume",        mapping_parse_force_hw_volume,NULL, NULL },
 
         /* Shared by [Mapping ...] and [Profile ...] */
         { "description",            mapping_parse_description,    NULL, NULL },
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
index a29aed1..a80dfc6 100644
--- a/src/modules/alsa/alsa-mixer.h
+++ b/src/modules/alsa/alsa-mixer.h
@@ -199,6 +199,7 @@ struct pa_alsa_path_set {
     PA_LLIST_HEAD(pa_alsa_path, paths);
     pa_alsa_direction_t direction;
     pa_bool_t probed:1;
+    pa_bool_t force_hw_volume:1;
 
     /* This is used during parsing only, as a shortcut so that we
      * don't have to iterate the list all the time */
@@ -255,6 +256,8 @@ struct pa_alsa_mapping {
 
     pa_sink *sink;
     pa_source *source;
+
+    pa_bool_t force_hw_volume:1;
 };
 
 struct pa_alsa_profile {
diff --git a/src/modules/alsa/mixer/profile-sets/default.conf b/src/modules/alsa/mixer/profile-sets/default.conf
index 9f7b5f2..560f930 100644
--- a/src/modules/alsa/mixer/profile-sets/default.conf
+++ b/src/modules/alsa/mixer/profile-sets/default.conf
@@ -55,6 +55,9 @@
 ; priority = ...
 ; direction = any | input | output          # Only useful for?
 ;
+; force-hw-volume = no | yes                # Force HW volume on a path sets in profile even if all paths do not support
+;                                           # HW volume. To be able to force the HW volume all paths with HW volume
+;                                           # must have dB info.
 ; [Profile id]
 ; input-mappings = ...                      # Lists mappings for sources on this profile, those mapping must be
 ;                                           # defined in this file too
-- 
1.7.1




More information about the pulseaudio-discuss mailing list