From 5e0d5a86822caf56f9d36b1363f007dd45b48c37 Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Tue, 10 Dec 2019 16:26:34 +0800 Subject: [PATCH] source: move the streams to the default_source when the source unlink When a source is unlinked, all streams of this source are moved to default_source, this action is implemented in the core rather than modules now. And after this change, the module-rescue-streams is not needed, but for backward compatibility, we keep it as a dummy module. Signed-off-by: Hui Wang --- src/daemon/default.pa.in | 4 - src/daemon/system.pa.in | 4 - src/modules/module-device-manager.c | 2 +- src/modules/module-filter-apply.c | 6 +- src/modules/module-intended-roles.c | 2 +- src/modules/module-rescue-streams.c | 183 +-------------------------------- src/modules/module-stream-restore.c | 74 ++----------- src/modules/module-switch-on-connect.c | 1 - src/pulsecore/core.c | 2 +- src/pulsecore/device-port.c | 2 +- src/pulsecore/source.c | 20 +++- src/pulsecore/source.h | 2 +- 12 files changed, 35 insertions(+), 267 deletions(-) diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in index 14b6a6f..030334f 100755 --- a/src/daemon/default.pa.in +++ b/src/daemon/default.pa.in @@ -138,10 +138,6 @@ load-module module-gconf ### that look up the default sink/source get the right value load-module module-default-device-restore -### Automatically move streams to the default sink if the sink they are -### connected to dies, similar for sources -load-module module-rescue-streams - ### Make sure we always have a sink around, even if it is a null sink. load-module module-always-sink diff --git a/src/daemon/system.pa.in b/src/daemon/system.pa.in index b1a4a5c..73e39ec 100755 --- a/src/daemon/system.pa.in +++ b/src/daemon/system.pa.in @@ -52,10 +52,6 @@ load-module module-native-protocol-unix ### that look up the default sink/source get the right value load-module module-default-device-restore -### Automatically move streams to the default sink if the sink they are -### connected to dies, similar for sources -load-module module-rescue-streams - ### Make sure we always have a sink around, even if it is a null sink. load-module module-always-sink diff --git a/src/modules/module-device-manager.c b/src/modules/module-device-manager.c index 5a9995c..308ef0b 100644 --- a/src/modules/module-device-manager.c +++ b/src/modules/module-device-manager.c @@ -1596,7 +1596,7 @@ int pa__init(pa_module*m) { } if (on_rescue) { - /* A little bit later than module-stream-restore, a little bit earlier than module-intended-roles, module-rescue-streams, ... */ + /* A little bit later than module-stream-restore, a little bit earlier than module-intended-roles, ... */ u->sink_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE+5, (pa_hook_cb_t) sink_unlink_hook_callback, u); u->source_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE+5, (pa_hook_cb_t) source_unlink_hook_callback, u); } diff --git a/src/modules/module-filter-apply.c b/src/modules/module-filter-apply.c index faeedcb..c9f3f39 100644 --- a/src/modules/module-filter-apply.c +++ b/src/modules/module-filter-apply.c @@ -687,8 +687,7 @@ static pa_hook_result_t sink_unlink_cb(pa_core *core, pa_sink *sink, struct user uint32_t idx; /* Attempt to rescue any streams to the parent sink as this is likely - * the best course of action (as opposed to a generic rescue via - * module-rescue-streams */ + * the best course of action */ if (filter->sink == sink) { pa_sink_input *i; @@ -769,8 +768,7 @@ static pa_hook_result_t source_unlink_cb(pa_core *core, pa_source *source, struc uint32_t idx; /* Attempt to rescue any streams to the parent source as this is likely - * the best course of action (as opposed to a generic rescue via - * module-rescue-streams */ + * the best course of action */ if (filter->source == source) { pa_source_output *o; diff --git a/src/modules/module-intended-roles.c b/src/modules/module-intended-roles.c index 434ad30..2269c0d 100644 --- a/src/modules/module-intended-roles.c +++ b/src/modules/module-intended-roles.c @@ -398,7 +398,7 @@ int pa__init(pa_module*m) { } if (on_rescue) { - /* A little bit later than module-stream-restore, a little bit earlier than module-rescue-streams, ... */ + /* A little bit later than module-stream-restore, ... */ u->sink_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE+10, (pa_hook_cb_t) sink_unlink_hook_callback, u); u->source_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE+10, (pa_hook_cb_t) source_unlink_hook_callback, u); } diff --git a/src/modules/module-rescue-streams.c b/src/modules/module-rescue-streams.c index a21b95a..ac95896 100644 --- a/src/modules/module-rescue-streams.c +++ b/src/modules/module-rescue-streams.c @@ -24,200 +24,23 @@ #include #include -#include -#include #include #include #include PA_MODULE_AUTHOR("Lennart Poettering"); -PA_MODULE_DESCRIPTION("When a source is removed, try to move its streams to the default source"); +PA_MODULE_DESCRIPTION("This module is obsolete, please remove it from your configuration."); PA_MODULE_VERSION(PACKAGE_VERSION); PA_MODULE_LOAD_ONCE(true); -static const char* const valid_modargs[] = { - NULL, -}; - -struct userdata { - pa_hook_slot - *source_unlink_slot, - *source_output_move_fail_slot; -}; - -static pa_source* find_source_from_port(pa_core *c, pa_device_port *port) { - pa_source *target; - uint32_t idx; - void *state; - pa_device_port *p; - - if (!port) - return NULL; - - PA_IDXSET_FOREACH(target, c->sources, idx) - PA_HASHMAP_FOREACH(p, target->ports, state) - if (port == p) - return target; - - return NULL; -} - -static void build_group_ports(pa_hashmap *g_ports, pa_hashmap *s_ports) { - void *state; - pa_device_port *p; - - if (!g_ports || !s_ports) - return; - - PA_HASHMAP_FOREACH(p, s_ports, state) - pa_hashmap_put(g_ports, p, p); -} - -static pa_source* find_evacuation_source(pa_core *c, pa_source_output *o, pa_source *skip) { - pa_source *target, *fb_source = NULL; - uint32_t idx; - pa_hashmap *all_ports; - pa_device_port *best_port; - - pa_assert(c); - pa_assert(o); - - if (c->default_source && c->default_source != skip && pa_source_output_may_move_to(o, c->default_source)) - return c->default_source; - - all_ports = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); - - PA_IDXSET_FOREACH(target, c->sources, idx) { - if (target == c->default_source) - continue; - - if (target == skip) - continue; - - /* We only move to a monitor source if we're already on one */ - if (skip && !target->monitor_of != !skip->monitor_of) - continue; - - if (!PA_SOURCE_IS_LINKED(target->state)) - continue; - - if (!pa_source_output_may_move_to(o, target)) - continue; - - if (!fb_source) - fb_source = target; - - build_group_ports(all_ports, target->ports); - } - - best_port = pa_device_port_find_best(all_ports); - - pa_hashmap_free(all_ports); - - if (best_port) - target = find_source_from_port(c, best_port); - else - target = fb_source; - - if (!target) - pa_log_debug("No evacuation source found."); - - return target; -} - -static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, void* userdata) { - pa_source_output *o; - uint32_t idx; - - pa_assert(c); - pa_assert(source); - - /* There's no point in doing anything if the core is shut down anyway */ - if (c->state == PA_CORE_SHUTDOWN) - return PA_HOOK_OK; - - if (pa_idxset_size(source->outputs) <= 0) { - pa_log_debug("No source outputs to move away."); - return PA_HOOK_OK; - } - - PA_IDXSET_FOREACH(o, source->outputs, idx) { - pa_source *target; - - if (!(target = find_evacuation_source(c, o, source))) - continue; - - if (pa_source_output_move_to(o, target, false) < 0) - pa_log_info("Failed to move source output %u \"%s\" to %s.", o->index, - pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_APPLICATION_NAME)), target->name); - else - pa_log_info("Successfully moved source output %u \"%s\" to %s.", o->index, - pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_APPLICATION_NAME)), target->name); - } - - return PA_HOOK_OK; -} - -static pa_hook_result_t source_output_move_fail_hook_callback(pa_core *c, pa_source_output *i, void *userdata) { - pa_source *target; - - pa_assert(c); - pa_assert(i); - - /* There's no point in doing anything if the core is shut down anyway */ - if (c->state == PA_CORE_SHUTDOWN) - return PA_HOOK_OK; - - if (!(target = find_evacuation_source(c, i, NULL))) - return PA_HOOK_OK; - - if (pa_source_output_finish_move(i, target, false) < 0) { - pa_log_info("Failed to move source output %u \"%s\" to %s.", i->index, - pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), target->name); - return PA_HOOK_OK; - - } else { - pa_log_info("Successfully moved source output %u \"%s\" to %s.", i->index, - pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), target->name); - return PA_HOOK_STOP; - } -} int pa__init(pa_module*m) { - pa_modargs *ma; - struct userdata *u; pa_assert(m); - if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log("Failed to parse module arguments"); - return -1; - } - - m->userdata = u = pa_xnew(struct userdata, 1); + pa_log("module-rescue-stream is obsolete and should no longer be loaded. Please remove it from your configuration."); - /* A little bit later than module-stream-restore, module-intended-roles... */ - u->source_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE+20, (pa_hook_cb_t) source_unlink_hook_callback, u); + pa_module_unload_request(m, false); - u->source_output_move_fail_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FAIL], PA_HOOK_LATE+20, (pa_hook_cb_t) source_output_move_fail_hook_callback, u); - - pa_modargs_free(ma); return 0; } - -void pa__done(pa_module*m) { - struct userdata *u; - - pa_assert(m); - - if (!(u = m->userdata)) - return; - - if (u->source_unlink_slot) - pa_hook_slot_free(u->source_unlink_slot); - - if (u->source_output_move_fail_slot) - pa_hook_slot_free(u->source_output_move_fail_slot); - - pa_xfree(u); -} diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index 0eb6028..9a66bef 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -65,7 +65,7 @@ PA_MODULE_USAGE( "restore_volume= " "restore_muted= " "on_hotplug= " - "on_rescue= " + "on_rescue= " "fallback_table="); #define SAVE_INTERVAL (10 * PA_USEC_PER_SEC) @@ -95,7 +95,6 @@ struct userdata { *sink_input_fixate_hook_slot, *source_output_new_hook_slot, *source_output_fixate_hook_slot, - *source_unlink_hook_slot, *connection_unlink_hook_slot; pa_time_event *save_time_event; pa_database* database; @@ -103,7 +102,6 @@ struct userdata { bool restore_device:1; bool restore_volume:1; bool restore_muted:1; - bool on_rescue:1; pa_native_protocol *protocol; pa_idxset *subscribed; @@ -1641,57 +1639,6 @@ static pa_hook_result_t source_output_fixate_hook_callback(pa_core *c, pa_source return PA_HOOK_OK; } -static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, struct userdata *u) { - pa_source_output *so; - uint32_t idx; - - pa_assert(c); - pa_assert(source); - pa_assert(u); - pa_assert(u->on_rescue && u->restore_device); - - /* There's no point in doing anything if the core is shut down anyway */ - if (c->state == PA_CORE_SHUTDOWN) - return PA_HOOK_OK; - - PA_IDXSET_FOREACH(so, source->outputs, idx) { - char *name; - struct entry *e; - - if (so->direct_on_input) - continue; - - if (!so->source) - continue; - - /* Skip this source output if it is connecting a filter source to - * the master */ - if (so->destination_source) - continue; - - if (!(name = pa_proplist_get_stream_group(so->proplist, "source-output", IDENTIFICATION_PROPERTY))) - continue; - - if ((e = entry_read(u, name))) { - - if (e->device_valid) { - pa_source *d; - - if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE)) && - d != source && - PA_SOURCE_IS_LINKED(d->state)) - pa_source_output_move_to(so, d, true); - } - - entry_free(e); - } - - pa_xfree(name); - } - - return PA_HOOK_OK; -} - static int fill_db(struct userdata *u, const char *filename) { FILE *f; int n = 0; @@ -2271,7 +2218,8 @@ int pa__init(pa_module*m) { pa_sink_input *si; pa_source_output *so; uint32_t idx; - bool restore_device = true, restore_volume = true, restore_muted = true, on_rescue = true; + bool restore_device = true, restore_volume = true, restore_muted = true; + #ifdef HAVE_DBUS pa_datum key; bool done; @@ -2286,14 +2234,14 @@ int pa__init(pa_module*m) { if (pa_modargs_get_value_boolean(ma, "restore_device", &restore_device) < 0 || pa_modargs_get_value_boolean(ma, "restore_volume", &restore_volume) < 0 || - pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0 || - pa_modargs_get_value_boolean(ma, "on_rescue", &on_rescue) < 0) { - pa_log("restore_device=, restore_volume=, restore_muted= and on_rescue= expect boolean arguments"); + pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0) { + pa_log("restore_device=, restore_volume= and restore_muted= expect boolean arguments"); goto fail; } - if (pa_modargs_get_value(ma, "on_hotplug", NULL) != NULL) - pa_log("on_hotplug is an obsolete argument, please remove it from your configuration"); + if (pa_modargs_get_value(ma, "on_hotplug", NULL) != NULL || + pa_modargs_get_value(ma, "on_rescue", NULL) != NULL) + pa_log("on_hotplug and on_rescue are obsolete arguments, please remove them from your configuration"); if (!restore_muted && !restore_volume && !restore_device) pa_log_warn("Neither restoring volume, nor restoring muted, nor restoring device enabled!"); @@ -2304,7 +2252,6 @@ int pa__init(pa_module*m) { u->restore_device = restore_device; u->restore_volume = restore_volume; u->restore_muted = restore_muted; - u->on_rescue = on_rescue; u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); u->protocol = pa_native_protocol_get(m->core); @@ -2320,11 +2267,6 @@ int pa__init(pa_module*m) { pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) source_output_new_hook_callback, u); } - if (restore_device && on_rescue) { - /* A little bit earlier than module-intended-roles, module-rescue-streams, ... */ - pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) source_unlink_hook_callback, u); - } - if (restore_volume || restore_muted) { pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) sink_input_fixate_hook_callback, u); pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) source_output_fixate_hook_callback, u); diff --git a/src/modules/module-switch-on-connect.c b/src/modules/module-switch-on-connect.c index 42d0e58..583b645 100644 --- a/src/modules/module-switch-on-connect.c +++ b/src/modules/module-switch-on-connect.c @@ -188,7 +188,6 @@ int pa__init(pa_module*m) { m->userdata = u = pa_xnew0(struct userdata, 1); - /* A little bit later than module-rescue-streams... */ pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE+30, (pa_hook_cb_t) sink_put_hook_callback, u); pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE+20, (pa_hook_cb_t) source_put_hook_callback, u); diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index dbed350..335f802 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -438,7 +438,7 @@ void pa_core_update_default_source(pa_core *core) { /* try to move the streams from old_default_source to the new default_source conditionally */ if (old_default_source) - pa_source_move_streams_to_default_source(core, old_default_source); + pa_source_move_streams_to_default_source(core, old_default_source, true); } void pa_core_set_exit_idle_time(pa_core *core, int time) { diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c index 5863d7f..92f1924 100644 --- a/src/pulsecore/device-port.c +++ b/src/pulsecore/device-port.c @@ -116,7 +116,7 @@ void pa_device_port_set_available(pa_device_port *p, pa_available_t status) { source = pa_device_port_get_source(p); if (source && p == source->active_port) { if (source->active_port->available == PA_AVAILABLE_NO) - pa_source_move_streams_to_default_source(p->core, source); + pa_source_move_streams_to_default_source(p->core, source, false); else pa_core_move_streams_to_newly_available_preferred_source(p->core, source); } diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index e08d4a4..84ae467 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -702,6 +702,9 @@ void pa_source_unlink(pa_source *s) { pa_core_update_default_source(s->core); + if (linked) + pa_source_move_streams_to_default_source(s->core, s, false); + if (s->card) pa_idxset_remove_by_data(s->card->sources, s, NULL); @@ -2993,7 +2996,7 @@ void pa_source_set_reference_volume_direct(pa_source *s, const pa_cvolume *volum pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_VOLUME_CHANGED], s); } -void pa_source_move_streams_to_default_source(pa_core *core, pa_source *old_source) { +void pa_source_move_streams_to_default_source(pa_core *core, pa_source *old_source, bool default_source_changed) { pa_source_output *o; uint32_t idx; bool old_source_is_unavailable = false; @@ -3001,6 +3004,9 @@ void pa_source_move_streams_to_default_source(pa_core *core, pa_source *old_sour pa_assert(core); pa_assert(old_source); + if (core->state == PA_CORE_SHUTDOWN) + return; + if (core->default_source == NULL || core->default_source->unlink_requested) return; @@ -3020,8 +3026,16 @@ void pa_source_move_streams_to_default_source(pa_core *core, pa_source *old_sour if (pa_safe_streq(old_source->name, o->preferred_source) && !old_source_is_unavailable) continue; - pa_log_info("The source output %u \"%s\" is moving to %s due to change of the default source.", - o->index, pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_APPLICATION_NAME)), core->default_source->name); + if (!pa_source_output_may_move_to(o, core->default_source)) + continue; + + if (default_source_changed) + pa_log_info("The source output %u \"%s\" is moving to %s due to change of the default source.", + o->index, pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_APPLICATION_NAME)), core->default_source->name); + else + pa_log_info("The source output %u \"%s\" is moving to %s due to unlink of a source.", + o->index, pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_APPLICATION_NAME)), core->default_source->name); + pa_source_output_move_to(o, core->default_source, false); } } diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h index d6d2536..12e37d6 100644 --- a/src/pulsecore/source.h +++ b/src/pulsecore/source.h @@ -483,7 +483,7 @@ void pa_source_set_reference_volume_direct(pa_source *s, const pa_cvolume *volum * PA_AVAILABLE_NO, this function is called to move the streams of the old * default_source or the source with active_port equals PA_AVAILABLE_NO to the * current default_source conditionally*/ -void pa_source_move_streams_to_default_source(pa_core *core, pa_source *old_source); +void pa_source_move_streams_to_default_source(pa_core *core, pa_source *old_source, bool default_source_changed); #define pa_source_assert_io_context(s) \ pa_assert(pa_thread_mq_get() || !PA_SOURCE_IS_LINKED((s)->state)) -- 2.7.4