summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTanu Kaskinen <tanuk@iki.fi>2016-03-07 13:18:29 +0200
committerTanu Kaskinen <tanuk@iki.fi>2016-04-25 13:50:47 +0300
commit085cced42ce0901a2f677fc2f630801b0f4edf80 (patch)
treede1ac9280647ff6dc54f3827ad629f1d9b3bba74
parent13fc8333873b5cfd5f42abf0b6071bb028d9f096 (diff)
downloadpulseaudio-085cced42ce0901a2f677fc2f630801b0f4edf80.tar.gz
device-manager, filter-apply: don't reroute streams that have a filter
device-manager reroutes all streams whenever a new device appears. When filter-apply has loaded a filter for some stream, the filter device may not be what device-manager considers the best device for the stream, which means that when an unrelated device appears, device-manager may break the filtering that filter-apply had set up. This patch changes filter-apply so that it saves the filter device name to the stream proplist when it sets up a filter. device-manager can then check the proplist when it does rerouting, and skip the rerouting for streams that have a filter applied to them. The proplist isn't cleaned up when the stream moves away from the filter device, so before doing any decisions based on the filter_device property, it should be checked that the stream is currently routed to the filter device. It seemed simpler to do it this way compared to setting up stream move monitoring in filter-apply and removing the property when the stream moves away from the filter device.
-rw-r--r--src/modules/module-device-manager.c20
-rw-r--r--src/modules/module-filter-apply.c53
2 files changed, 71 insertions, 2 deletions
diff --git a/src/modules/module-device-manager.c b/src/modules/module-device-manager.c
index 1a0a53e12..0df9575b9 100644
--- a/src/modules/module-device-manager.c
+++ b/src/modules/module-device-manager.c
@@ -649,6 +649,7 @@ static void update_highest_priority_device_indexes(struct userdata *u, const cha
}
static void route_sink_input(struct userdata *u, pa_sink_input *si) {
+ const char *filter_device;
const char *role;
uint32_t role_index, device_index;
pa_sink *sink;
@@ -663,6 +664,15 @@ static void route_sink_input(struct userdata *u, pa_sink_input *si) {
if (!si->sink)
return;
+ /* If module-filter-apply has loaded a filter for the stream, let's not
+ * break the filtering. The pa_streq() check is needed, because
+ * module-filter-apply doesn't unset the property when the stream moves
+ * away from the filter device for whatever reason (this is ugly, but
+ * easier to do this way than appropriately unsetting the property). */
+ filter_device = pa_proplist_gets(si->proplist, "module-filter-apply.filter_device");
+ if (filter_device && pa_streq(filter_device, si->sink->name))
+ return;
+
/* It might happen that a stream and a sink are set up at the
same time, in which case we want to make sure we don't
interfere with that */
@@ -707,6 +717,7 @@ static pa_hook_result_t route_sink_inputs(struct userdata *u, pa_sink *ignore_si
}
static void route_source_output(struct userdata *u, pa_source_output *so) {
+ const char *filter_device;
const char *role;
uint32_t role_index, device_index;
pa_source *source;
@@ -724,6 +735,15 @@ static void route_source_output(struct userdata *u, pa_source_output *so) {
if (!so->source)
return;
+ /* If module-filter-apply has loaded a filter for the stream, let's not
+ * break the filtering. The pa_streq() check is needed, because
+ * module-filter-apply doesn't unset the property when the stream moves
+ * away from the filter device for whatever reason (this is ugly, but
+ * easier to do this way than appropriately unsetting the property). */
+ filter_device = pa_proplist_gets(so->proplist, "module-filter-apply.filter_device");
+ if (filter_device && pa_streq(filter_device, so->source->name))
+ return;
+
/* It might happen that a stream and a source are set up at the
same time, in which case we want to make sure we don't
interfere with that */
diff --git a/src/modules/module-filter-apply.c b/src/modules/module-filter-apply.c
index 7f4a2b7a4..f5ff0a33d 100644
--- a/src/modules/module-filter-apply.c
+++ b/src/modules/module-filter-apply.c
@@ -271,10 +271,59 @@ static void trigger_housekeeping(struct userdata *u) {
}
static int do_move(pa_object *obj, pa_object *parent, bool restore, bool is_input) {
- if (is_input)
+ if (is_input) {
+ if (!restore) {
+ char *old_value;
+
+ if (pa_proplist_contains(PA_SINK_INPUT(obj)->proplist, "module-filter-apply.filter_device")) {
+ old_value = pa_xstrdup(pa_proplist_gets(PA_SINK_INPUT(obj)->proplist, "module-filter-apply.filter_device"));
+ if (!old_value)
+ old_value = pa_xstrdup("(data)");
+ } else
+ old_value = pa_xstrdup("(unset)");
+
+ if (!pa_streq(PA_SINK(parent)->name, old_value)) {
+ pa_proplist *pl;
+
+ pl = pa_proplist_new();
+ pa_proplist_sets(pl, "module-filter-apply.filter_device", PA_SINK(parent)->name);
+ pa_sink_input_update_proplist(PA_SINK_INPUT(obj), PA_UPDATE_REPLACE, pl);
+ pa_proplist_free(pl);
+ pa_log_debug("Sink input %u: proplist[module-filter-apply.filter_device]: %s -> %s",
+ PA_SINK_INPUT(obj)->index, old_value, PA_SINK(parent)->name);
+ }
+
+ pa_xfree(old_value);
+ }
+
return pa_sink_input_move_to(PA_SINK_INPUT(obj), PA_SINK(parent), restore);
- else
+ } else {
+ if (!restore) {
+ char *old_value;
+
+ if (pa_proplist_contains(PA_SOURCE_OUTPUT(obj)->proplist, "module-filter-apply.filter_device")) {
+ old_value = pa_xstrdup(pa_proplist_gets(PA_SOURCE_OUTPUT(obj)->proplist, "module-filter-apply.filter_device"));
+ if (!old_value)
+ old_value = pa_xstrdup("(data)");
+ } else
+ old_value = pa_xstrdup("(unset)");
+
+ if (!pa_streq(PA_SOURCE(parent)->name, old_value)) {
+ pa_proplist *pl;
+
+ pl = pa_proplist_new();
+ pa_proplist_sets(pl, "module-filter-apply.filter_device", PA_SOURCE(parent)->name);
+ pa_source_output_update_proplist(PA_SOURCE_OUTPUT(obj), PA_UPDATE_REPLACE, pl);
+ pa_proplist_free(pl);
+ pa_log_debug("Source output %u: proplist[module-filter-apply.filter_device]: %s -> %s",
+ PA_SOURCE_OUTPUT(obj)->index, old_value, PA_SOURCE(parent)->name);
+ }
+
+ pa_xfree(old_value);
+ }
+
return pa_source_output_move_to(PA_SOURCE_OUTPUT(obj), PA_SOURCE(parent), restore);
+ }
}
static void move_object_for_filter(pa_object *o, struct filter* filter, bool restore, bool is_sink_input) {