[PATCH 3/7] device-manager, filter-apply: don't reroute streams that have a filter

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.
---
 src/modules/module-device-manager.c | 14 ++++++++++
 src/modules/module-filter-apply.c   | 53 +++++++++++++++++++++++++++++++++++--
 2 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/src/modules/module-device-manager.c b/src/modules/module-device-manager.c
index 1a0a53e..76363f3 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,12 @@ 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. */
+    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 +714,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 +732,12 @@ 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. */
+    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 7f4a2b7..f5ff0a3 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) {
-- 
2.7.0



[Index of Archives]     [Linux Audio Users]     [AMD Graphics]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux