mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	source: move streams to new appeared sources if they prefer these sources
When a new source appears, all streams that have their preferred_source set to the new source should be moved to the new source. Signed-off-by: Hui Wang <hui.wang@canonical.com>
This commit is contained in:
		
							parent
							
								
									c254f8405c
								
							
						
					
					
						commit
						1cea7ab38d
					
				
					 4 changed files with 45 additions and 65 deletions
				
			
		| 
						 | 
					@ -64,7 +64,7 @@ PA_MODULE_USAGE(
 | 
				
			||||||
        "restore_device=<Save/restore sinks/sources?> "
 | 
					        "restore_device=<Save/restore sinks/sources?> "
 | 
				
			||||||
        "restore_volume=<Save/restore volumes?> "
 | 
					        "restore_volume=<Save/restore volumes?> "
 | 
				
			||||||
        "restore_muted=<Save/restore muted states?> "
 | 
					        "restore_muted=<Save/restore muted states?> "
 | 
				
			||||||
        "on_hotplug=<When new device becomes available, recheck streams?> "
 | 
					        "on_hotplug=<This argument is obsolete, please remove it from configuration> "
 | 
				
			||||||
        "on_rescue=<When device becomes unavailable, recheck streams?> "
 | 
					        "on_rescue=<When device becomes unavailable, recheck streams?> "
 | 
				
			||||||
        "fallback_table=<filename>");
 | 
					        "fallback_table=<filename>");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,7 +95,6 @@ struct userdata {
 | 
				
			||||||
        *sink_input_fixate_hook_slot,
 | 
					        *sink_input_fixate_hook_slot,
 | 
				
			||||||
        *source_output_new_hook_slot,
 | 
					        *source_output_new_hook_slot,
 | 
				
			||||||
        *source_output_fixate_hook_slot,
 | 
					        *source_output_fixate_hook_slot,
 | 
				
			||||||
        *source_put_hook_slot,
 | 
					 | 
				
			||||||
        *source_unlink_hook_slot,
 | 
					        *source_unlink_hook_slot,
 | 
				
			||||||
        *connection_unlink_hook_slot;
 | 
					        *connection_unlink_hook_slot;
 | 
				
			||||||
    pa_time_event *save_time_event;
 | 
					    pa_time_event *save_time_event;
 | 
				
			||||||
| 
						 | 
					@ -104,7 +103,6 @@ struct userdata {
 | 
				
			||||||
    bool restore_device:1;
 | 
					    bool restore_device:1;
 | 
				
			||||||
    bool restore_volume:1;
 | 
					    bool restore_volume:1;
 | 
				
			||||||
    bool restore_muted:1;
 | 
					    bool restore_muted:1;
 | 
				
			||||||
    bool on_hotplug:1;
 | 
					 | 
				
			||||||
    bool on_rescue:1;
 | 
					    bool on_rescue:1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_native_protocol *protocol;
 | 
					    pa_native_protocol *protocol;
 | 
				
			||||||
| 
						 | 
					@ -1643,59 +1641,6 @@ static pa_hook_result_t source_output_fixate_hook_callback(pa_core *c, pa_source
 | 
				
			||||||
    return PA_HOOK_OK;
 | 
					    return PA_HOOK_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static pa_hook_result_t source_put_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_hotplug && u->restore_device);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    PA_IDXSET_FOREACH(so, c->source_outputs, idx) {
 | 
					 | 
				
			||||||
        char *name;
 | 
					 | 
				
			||||||
        struct entry *e;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (so->source == source)
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (so->direct_on_input)
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* Skip this if it is already in the process of being moved anyway */
 | 
					 | 
				
			||||||
        if (!so->source)
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (pa_safe_streq(so->source->name, so->preferred_source))
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* Skip this source output if it is connecting a filter source to
 | 
					 | 
				
			||||||
         * the master */
 | 
					 | 
				
			||||||
        if (so->destination_source)
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* It might happen that a stream and a source are set up at the
 | 
					 | 
				
			||||||
           same time, in which case we want to make sure we don't
 | 
					 | 
				
			||||||
           interfere with that */
 | 
					 | 
				
			||||||
        if (!PA_SOURCE_OUTPUT_IS_LINKED(so->state))
 | 
					 | 
				
			||||||
            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_streq(e->device, source->name))
 | 
					 | 
				
			||||||
                pa_source_output_move_to(so, source, true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            entry_free(e);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        pa_xfree(name);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return PA_HOOK_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
 | 
					static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
 | 
				
			||||||
    pa_source_output *so;
 | 
					    pa_source_output *so;
 | 
				
			||||||
    uint32_t idx;
 | 
					    uint32_t idx;
 | 
				
			||||||
| 
						 | 
					@ -2326,7 +2271,7 @@ int pa__init(pa_module*m) {
 | 
				
			||||||
    pa_sink_input *si;
 | 
					    pa_sink_input *si;
 | 
				
			||||||
    pa_source_output *so;
 | 
					    pa_source_output *so;
 | 
				
			||||||
    uint32_t idx;
 | 
					    uint32_t idx;
 | 
				
			||||||
    bool restore_device = true, restore_volume = true, restore_muted = true, on_hotplug = true, on_rescue = true;
 | 
					    bool restore_device = true, restore_volume = true, restore_muted = true, on_rescue = true;
 | 
				
			||||||
#ifdef HAVE_DBUS
 | 
					#ifdef HAVE_DBUS
 | 
				
			||||||
    pa_datum key;
 | 
					    pa_datum key;
 | 
				
			||||||
    bool done;
 | 
					    bool done;
 | 
				
			||||||
| 
						 | 
					@ -2342,12 +2287,14 @@ int pa__init(pa_module*m) {
 | 
				
			||||||
    if (pa_modargs_get_value_boolean(ma, "restore_device", &restore_device) < 0 ||
 | 
					    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_volume", &restore_volume) < 0 ||
 | 
				
			||||||
        pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0 ||
 | 
					        pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0 ||
 | 
				
			||||||
        pa_modargs_get_value_boolean(ma, "on_hotplug", &on_hotplug) < 0 ||
 | 
					 | 
				
			||||||
        pa_modargs_get_value_boolean(ma, "on_rescue", &on_rescue) < 0) {
 | 
					        pa_modargs_get_value_boolean(ma, "on_rescue", &on_rescue) < 0) {
 | 
				
			||||||
        pa_log("restore_device=, restore_volume=, restore_muted=, on_hotplug= and on_rescue= expect boolean arguments");
 | 
					        pa_log("restore_device=, restore_volume=, restore_muted= and on_rescue= expect boolean arguments");
 | 
				
			||||||
        goto fail;
 | 
					        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 (!restore_muted && !restore_volume && !restore_device)
 | 
					    if (!restore_muted && !restore_volume && !restore_device)
 | 
				
			||||||
        pa_log_warn("Neither restoring volume, nor restoring muted, nor restoring device enabled!");
 | 
					        pa_log_warn("Neither restoring volume, nor restoring muted, nor restoring device enabled!");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2357,7 +2304,6 @@ int pa__init(pa_module*m) {
 | 
				
			||||||
    u->restore_device = restore_device;
 | 
					    u->restore_device = restore_device;
 | 
				
			||||||
    u->restore_volume = restore_volume;
 | 
					    u->restore_volume = restore_volume;
 | 
				
			||||||
    u->restore_muted = restore_muted;
 | 
					    u->restore_muted = restore_muted;
 | 
				
			||||||
    u->on_hotplug = on_hotplug;
 | 
					 | 
				
			||||||
    u->on_rescue = on_rescue;
 | 
					    u->on_rescue = on_rescue;
 | 
				
			||||||
    u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
 | 
					    u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2374,11 +2320,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);
 | 
					        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_hotplug) {
 | 
					 | 
				
			||||||
        /* A little bit earlier than module-intended-roles ... */
 | 
					 | 
				
			||||||
        pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE, (pa_hook_cb_t) source_put_hook_callback, u);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (restore_device && on_rescue) {
 | 
					    if (restore_device && on_rescue) {
 | 
				
			||||||
        /* A little bit earlier than module-intended-roles, module-rescue-streams, ... */
 | 
					        /* 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);
 | 
					        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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -559,6 +559,41 @@ void pa_core_move_streams_to_newly_available_preferred_sink(pa_core *c, pa_sink
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void pa_core_move_streams_to_newly_available_preferred_source(pa_core *c, pa_source *s) {
 | 
				
			||||||
 | 
					    pa_source_output *so;
 | 
				
			||||||
 | 
					    uint32_t idx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_assert(c);
 | 
				
			||||||
 | 
					    pa_assert(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    PA_IDXSET_FOREACH(so, c->source_outputs, idx) {
 | 
				
			||||||
 | 
					        if (so->source == s)
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* It might happen that a stream and a source are set up at the
 | 
				
			||||||
 | 
					           same time, in which case we want to make sure we don't
 | 
				
			||||||
 | 
					           interfere with that */
 | 
				
			||||||
 | 
					        if (!PA_SOURCE_OUTPUT_IS_LINKED(so->state))
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (pa_safe_streq(so->preferred_source, s->name))
 | 
				
			||||||
 | 
					            pa_source_output_move_to(so, s, false);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Helper macro to reduce repetition in pa_suspend_cause_to_string().
 | 
					/* Helper macro to reduce repetition in pa_suspend_cause_to_string().
 | 
				
			||||||
 * Parameters:
 | 
					 * Parameters:
 | 
				
			||||||
 *   char *p: the current position in the write buffer
 | 
					 *   char *p: the current position in the write buffer
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -281,4 +281,6 @@ const char *pa_suspend_cause_to_string(pa_suspend_cause_t cause, char buf[PA_SUS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pa_core_move_streams_to_newly_available_preferred_sink(pa_core *c, pa_sink *s);
 | 
					void pa_core_move_streams_to_newly_available_preferred_sink(pa_core *c, pa_sink *s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void pa_core_move_streams_to_newly_available_preferred_source(pa_core *c, pa_source *s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -671,6 +671,8 @@ void pa_source_put(pa_source *s) {
 | 
				
			||||||
     * source, and if we were to call pa_core_update_default_source() before that,
 | 
					     * source, and if we were to call pa_core_update_default_source() before that,
 | 
				
			||||||
     * the default source might change twice, causing unnecessary stream moving. */
 | 
					     * the default source might change twice, causing unnecessary stream moving. */
 | 
				
			||||||
    pa_core_update_default_source(s->core);
 | 
					    pa_core_update_default_source(s->core);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_core_move_streams_to_newly_available_preferred_source(s->core, s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Called from main context */
 | 
					/* Called from main context */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue