mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	core: move source-outputs conditionally when update default_source
When the default source changes, the streams from the old default source should be moved to the new default source, unless the preferred_source string is set to the old default source and the active port of the old default source is not unavailable Signed-off-by: Hui Wang <hui.wang@canonical.com>
This commit is contained in:
		
							parent
							
								
									70bbbcdc84
								
							
						
					
					
						commit
						c254f8405c
					
				
					 4 changed files with 47 additions and 25 deletions
				
			
		| 
						 | 
					@ -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) {
 | 
					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;
 | 
					    const char *s;
 | 
				
			||||||
    struct userdata *u = userdata;
 | 
					    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;
 | 
					            return PA_HOOK_OK;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    old_default_source = c->default_source;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* Actually do the switch to the new source */
 | 
					    /* Actually do the switch to the new source */
 | 
				
			||||||
    pa_core_set_configured_default_source(c, source->name);
 | 
					    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;
 | 
					    return PA_HOOK_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)");
 | 
					                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_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);
 | 
					    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) {
 | 
					void pa_core_set_exit_idle_time(pa_core *core, int time) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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_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);
 | 
					    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,
 | 
					    /* It's good to fire the SOURCE_PUT hook before updating the default source,
 | 
				
			||||||
     * because module-switch-on-connect needs to know the old 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);
 | 
					    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_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);
 | 
					    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);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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. */
 | 
					 * sets s->reference_volume and fires change notifications. */
 | 
				
			||||||
void pa_source_set_reference_volume_direct(pa_source *s, const pa_cvolume *volume);
 | 
					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) \
 | 
					#define pa_source_assert_io_context(s) \
 | 
				
			||||||
    pa_assert(pa_thread_mq_get() || !PA_SOURCE_IS_LINKED((s)->state))
 | 
					    pa_assert(pa_thread_mq_get() || !PA_SOURCE_IS_LINKED((s)->state))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue