[pulseaudio-discuss] [PATCH] Hack around a bug in the core causing volumes not to be set on port change.

David Henningsson david.henningsson at canonical.com
Thu Oct 13 08:36:34 PDT 2011


Two problems:
 1) Old volume is lingering in some variables after port change
 2) If there's nothing in m-d-r database, volume is not updated for the new port

After some talk with Colin Guthrie this morning, I believe a better long-term
fix would be to have per port volumes stored in the core, and not retrieving
them from the database on port change, but such a change would be too heavy
for a stable release.
So this is more of a quick hack. 

Signed-off-by: David Henningsson <david.henningsson at canonical.com>
---

Note: I don't know if upstream is interested; if not, see it just as information of
what I'm doing to fixup things downstream (i e Ubuntu 11.10).


diff --git a/src/modules/module-device-restore.c b/src/modules/module-device-restore.c
index de98035..685a691 100644
--- a/src/modules/module-device-restore.c
+++ b/src/modules/module-device-restore.c
@@ -812,6 +812,8 @@ static pa_hook_result_t sink_fixate_hook_callback(pa_core *c, pa_sink_new_data *
 static pa_hook_result_t sink_port_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
     char *name;
     struct perportentry *e;
+    pa_cvolume old_volume;
+    pa_bool_t mute_was_set = FALSE, volume_was_set = FALSE, old_mute;
 
     pa_assert(c);
     pa_assert(sink);
@@ -820,6 +822,12 @@ static pa_hook_result_t sink_port_hook_callback(pa_core *c, pa_sink *sink, struc
 
     name = pa_sprintf_malloc("sink:%s", sink->name);
 
+    /* Hack 1: First pick up the old volumes, then make sure they are not lingering any more */
+    old_volume = *pa_sink_get_volume(sink, FALSE);
+    old_mute = pa_sink_get_mute(sink, FALSE);
+    pa_sink_get_volume(sink, TRUE);
+    pa_sink_get_mute(sink, TRUE);
+
     if ((e = perportentry_read(u, name, (sink->active_port ? sink->active_port->name : NULL)))) {
 
         if (u->restore_volume && e->volume_valid) {
@@ -832,6 +840,7 @@ static pa_hook_result_t sink_port_hook_callback(pa_core *c, pa_sink *sink, struc
             pa_cvolume_remap(&v, &e->channel_map, &sink->channel_map);
             pa_sink_set_volume(sink, &v, TRUE, FALSE);
             sink->save_volume = TRUE;
+            volume_was_set = TRUE;
         }
 
         if (u->restore_muted && e->muted_valid) {
@@ -839,6 +848,7 @@ static pa_hook_result_t sink_port_hook_callback(pa_core *c, pa_sink *sink, struc
             pa_log_info("Restoring mute state for sink %s.", sink->name);
             pa_sink_set_mute(sink, e->muted, FALSE);
             sink->save_muted = TRUE;
+            mute_was_set = TRUE;
         }
 
         perportentry_free(e);
@@ -846,6 +856,12 @@ static pa_hook_result_t sink_port_hook_callback(pa_core *c, pa_sink *sink, struc
 
     pa_xfree(name);
 
+    /* Hack 2: Work around volume not set correctly in core on port change */
+    if (!volume_was_set)
+        pa_sink_set_volume(sink, &old_volume, TRUE, FALSE);
+    if (!mute_was_set)
+        pa_sink_set_mute(sink, old_mute, FALSE);
+
     return PA_HOOK_OK;
 }
 
@@ -953,6 +969,8 @@ static pa_hook_result_t source_fixate_hook_callback(pa_core *c, pa_source_new_da
 static pa_hook_result_t source_port_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
     char *name;
     struct perportentry *e;
+    pa_cvolume old_volume;
+    pa_bool_t mute_was_set = FALSE, volume_was_set = FALSE, old_mute;
 
     pa_assert(c);
     pa_assert(source);
@@ -961,6 +979,12 @@ static pa_hook_result_t source_port_hook_callback(pa_core *c, pa_source *source,
 
     name = pa_sprintf_malloc("source:%s", source->name);
 
+    /* Hack 1: First pick up the old volumes, then make sure they are not lingering any more */
+    old_volume = *pa_source_get_volume(source, FALSE);
+    old_mute = pa_source_get_mute(source, FALSE);
+    pa_source_get_volume(source, TRUE);
+    pa_source_get_mute(source, TRUE);
+
     if ((e = perportentry_read(u, name, (source->active_port ? source->active_port->name : NULL)))) {
 
         if (u->restore_volume && e->volume_valid) {
@@ -973,6 +997,7 @@ static pa_hook_result_t source_port_hook_callback(pa_core *c, pa_source *source,
             pa_cvolume_remap(&v, &e->channel_map, &source->channel_map);
             pa_source_set_volume(source, &v, TRUE, FALSE);
             source->save_volume = TRUE;
+            volume_was_set = TRUE;
         }
 
         if (u->restore_muted && e->muted_valid) {
@@ -980,6 +1005,7 @@ static pa_hook_result_t source_port_hook_callback(pa_core *c, pa_source *source,
             pa_log_info("Restoring mute state for source %s.", source->name);
             pa_source_set_mute(source, e->muted, FALSE);
             source->save_muted = TRUE;
+            mute_was_set = TRUE;
         }
 
         perportentry_free(e);
@@ -987,6 +1013,12 @@ static pa_hook_result_t source_port_hook_callback(pa_core *c, pa_source *source,
 
     pa_xfree(name);
 
+    /* Hack 2: Work around volume not set correctly in core on port change */
+    if (!volume_was_set)
+        pa_source_set_volume(source, &old_volume, TRUE, FALSE);
+    if (!mute_was_set)
+        pa_source_set_mute(source, old_mute, FALSE);
+
     return PA_HOOK_OK;
 }
 
-- 
1.7.5.4



More information about the pulseaudio-discuss mailing list