diff options
author | Georg Chini <georg@chini.tk> | 2023-01-08 13:33:25 +0100 |
---|---|---|
committer | PulseAudio Marge Bot <pulseaudio-maintainers@lists.freedesktop.org> | 2023-01-21 10:06:57 +0000 |
commit | 6473e9ed0e3fc3c9be4d6d3df93183f44a0dcb85 (patch) | |
tree | c16f10c9fdc0cc3b6503a59adb08e60bfadaf61a | |
parent | 94dd7b4b7b01470d09102402482866ff89037f42 (diff) | |
download | pulseaudio-6473e9ed0e3fc3c9be4d6d3df93183f44a0dcb85.tar.gz |
stream-interaction: Fix regression when a trigger role is also a cork role
If the same role is named in trigger_roles and cork_roles, a stream with that
role will crash PA. This patch fixes the crash and re-introduces the old
behavior, so that for example specifying trigger_roles=alarm, phone and
cork_roles=alarm, multimedia means that a phone stream will cork alarm and
multimedia streams while an alarm stream will only cork multimedia streams.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/767>
-rw-r--r-- | src/modules/stream-interaction.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/src/modules/stream-interaction.c b/src/modules/stream-interaction.c index b2602f5aa..a6440087c 100644 --- a/src/modules/stream-interaction.c +++ b/src/modules/stream-interaction.c @@ -100,7 +100,7 @@ static const char *get_trigger_role(struct userdata *u, pa_object *stream, struc return NULL; } -static const char *find_trigger_stream(struct userdata *u, pa_object *device, pa_object *ignore_stream, struct group *g) { +static const char *find_trigger_stream(struct userdata *u, pa_object *current_stream, pa_object *device, pa_object *ignore_stream, struct group *g) { pa_object *j; uint32_t idx; const char *trigger_role; @@ -108,6 +108,23 @@ static const char *find_trigger_stream(struct userdata *u, pa_object *device, pa pa_assert(u); pa_object_assert_ref(device); + /* If the current stream is a trigger stream, return the role of this stream, otherwise + * return the role of the first trigger stream that is found on the device. */ + + trigger_role = get_trigger_role(u, current_stream, g); + if (GET_DEVICE_FROM_STREAM(current_stream) == device && current_stream != ignore_stream && trigger_role) { + + if (pa_sink_isinstance(device)) { + if (!PA_SINK_INPUT(current_stream)->muted && + PA_SINK_INPUT(current_stream)->state != PA_SINK_INPUT_CORKED) + return trigger_role; + } else { + if (!PA_SOURCE_OUTPUT(current_stream)->muted && + PA_SOURCE_OUTPUT(current_stream)->state != PA_SOURCE_OUTPUT_CORKED) + return trigger_role; + } + } + PA_IDXSET_FOREACH(j, pa_sink_isinstance(device) ? PA_SINK(device)->inputs : PA_SOURCE(device)->outputs, idx) { if (j == ignore_stream) continue; @@ -129,7 +146,7 @@ static const char *find_trigger_stream(struct userdata *u, pa_object *device, pa return NULL; } -static const char *find_global_trigger_stream(struct userdata *u, pa_object *ignore_stream, struct group *g) { +static const char *find_global_trigger_stream(struct userdata *u, pa_object *current_stream, pa_object *ignore_stream, struct group *g) { const char *trigger_role = NULL; pa_sink *sink; pa_source *source; @@ -137,16 +154,20 @@ static const char *find_global_trigger_stream(struct userdata *u, pa_object *ign pa_assert(u); + /* Check device of current stream first in case the current stream is a trigger stream. */ + if ((trigger_role = find_trigger_stream(u, current_stream, GET_DEVICE_FROM_STREAM(current_stream), ignore_stream, g))) + return trigger_role; + /* Find any trigger role among the sink-inputs and source-outputs. */ PA_IDXSET_FOREACH(sink, u->core->sinks, idx) - if ((trigger_role = find_trigger_stream(u, PA_OBJECT(sink), ignore_stream, g))) + if ((trigger_role = find_trigger_stream(u, current_stream, PA_OBJECT(sink), ignore_stream, g))) break; if (!u->source_trigger || trigger_role) return trigger_role; PA_IDXSET_FOREACH(source, u->core->sources, idx) - if ((trigger_role = find_trigger_stream(u, PA_OBJECT(source), ignore_stream, g))) + if ((trigger_role = find_trigger_stream(u, current_stream, PA_OBJECT(source), ignore_stream, g))) break; return trigger_role; @@ -204,7 +225,7 @@ static inline void apply_interaction_to_sink(struct userdata *u, pa_sink *s, con role = "no_role"; PA_IDXSET_FOREACH(interaction_role, g->interaction_roles, role_idx) { - if ((trigger = pa_streq(role, interaction_role))) + if ((trigger = (pa_streq(interaction_role, role) && (!get_trigger_role(u, PA_OBJECT(j), g) || !pa_safe_streq(new_trigger, role))))) break; if ((trigger = (pa_streq(interaction_role, "any_role") && !get_trigger_role(u, PA_OBJECT(j), g)))) break; @@ -289,10 +310,10 @@ static pa_hook_result_t process(struct userdata *u, pa_object *stream, bool crea for (j = 0; j < u->n_groups; j++) { if (u->global) { - trigger_role = find_global_trigger_stream(u, create ? NULL : stream, u->groups[j]); + trigger_role = find_global_trigger_stream(u, stream, create ? NULL : stream, u->groups[j]); apply_interaction_global(u, trigger_role, create ? NULL : (pa_sink_input_isinstance(stream) ? PA_SINK_INPUT(stream) : NULL), new_stream, u->groups[j]); } else { - trigger_role = find_trigger_stream(u, GET_DEVICE_FROM_STREAM(stream), create ? NULL : stream, u->groups[j]); + trigger_role = find_trigger_stream(u, stream, GET_DEVICE_FROM_STREAM(stream), create ? NULL : stream, u->groups[j]); if (pa_sink_input_isinstance(stream)) apply_interaction_to_sink(u, PA_SINK_INPUT(stream)->sink, trigger_role, create ? NULL : PA_SINK_INPUT(stream), new_stream, u->groups[j]); } |