Commit 737ebcdf authored by Tanu Kaskinen's avatar Tanu Kaskinen Committed by PulseAudio Marge Bot
Browse files

sink-input, source-output: Add hooks for preferred device changes

The hooks are fired when the preferred device changes. This is useful
for module-stream-restore.

I added new set_preferred_sink/source() functions for firing the hooks.
The functions also log the preferred device changes.

There was already pa_sink_input_set_preferred_sink(), but that had a
side effect of moving the stream, so I needed a new function. Since it
can be confusing when the two similarly named functions should be
called, I added a comment for pa_sink_input_set_preferred_sink() that
explains the different situations.

Part-of: <!535>
parent 1f204a13
......@@ -104,6 +104,7 @@ typedef enum pa_core_hook {
PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED,
PA_CORE_HOOK_SINK_INPUT_VOLUME_CHANGED,
PA_CORE_HOOK_SINK_INPUT_MUTE_CHANGED,
PA_CORE_HOOK_SINK_INPUT_PREFERRED_SINK_CHANGED,
PA_CORE_HOOK_SINK_INPUT_SEND_EVENT,
PA_CORE_HOOK_SOURCE_OUTPUT_NEW,
PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE,
......@@ -117,6 +118,7 @@ typedef enum pa_core_hook {
PA_CORE_HOOK_SOURCE_OUTPUT_PROPLIST_CHANGED,
PA_CORE_HOOK_SOURCE_OUTPUT_VOLUME_CHANGED,
PA_CORE_HOOK_SOURCE_OUTPUT_MUTE_CHANGED,
PA_CORE_HOOK_SOURCE_OUTPUT_PREFERRED_SOURCE_CHANGED,
PA_CORE_HOOK_SOURCE_OUTPUT_SEND_EVENT,
PA_CORE_HOOK_CLIENT_NEW,
PA_CORE_HOOK_CLIENT_PUT,
......
......@@ -1888,6 +1888,22 @@ static void update_volume_due_to_moving(pa_sink_input *i, pa_sink *dest) {
pa_sink_set_volume(i->sink, NULL, false, i->save_volume);
}
/* Called from the main thread. */
static void set_preferred_sink(pa_sink_input *i, const char *sink_name) {
pa_assert(i);
if (pa_safe_streq(i->preferred_sink, sink_name))
return;
pa_log_debug("Sink input %u: preferred_sink: %s -> %s",
i->index, i->preferred_sink ? i->preferred_sink : "(unset)", sink_name ? sink_name : "(unset)");
pa_xfree(i->preferred_sink);
i->preferred_sink = pa_xstrdup(sink_name);
pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT | PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PREFERRED_SINK_CHANGED], i);
}
/* Called from main context */
int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, bool save) {
struct volume_factor_entry *v;
......@@ -1930,11 +1946,10 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, bool save) {
/* save == true, means user is calling the move_to() and want to
save the preferred_sink */
if (save) {
pa_xfree(i->preferred_sink);
if (dest == dest->core->default_sink)
i->preferred_sink = NULL;
set_preferred_sink(i, NULL);
else
i->preferred_sink = pa_xstrdup(dest->name);
set_preferred_sink(i, dest->name);
}
pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL);
......@@ -2434,16 +2449,29 @@ void pa_sink_input_set_reference_ratio(pa_sink_input *i, const pa_cvolume *ratio
pa_cvolume_snprint_verbose(new_ratio_str, sizeof(new_ratio_str), ratio, &i->channel_map, true));
}
/* Called from the main thread. */
/* Called from the main thread.
*
* This is called when e.g. module-stream-restore wants to change the preferred
* sink. As a side effect the stream is moved to the new preferred sink. Note
* that things can work also in the other direction: if the user moves
* a stream, as a side effect the preferred sink is changed. This could cause
* an infinite loop, but it's avoided by these two measures:
* - When pa_sink_input_set_preferred_sink() is called, it calls
* pa_sink_input_move_to() with save=false, which avoids the recursive
* pa_sink_input_set_preferred_sink() call.
* - When the primary operation is to move a stream,
* pa_sink_input_finish_move() calls set_preferred_sink() instead of
* pa_sink_input_set_preferred_sink(). set_preferred_sink() doesn't move
* the stream as a side effect.
*/
void pa_sink_input_set_preferred_sink(pa_sink_input *i, pa_sink *s) {
pa_assert(i);
pa_xfree(i->preferred_sink);
if (s) {
i->preferred_sink = pa_xstrdup(s->name);
set_preferred_sink(i, s->name);
pa_sink_input_move_to(i, s, false);
} else {
i->preferred_sink = NULL;
set_preferred_sink(i, NULL);
pa_sink_input_move_to(i, i->core->default_sink, false);
}
}
......@@ -1531,6 +1531,22 @@ static void update_volume_due_to_moving(pa_source_output *o, pa_source *dest) {
pa_source_set_volume(o->source, NULL, false, o->save_volume);
}
/* Called from the main thread. */
static void set_preferred_source(pa_source_output *o, const char *source_name) {
pa_assert(o);
if (pa_safe_streq(o->preferred_source, source_name))
return;
pa_log_debug("Source output %u: preferred_source: %s -> %s",
o->index, o->preferred_source ? o->preferred_source : "(unset)", source_name ? source_name : "(unset)");
pa_xfree(o->preferred_source);
o->preferred_source = pa_xstrdup(source_name);
pa_subscription_post(o->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT | PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PREFERRED_SOURCE_CHANGED], o);
}
/* Called from main context */
int pa_source_output_finish_move(pa_source_output *o, pa_source *dest, bool save) {
pa_source_output_assert_ref(o);
......@@ -1570,11 +1586,10 @@ int pa_source_output_finish_move(pa_source_output *o, pa_source *dest, bool save
/* save == true, means user is calling the move_to() and want to
save the preferred_source */
if (save) {
pa_xfree(o->preferred_source);
if (dest == dest->core->default_source)
o->preferred_source = NULL;
set_preferred_source(o, NULL);
else
o->preferred_source = pa_xstrdup(dest->name);
set_preferred_source(o, dest->name);
}
pa_idxset_put(o->source->outputs, pa_source_output_ref(o), NULL);
......@@ -1907,16 +1922,29 @@ void pa_source_output_set_reference_ratio(pa_source_output *o, const pa_cvolume
pa_cvolume_snprint_verbose(new_ratio_str, sizeof(new_ratio_str), ratio, &o->channel_map, true));
}
/* Called from the main thread. */
/* Called from the main thread.
*
* This is called when e.g. module-stream-restore wants to change the preferred
* source. As a side effect the stream is moved to the new preferred source.
* Note that things can work also in the other direction: if the user moves
* a stream, as a side effect the preferred source is changed. This could cause
* an infinite loop, but it's avoided by these two measures:
* - When pa_source_output_set_preferred_source() is called, it calls
* pa_source_output_move_to() with save=false, which avoids the recursive
* pa_source_output_set_preferred_source() call.
* - When the primary operation is to move a stream,
* pa_source_output_finish_move() calls set_preferred_source() instead of
* pa_source_output_set_preferred_source(). set_preferred_source() doesn't
* move the stream as a side effect.
*/
void pa_source_output_set_preferred_source(pa_source_output *o, pa_source *s) {
pa_assert(o);
pa_xfree(o->preferred_source);
if (s) {
o->preferred_source = pa_xstrdup(s->name);
set_preferred_source(o, s->name);
pa_source_output_move_to(o, s, false);
} else {
o->preferred_source = NULL;
set_preferred_source(o, NULL);
pa_source_output_move_to(o, o->core->default_source, false);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment