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

Maarten Bosmans mkbosmans at gmail.com
Fri Sep 9 00:58:56 PDT 2011


Thanks for the explanation, it's a lot clearer now than when you tried
to do it on IRC.

2011/9/8 Colin Guthrie <colin at mageia.org>:
> 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).

Indeed, I just discovered that I also have such hardware (PCM has 12
dB of overhead above 0 dB). Do we have any idea how common this is and
whether most alsa drivers report the dBs correctly now?

I would very much like to have this mode the default (eventually,
probably not pre-1.0), because it seems a lot more useful to me.

> 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.

Is a (disabled by default) per user preference enough to make
applications stop implementing the different volume scale? This looks
like a candidate for paprefs to me.

Perhaps, in order to still expose the whole hw volume in the new mode,
we could make PA_VOLUME_UI_MAX the maximum of the current value and
the maximum hardware volume setting. (ignoring any implementation
difficulties for the moment)

> 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.

As David said, this might not be a good thing for sources. Let me
apply the patch and play with it a bit this weekend.

> ---
>  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
>
> _______________________________________________
> pulseaudio-discuss mailing list
> pulseaudio-discuss at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss
>


More information about the pulseaudio-discuss mailing list