[pulseaudio-discuss] [PATCH 2/4] move stream after default sink is changed.

Tanu Kaskinen tanuk at iki.fi
Thu Dec 13 09:16:18 UTC 2018


On Mon, 2018-11-05 at 09:47 +0800, Hui Wang wrote:
> When default sink changes, the stream should be moved to new
> default_sink too.

Except if the stream's preferred sink is the old default sink.

> If it is user to call change default function,
> all stream will move to new default sink unconditionally; if it
> is not, will check if stream binds to old_default_sink and the
> active_port staus of old_default_sink, then it will move the
> stream conditionally.

Why does it matter if the default sink changed due to user request or
some other reason? I don't think streams should be moved
unconditionally when the user changes the default sink.

I think it would be logical to not care about the port unavailability
in this patch, because there's a separate patch for handling that.

> diff --git a/src/modules/module-switch-on-connect.c b/src/modules/module-switch-on-connect.c
> index faa0f289f..4f01c701f 100644
> --- a/src/modules/module-switch-on-connect.c
> +++ b/src/modules/module-switch-on-connect.c

> @@ -100,29 +97,8 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, void*
>              return PA_HOOK_OK;
>          }
>  
> -    old_default_sink = c->default_sink;
> -
>      /* Actually do the switch to the new sink */

This comment isn't very helpful any more (not sure how helpful it was
before either), I'd remove it.

> -    pa_core_set_configured_default_sink(c, sink->name);
> -
> -    /* Now move all old inputs over */
> -    if (pa_idxset_size(old_default_sink->inputs) <= 0) {
> -        pa_log_debug("No sink inputs to move away.");
> -        return PA_HOOK_OK;
> -    }
> -
> -    PA_IDXSET_FOREACH(i, old_default_sink->inputs, idx) {
> -        if (i->preferred_sink != NULL || !PA_SINK_INPUT_IS_LINKED(i->state))
> -            continue;
> -
> -        if (pa_sink_input_move_to(i, sink, false) < 0)
> -            pa_log_info("Failed to move sink input %u \"%s\" to %s.", i->index,
> -                        pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), sink->name);
> -        else
> -            pa_log_info("Successfully moved sink input %u \"%s\" to %s.", i->index,
> -                        pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), sink->name);
> -    }
> -
> +    pa_core_set_configured_default_sink(c, sink->name, false);
>      return PA_HOOK_OK;
>  }

> diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
> index 566367f9e..63a3456e7 100644
> --- a/src/pulsecore/sink.c
> +++ b/src/pulsecore/sink.c

> @@ -3886,3 +3886,36 @@ void pa_sink_set_reference_volume_direct(pa_sink *s, const pa_cvolume *volume) {
>      pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
>      pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_VOLUME_CHANGED], s);
>  }
> +
> +void pa_sink_move_streams_from_oldsink_to_newsink(pa_sink *old_sink, pa_sink *new_sink, bool from_user) {

I think "pa_sink_move_streams_to_default_sink" would be a better name
for the function. It would also be good to have a comment explaining
when the function is used and which streams are not moved (that could
go to the header file).

> +    pa_sink_input *i;
> +    uint32_t idx;
> +    pa_device_port *o_active_p;
> +
> +    if (old_sink == new_sink)
> +	return;
> +
> +    if (old_sink == NULL)
> +	return;

It doesn't make sense to call this function with NULL, so this check
should be an assertion instead.

> +
> +    o_active_p = old_sink->active_port;

Note that not all sinks have ports, so this can be NULL.

Since we only care about the availability of the active port, I'd add a
"old_sink_is_unavailable" boolean to be used inside the loop.

> +    if (pa_idxset_size(old_sink->inputs) > 0) {
> +	    PA_IDXSET_FOREACH(i, old_sink->inputs, idx) {
> +		if (!PA_SINK_INPUT_IS_LINKED(i->state))
> +		    continue;
> +
> +		if (!from_user && i->preferred_sink != NULL && pa_safe_streq(old_sink->name, i->preferred_sink))

No need to check if i->preferred_sink is NULL, because pa_safe_streq()
checks that anyway.

> +		    if (o_active_p->available != PA_AVAILABLE_NO)
> +			continue;
> +
> +		if (pa_sink_input_move_to(i, new_sink, from_user) < 0)
> +		    pa_log_info("Failed to move sink input %u \"%s\" to %s.", i->index,
> +				pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), new_sink->name);
> +		else
> +		    pa_log_info("Successfully moved sink input %u \"%s\" to %s.", i->index,
> +				pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), new_sink->name);

Logging the reason for moving the stream before calling
pa_sink_input_move_to() would be very useful.

Here's a suggestion you don't need to implement, but you can if you
want: it would be nice to have good enough logging in
pa_sink_input_move_finish() so that callers don't all need to do their
own logging about the move result. This should be done in a separate
patch.

-- 
Tanu

https://www.patreon.com/tanuk
https://liberapay.com/tanuk



More information about the pulseaudio-discuss mailing list