alsa-mixer: Implement a new path option: "mute-during-activation".
authorTanu Kaskinen <tanu.kaskinen@digia.com>
Thu, 22 Mar 2012 09:29:10 +0000 (11:29 +0200)
committerTanu Kaskinen <tanuk@iki.fi>
Fri, 6 Jul 2012 17:38:03 +0000 (20:38 +0300)
src/modules/alsa/alsa-mixer.c
src/modules/alsa/alsa-mixer.h
src/modules/alsa/alsa-sink.c
src/modules/alsa/alsa-source.c
src/modules/alsa/mixer/paths/analog-output.conf.common

index ee59dea014d4b0a283e261aaeac1704f1f51009a..842363602fbf0a24e5b9b633e77a404480a5dacb 100644 (file)
@@ -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;
 
index 111dfaa45188745ba23e1ea1eb36d4d7ce1cd642..6fe9c328a7e44729b1bef323cd1746e7dc75d0a2 100644 (file)
@@ -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);
 
index 472d66a4e88bc51204072eb5de79dbdc1a9575bc..a7e543e7e66579f9583467f07fc7290d34d5ad3f 100644 (file)
@@ -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);
index c27bbc2b79c83e23eef50bae9486b43689ec6bdb..616215e9583f887949e8e9d8ade11f6026fd820f 100644 (file)
@@ -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);
index e69615d4735bced4c9cb9044efafebd8dbfacfb7..01835fbc83f832590e3c4211162dbc423c13655f 100644 (file)
@@ -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.
 ; <key> = <value>                        # Each property is defined on its own line.