[pulseaudio-discuss] [PATCH] core: Don't let moving filter sources/sinks become the default source/sink
Georg Chini
georg at chini.tk
Mon May 8 07:31:22 UTC 2017
When a virtual sink is loaded and there is only one sound card, then during
a profile switch, all sinks and sources can become temporarily unavailable.
In that situation, the virtual sink will become the default sink, although
it is not connected to a master sink due to the move operation initiated by
the profile switch. If module-always sink is loaded, it will load a null-sink
in that situation. If also module-switch-on-connect is present, it will change
the default sink to the new null sink and try to move the sink-inputs from the
virtual sink to the null sink. This leads to a segfault because the master
sink of the virtual sink is invalid.
This patch fixes the issue by disallowing a moving virtual sink to become the
default sink.
It also fixes a bug in module-switch-on-connect, which assumed that default_sink
is always set.
The same applies to the source side.
The is_filter_{sink,source}_moving() functions were stolen from one of Tanu's
previous unapplied patches.
Buglink: https://bugs.freedesktop.org/show_bug.cgi?id=100277
---
src/modules/module-switch-on-connect.c | 12 ++++++++++
src/pulsecore/core.c | 42 ++++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+)
diff --git a/src/modules/module-switch-on-connect.c b/src/modules/module-switch-on-connect.c
index 776c923e..e2da7222 100644
--- a/src/modules/module-switch-on-connect.c
+++ b/src/modules/module-switch-on-connect.c
@@ -75,6 +75,12 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, void*
return PA_HOOK_OK;
}
+ /* No default sink, nothing to move away, just set the new default */
+ if (!c->default_sink) {
+ pa_core_set_configured_default_sink(c, sink);
+ return PA_HOOK_OK;
+ }
+
if (c->default_sink == sink)
return PA_HOOK_OK;
@@ -135,6 +141,12 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source,
return PA_HOOK_OK;
}
+ /* No default source, nothing to move away, just set the new default */
+ if (!c->default_source) {
+ pa_core_set_configured_default_source(c, source);
+ return PA_HOOK_OK;
+ }
+
if (c->default_source == source)
return PA_HOOK_OK;
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index 52e51db1..99043033 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -258,6 +258,23 @@ void pa_core_set_configured_default_source(pa_core *core, pa_source *source) {
pa_core_update_default_source(core);
}
+/* Test if a sink is a moving filter sink */
+static bool is_filter_sink_moving(pa_sink *s) {
+ pa_sink *sink = s;
+
+ if (!sink)
+ return false;
+
+ while (sink->input_to_master) {
+ sink = sink->input_to_master->sink;
+
+ if (!sink)
+ return true;
+ }
+
+ return false;
+}
+
/* a < b -> return -1
* a == b -> return 0
* a > b -> return 1 */
@@ -314,6 +331,10 @@ void pa_core_update_default_sink(pa_core *core) {
best = sink;
}
+ /* A moving filter sink cannot be the default sink */
+ if (is_filter_sink_moving(best))
+ best = NULL;
+
old_default_sink = core->default_sink;
if (best == old_default_sink)
@@ -332,6 +353,23 @@ void pa_core_update_default_sink(pa_core *core) {
pa_hook_fire(&core->hooks[PA_CORE_HOOK_DEFAULT_SINK_CHANGED], core->default_sink);
}
+/* Test if a source is a moving filter source */
+static bool is_filter_source_moving(pa_source *o) {
+ pa_source *source = o;
+
+ if (!source)
+ return false;
+
+ while (source->output_from_master) {
+ source = source->output_from_master->source;
+
+ if (!source)
+ return true;
+ }
+
+ return false;
+}
+
/* a < b -> return -1
* a == b -> return 0
* a > b -> return 1 */
@@ -398,6 +436,10 @@ void pa_core_update_default_source(pa_core *core) {
best = source;
}
+ /* A moving filter source cannot be the default source */
+ if (is_filter_source_moving(best))
+ best = NULL;
+
old_default_source = core->default_source;
if (best == old_default_source)
--
2.11.0
More information about the pulseaudio-discuss
mailing list