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