[pulseaudio-discuss] [PATCH] volumes: Implement options to bypass the base volume system.

Colin Guthrie colin at mageia.org
Thu Sep 8 13:30:00 PDT 2011


When the underlying hardware (typically ALSA) reports that the dB
volume ranges to to a value >0dB, a 'base volume' is automatically
added. This system allows the user to utilise the full range of the
underlying hardware controls (ranging from PA_VOLUME_MIN to
PA_VOLUME_NORM) but still get informed, via UI clues, as to the point
the hardware reports as 0dB (i.e. the point at which your sound should
be unmodified).

Sadly, this system does not work for some users. Sometimes the range
where the volume remains below the underlying 0dB point is very small
(e.g. from 0 to 20%). In this scenario, things are made very awkward for
users as the active range they typically want to adjust is so small.

Added to the above scenario, if the user has flat volumes enabled they
will also get this limited range within application volume controls.

This particular scenario has prompted some applications to implement
their own work arounds to this problem and scale the whole volume range
they expose to the base volume when flat volumes are enabled. This
means that the scale the user sees inside the application will be
different to e.g. the scale given by panel applet volume controls,
OSD displays+volume keys and full blown mixers GUIs.

This inconsistency in applications is what has prompted this feature.
It allows users to choose whether or not they want to expose the base
volume and get the full range of h/w control (as currently), or whether
they would prefer to honour the 0dB of the underlying h/w and set
that to our 0dB point (aka 100%). UIs which honour PA_VOLUME_UI_MAX will
still offer the user some of the additional range their h/w supports
>0dB.

The behaviour remains unchanged by default and users will have to set
the feature manually in daemon.conf. The option is split so the user can
choose to apply it separately for sinks (where the problem is most
visible) and sources.
---
 src/daemon/daemon-conf.c       |    6 ++++++
 src/daemon/daemon-conf.h       |    2 ++
 src/daemon/daemon.conf.in      |    2 ++
 src/daemon/main.c              |    2 ++
 src/modules/alsa/alsa-sink.c   |   17 ++++++++++++-----
 src/modules/alsa/alsa-source.c |   17 ++++++++++++-----
 src/pulsecore/core.h           |    2 ++
 7 files changed, 38 insertions(+), 10 deletions(-)

diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
index c4ee544..5fb10a0 100644
--- a/src/daemon/daemon-conf.c
+++ b/src/daemon/daemon-conf.c
@@ -71,6 +71,8 @@ static const pa_daemon_conf default_conf = {
     .disallow_module_loading = FALSE,
     .disallow_exit = FALSE,
     .flat_volumes = TRUE,
+    .sink_use_base_volume = TRUE,
+    .source_use_base_volume = TRUE,
     .exit_idle_time = 20,
     .scache_idle_time = 20,
     .auto_log_target = 1,
@@ -535,6 +537,8 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
         { "disable-shm",                pa_config_parse_bool,     &c->disable_shm, NULL },
         { "enable-shm",                 pa_config_parse_not_bool, &c->disable_shm, NULL },
         { "flat-volumes",               pa_config_parse_bool,     &c->flat_volumes, NULL },
+        { "sink-use-base-volume",       pa_config_parse_bool,     &c->sink_use_base_volume, NULL },
+        { "source-use-base-volume",     pa_config_parse_bool,     &c->source_use_base_volume, NULL },
         { "lock-memory",                pa_config_parse_bool,     &c->lock_memory, NULL },
         { "enable-sync-volume",         pa_config_parse_bool,     &c->sync_volume, NULL },
         { "exit-idle-time",             pa_config_parse_int,      &c->exit_idle_time, NULL },
@@ -736,6 +740,8 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {
     pa_strbuf_printf(s, "cpu-limit = %s\n", pa_yes_no(!c->no_cpu_limit));
     pa_strbuf_printf(s, "enable-shm = %s\n", pa_yes_no(!c->disable_shm));
     pa_strbuf_printf(s, "flat-volumes = %s\n", pa_yes_no(c->flat_volumes));
+    pa_strbuf_printf(s, "sink-use-base-volume = %s\n", pa_yes_no(c->sink_use_base_volume));
+    pa_strbuf_printf(s, "source-use-base-volume = %s\n", pa_yes_no(c->source_use_base_volume));
     pa_strbuf_printf(s, "lock-memory = %s\n", pa_yes_no(c->lock_memory));
     pa_strbuf_printf(s, "enable-sync-volume = %s\n", pa_yes_no(c->sync_volume));
     pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time);
diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h
index 9fd6aba..e1b7804 100644
--- a/src/daemon/daemon-conf.h
+++ b/src/daemon/daemon-conf.h
@@ -75,6 +75,8 @@ typedef struct pa_daemon_conf {
         log_meta,
         log_time,
         flat_volumes,
+        sink_use_base_volume,
+        source_use_base_volume,
         lock_memory,
         sync_volume;
     pa_server_type_t local_server_type;
diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in
index 6437f8f..dd80cce 100644
--- a/src/daemon/daemon.conf.in
+++ b/src/daemon/daemon.conf.in
@@ -59,6 +59,8 @@ ifelse(@HAVE_DBUS@, 1, [dnl
 ; enable-lfe-remixing = no
 
 ; flat-volumes = yes
+; sink-use-base-volume = yes
+; source-use-base-volume = yes
 
 ifelse(@HAVE_SYS_RESOURCE_H@, 1, [dnl
 ; rlimit-fsize = -1
diff --git a/src/daemon/main.c b/src/daemon/main.c
index e7e5238..bcd879e 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -1029,6 +1029,8 @@ int main(int argc, char *argv[]) {
     c->running_as_daemon = !!conf->daemonize;
     c->disallow_exit = conf->disallow_exit;
     c->flat_volumes = conf->flat_volumes;
+    c->sink_use_base_volume = conf->sink_use_base_volume;
+    c->source_use_base_volume = conf->source_use_base_volume;
 #ifdef HAVE_DBUS
     c->server_type = conf->local_server_type;
 #endif
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 7d205bf..dc4bd52 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -1284,14 +1284,18 @@ static void sink_set_volume_cb(pa_sink *s) {
     pa_assert(u->mixer_path);
     pa_assert(u->mixer_handle);
 
-    /* Shift up by the base volume */
-    pa_sw_cvolume_divide_scalar(&r, &s->real_volume, s->base_volume);
+    if (u->core->sink_use_base_volume)
+        /* Shift up by the base volume */
+        pa_sw_cvolume_divide_scalar(&r, &s->real_volume, s->base_volume);
+    else
+        r = s->real_volume;
 
     if (pa_alsa_path_set_volume(u->mixer_path, u->mixer_handle, &s->channel_map, &r, sync_volume, !sync_volume) < 0)
         return;
 
-    /* Shift down by the base volume, so that 0dB becomes maximum volume */
-    pa_sw_cvolume_multiply_scalar(&r, &r, s->base_volume);
+    if (u->core->sink_use_base_volume)
+        /* Shift down by the base volume, so that 0dB becomes maximum volume */
+        pa_sw_cvolume_multiply_scalar(&r, &r, s->base_volume);
 
     u->hardware_volume = r;
 
@@ -1421,7 +1425,10 @@ static void mixer_volume_init(struct userdata *u) {
             pa_sink_enable_decibel_volume(u->sink, TRUE);
             pa_log_info("Hardware volume ranges from %0.2f dB to %0.2f dB.", u->mixer_path->min_dB, u->mixer_path->max_dB);
 
-            u->sink->base_volume = pa_sw_volume_from_dB(-u->mixer_path->max_dB);
+            if (u->core->sink_use_base_volume)
+                u->sink->base_volume = pa_sw_volume_from_dB(-u->mixer_path->max_dB);
+            else
+                u->sink->base_volume = PA_VOLUME_NORM;
             u->sink->n_volume_steps = PA_VOLUME_NORM+1;
 
             pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(u->sink->base_volume));
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index fa500a1..932db4e 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -1135,14 +1135,18 @@ static void source_set_volume_cb(pa_source *s) {
     pa_assert(u->mixer_path);
     pa_assert(u->mixer_handle);
 
-    /* Shift up by the base volume */
-    pa_sw_cvolume_divide_scalar(&r, &s->real_volume, s->base_volume);
+    if (u->core->source_use_base_volume)
+        /* Shift up by the base volume */
+        pa_sw_cvolume_divide_scalar(&r, &s->real_volume, s->base_volume);
+    else
+        r = s->real_volume;
 
     if (pa_alsa_path_set_volume(u->mixer_path, u->mixer_handle, &s->channel_map, &r, sync_volume, !sync_volume) < 0)
         return;
 
-    /* Shift down by the base volume, so that 0dB becomes maximum volume */
-    pa_sw_cvolume_multiply_scalar(&r, &r, s->base_volume);
+    if (u->core->source_use_base_volume)
+        /* Shift down by the base volume, so that 0dB becomes maximum volume */
+        pa_sw_cvolume_multiply_scalar(&r, &r, s->base_volume);
 
     u->hardware_volume = r;
 
@@ -1272,7 +1276,10 @@ static void mixer_volume_init(struct userdata *u) {
             pa_source_enable_decibel_volume(u->source, TRUE);
             pa_log_info("Hardware volume ranges from %0.2f dB to %0.2f dB.", u->mixer_path->min_dB, u->mixer_path->max_dB);
 
-            u->source->base_volume = pa_sw_volume_from_dB(-u->mixer_path->max_dB);
+            if (u->core->source_use_base_volume)
+                u->source->base_volume = pa_sw_volume_from_dB(-u->mixer_path->max_dB);
+            else
+                u->source->base_volume = PA_VOLUME_NORM;
             u->source->n_volume_steps = PA_VOLUME_NORM+1;
 
             pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(u->source->base_volume));
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index d4639e0..1e93f0d 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -163,6 +163,8 @@ struct pa_core {
     int exit_idle_time, scache_idle_time;
 
     pa_bool_t flat_volumes:1;
+    pa_bool_t sink_use_base_volume:1;
+    pa_bool_t source_use_base_volume:1;
     pa_bool_t disallow_module_loading:1;
     pa_bool_t disallow_exit:1;
     pa_bool_t running_as_daemon:1;
-- 
1.7.6



More information about the pulseaudio-discuss mailing list