summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorg Chini <georg@chini.tk>2023-01-08 13:33:25 +0100
committerPulseAudio Marge Bot <pulseaudio-maintainers@lists.freedesktop.org>2023-01-21 10:06:57 +0000
commit6473e9ed0e3fc3c9be4d6d3df93183f44a0dcb85 (patch)
treec16f10c9fdc0cc3b6503a59adb08e60bfadaf61a
parent94dd7b4b7b01470d09102402482866ff89037f42 (diff)
downloadpulseaudio-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.c35
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]);
}