diff --git a/src/modules/module-switch-on-connect.c b/src/modules/module-switch-on-connect.c index e56774b00..42d0e586f 100644 --- a/src/modules/module-switch-on-connect.c +++ b/src/modules/module-switch-on-connect.c @@ -116,9 +116,6 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, void* } static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, void* userdata) { - pa_source_output *o; - uint32_t idx; - pa_source *old_default_source; const char *s; struct userdata *u = userdata; @@ -172,29 +169,9 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, return PA_HOOK_OK; } - old_default_source = c->default_source; - /* Actually do the switch to the new source */ pa_core_set_configured_default_source(c, source->name); - /* Now move all old outputs over */ - if (pa_idxset_size(old_default_source->outputs) <= 0) { - pa_log_debug("No source outputs to move away."); - return PA_HOOK_OK; - } - - PA_IDXSET_FOREACH(o, old_default_source->outputs, idx) { - if (pa_safe_streq(o->source->name, o->preferred_source) || !PA_SOURCE_OUTPUT_IS_LINKED(o->state)) - continue; - - if (pa_source_output_move_to(o, source, 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)), source->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)), source->name); - } - return PA_HOOK_OK; } diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 87ccebb0a..76a2202a5 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -435,6 +435,10 @@ void pa_core_update_default_source(pa_core *core) { old_default_source ? old_default_source->name : "(unset)", best ? best->name : "(unset)"); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SERVER | PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX); pa_hook_fire(&core->hooks[PA_CORE_HOOK_DEFAULT_SOURCE_CHANGED], core->default_source); + + /* 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); } void pa_core_set_exit_idle_time(pa_core *core, int time) { diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 855d3de0e..ed771b48c 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -666,8 +666,10 @@ void pa_source_put(pa_source *s) { pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index); pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PUT], s); - /* This function must be called after the PA_CORE_HOOK_SOURCE_PUT hook, - * because module-switch-on-connect needs to know the old default source */ + /* It's good to fire the SOURCE_PUT hook before updating the default source, + * because module-switch-on-connect will set the new source as the default + * source, and if we were to call pa_core_update_default_source() before that, + * the default source might change twice, causing unnecessary stream moving. */ pa_core_update_default_source(s->core); } @@ -2988,3 +2990,36 @@ void pa_source_set_reference_volume_direct(pa_source *s, const pa_cvolume *volum pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); 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) { + pa_source_output *o; + uint32_t idx; + bool old_source_is_unavailable = false; + + pa_assert(core); + pa_assert(old_source); + + if (core->default_source == NULL || core->default_source->unlink_requested) + return; + + if (old_source == core->default_source) + return; + + if (old_source->active_port && old_source->active_port->available == PA_AVAILABLE_NO) + old_source_is_unavailable = true; + + PA_IDXSET_FOREACH(o, old_source->outputs, idx) { + if (!PA_SOURCE_OUTPUT_IS_LINKED(o->state)) + continue; + + if (!o->source) + continue; + + 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); + pa_source_output_move_to(o, core->default_source, false); + } +} diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h index e9462c63b..d6d25367f 100644 --- a/src/pulsecore/source.h +++ b/src/pulsecore/source.h @@ -479,6 +479,12 @@ int64_t pa_source_get_latency_within_thread(pa_source *s, bool allow_negative); * sets s->reference_volume and fires change notifications. */ void pa_source_set_reference_volume_direct(pa_source *s, const pa_cvolume *volume); +/* When the default_source is changed or the active_port of a source is changed to + * 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); + #define pa_source_assert_io_context(s) \ pa_assert(pa_thread_mq_get() || !PA_SOURCE_IS_LINKED((s)->state))