diff options
author | Tanu Kaskinen <tanuk@iki.fi> | 2021-04-05 17:13:27 +0300 |
---|---|---|
committer | PulseAudio Marge Bot <pulseaudio-maintainers@lists.freedesktop.org> | 2021-04-05 15:17:15 +0000 |
commit | 737ebcdfdbb1d8496639b29caf56d11be895cf10 (patch) | |
tree | 65a543873d264c8e72fca871f3f89b68838ffc62 | |
parent | 1f204a1357f2d26a4cca12ea9e017db90dd2d961 (diff) |
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: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/535>
-rw-r--r-- | src/pulsecore/core.h | 2 | ||||
-rw-r--r-- | src/pulsecore/sink-input.c | 42 | ||||
-rw-r--r-- | src/pulsecore/source-output.c | 42 |
3 files changed, 72 insertions, 14 deletions
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index 57924b940..118dcf291 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -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, diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 12e3c8b42..5e7657c45 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -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); } } diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index 248698adc..bee9241b9 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -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); } } |