From 8417cac4f6c8036d6ce65efa3df6ae8477f8e3e2 Mon Sep 17 00:00:00 2001 From: Tanu Kaskinen Date: Thu, 22 Mar 2012 11:29:10 +0200 Subject: [PATCH] alsa-mixer: Implement a new path option: "mute-during-activation". --- src/modules/alsa/alsa-mixer.c | 30 +++++++++++++++++++++- src/modules/alsa/alsa-mixer.h | 3 ++- src/modules/alsa/alsa-sink.c | 6 ++--- src/modules/alsa/alsa-source.c | 6 ++--- .../alsa/mixer/paths/analog-output.conf.common | 3 +++ 5 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index ee59dea..8423636 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -1196,7 +1196,7 @@ static int element_set_constant_volume(pa_alsa_element *e, snd_mixer_t *m) { return r; } -int pa_alsa_path_select(pa_alsa_path *p, snd_mixer_t *m) { +int pa_alsa_path_select(pa_alsa_path *p, snd_mixer_t *m, bool device_is_muted) { pa_alsa_element *e; int r = 0; @@ -1206,6 +1206,19 @@ int pa_alsa_path_select(pa_alsa_path *p, snd_mixer_t *m) { pa_log_debug("Activating path %s", p->name); pa_alsa_path_dump(p); + /* First turn on hw mute if available, to avoid noise + * when setting the mixer controls. */ + if (p->mute_during_activation) { + PA_LLIST_FOREACH(e, p->elements) { + if (e->switch_use == PA_ALSA_SWITCH_MUTE) + /* If the muting fails here, that's not a critical problem for + * selecting a path, so we ignore the return value. + * element_set_switch() will print a warning anyway, so this + * won't be a silent failure either. */ + (void) element_set_switch(e, m, FALSE); + } + } + PA_LLIST_FOREACH(e, p->elements) { switch (e->switch_use) { @@ -1244,6 +1257,16 @@ int pa_alsa_path_select(pa_alsa_path *p, snd_mixer_t *m) { return -1; } + /* Finally restore hw mute to the device mute status. */ + if (p->mute_during_activation) { + PA_LLIST_FOREACH(e, p->elements) { + if (e->switch_use == PA_ALSA_SWITCH_MUTE) { + if (element_set_switch(e, m, !device_is_muted) < 0) + return -1; + } + } + } + return 0; } @@ -2353,12 +2376,14 @@ pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa char *fn; int r; const char *n; + bool mute_during_activation = false; pa_config_item items[] = { /* [General] */ { "priority", pa_config_parse_unsigned, NULL, "General" }, { "description", pa_config_parse_string, NULL, "General" }, { "name", pa_config_parse_string, NULL, "General" }, + { "mute-during-activation", pa_config_parse_bool, NULL, "General" }, /* [Option ...] */ { "priority", option_parse_priority, NULL, NULL }, @@ -2395,6 +2420,7 @@ pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa items[0].data = &p->priority; items[1].data = &p->description; items[2].data = &p->name; + items[3].data = &mute_during_activation; if (!paths_dir) paths_dir = get_default_paths_dir(); @@ -2407,6 +2433,8 @@ pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa if (r < 0) goto fail; + p->mute_during_activation = mute_during_activation; + if (path_verify(p) < 0) goto fail; diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h index 111dfaa..6fe9c32 100644 --- a/src/modules/alsa/alsa-mixer.h +++ b/src/modules/alsa/alsa-mixer.h @@ -188,6 +188,7 @@ struct pa_alsa_path { pa_bool_t has_mute:1; pa_bool_t has_volume:1; pa_bool_t has_dB:1; + bool mute_during_activation:1; /* These two are used during probing only */ pa_bool_t has_req_any:1; pa_bool_t req_any_present:1; @@ -229,7 +230,7 @@ int pa_alsa_path_get_volume(pa_alsa_path *p, snd_mixer_t *m, const pa_channel_ma int pa_alsa_path_get_mute(pa_alsa_path *path, snd_mixer_t *m, pa_bool_t *muted); int pa_alsa_path_set_volume(pa_alsa_path *path, snd_mixer_t *m, const pa_channel_map *cm, pa_cvolume *v, pa_bool_t deferred_volume, pa_bool_t write_to_hw); int pa_alsa_path_set_mute(pa_alsa_path *path, snd_mixer_t *m, pa_bool_t muted); -int pa_alsa_path_select(pa_alsa_path *p, snd_mixer_t *m); +int pa_alsa_path_select(pa_alsa_path *p, snd_mixer_t *m, bool device_is_muted); void pa_alsa_path_set_callback(pa_alsa_path *p, snd_mixer_t *m, snd_mixer_elem_callback_t cb, void *userdata); void pa_alsa_path_free(pa_alsa_path *p); diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index 472d66a..a7e543e 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -1461,7 +1461,7 @@ static int sink_set_port_cb(pa_sink *s, pa_device_port *p) { data = PA_DEVICE_PORT_DATA(p); pa_assert_se(u->mixer_path = data->path); - pa_alsa_path_select(u->mixer_path, u->mixer_handle); + pa_alsa_path_select(u->mixer_path, u->mixer_handle, s->muted); mixer_volume_init(u); @@ -1905,7 +1905,7 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) { data = PA_DEVICE_PORT_DATA(u->sink->active_port); u->mixer_path = data->path; - pa_alsa_path_select(data->path, u->mixer_handle); + pa_alsa_path_select(data->path, u->mixer_handle, u->sink->muted); if (data->setting) pa_alsa_setting_select(data->setting, u->mixer_handle); @@ -1918,7 +1918,7 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) { if (u->mixer_path) { /* Hmm, we have only a single path, then let's activate it */ - pa_alsa_path_select(u->mixer_path, u->mixer_handle); + pa_alsa_path_select(u->mixer_path, u->mixer_handle, u->sink->muted); if (u->mixer_path->settings) pa_alsa_setting_select(u->mixer_path->settings, u->mixer_handle); diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c index c27bbc2..616215e 100644 --- a/src/modules/alsa/alsa-source.c +++ b/src/modules/alsa/alsa-source.c @@ -1364,7 +1364,7 @@ static int source_set_port_cb(pa_source *s, pa_device_port *p) { data = PA_DEVICE_PORT_DATA(p); pa_assert_se(u->mixer_path = data->path); - pa_alsa_path_select(u->mixer_path, u->mixer_handle); + pa_alsa_path_select(u->mixer_path, u->mixer_handle, s->muted); mixer_volume_init(u); @@ -1642,7 +1642,7 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) { data = PA_DEVICE_PORT_DATA(u->source->active_port); u->mixer_path = data->path; - pa_alsa_path_select(data->path, u->mixer_handle); + pa_alsa_path_select(data->path, u->mixer_handle, u->source->muted); if (data->setting) pa_alsa_setting_select(data->setting, u->mixer_handle); @@ -1655,7 +1655,7 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) { if (u->mixer_path) { /* Hmm, we have only a single path, then let's activate it */ - pa_alsa_path_select(u->mixer_path, u->mixer_handle); + pa_alsa_path_select(u->mixer_path, u->mixer_handle, u->source->muted); if (u->mixer_path->settings) pa_alsa_setting_select(u->mixer_path->settings, u->mixer_handle); diff --git a/src/modules/alsa/mixer/paths/analog-output.conf.common b/src/modules/alsa/mixer/paths/analog-output.conf.common index e69615d..01835fb 100644 --- a/src/modules/alsa/mixer/paths/analog-output.conf.common +++ b/src/modules/alsa/mixer/paths/analog-output.conf.common @@ -56,6 +56,9 @@ ; [General] ; priority = ... # Priority for this path ; description = ... +; mute-during-activation = yes | no # If this path supports hardware mute, should the hw mute be used while activating this +; # path? In some cases this can reduce extra noises during port switching, while in other +; # cases this can increase such noises. Default: no. ; ; [Properties] # Property list for this path. The list is merged into the port property list. ; = # Each property is defined on its own line. -- 2.7.4