[pulseaudio-commits] 3 commits - src/modules

Arun Raghavan arun at kemper.freedesktop.org
Wed Nov 23 23:06:56 PST 2011


 src/modules/echo-cancel/module-echo-cancel.c |   32 ++++----
 src/modules/module-equalizer-sink.c          |    3 
 src/modules/module-filter-apply.c            |  105 ++++++++++++++-------------
 3 files changed, 79 insertions(+), 61 deletions(-)

New commits:
commit c30a68ebbda56aa1da0d0855f01d195f7d25d448
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date:   Fri Nov 11 15:08:24 2011 +0530

    filters: Allow a filter to have both sink and source
    
    This sets the base for better representing module-echo-cancel. This
    patch itself should change no behaviour -- it only makes way for other
    changes.

diff --git a/src/modules/module-filter-apply.c b/src/modules/module-filter-apply.c
index dd9a137..d1fb5df 100644
--- a/src/modules/module-filter-apply.c
+++ b/src/modules/module-filter-apply.c
@@ -57,9 +57,10 @@ static const char* const valid_modargs[] = {
 struct filter {
     char *name;
     uint32_t module_index;
-    pa_bool_t is_sink;
-    pa_object *parent_obj;      /* source or sink that the filter is connected to */
-    pa_object *obj;             /* source or sink of the filter */
+    pa_sink *sink;
+    pa_sink *sink_master;
+    pa_source *source;
+    pa_source *source_master;
 };
 
 struct userdata {
@@ -83,17 +84,19 @@ struct userdata {
 static unsigned filter_hash(const void *p) {
     const struct filter *f = p;
 
-    if (f->is_sink)
-        return (unsigned) (PA_SINK(f->parent_obj)->index + pa_idxset_string_hash_func(f->name));
+    if (f->sink_master && !f->source_master)
+        return (unsigned) (f->sink_master->index + pa_idxset_string_hash_func(f->name));
+    else if (!f->sink_master && f->source_master)
+        return (unsigned) ((f->source_master->index << 16) + pa_idxset_string_hash_func(f->name));
     else
-        return (unsigned) ((PA_SOURCE(f->parent_obj)->index << 16) + pa_idxset_string_hash_func(f->name));
+        pa_assert_not_reached();
 }
 
 static int filter_compare(const void *a, const void *b) {
     const struct filter *fa = a, *fb = b;
     int r;
 
-    if (fa->parent_obj != fb->parent_obj)
+    if (fa->sink_master != fb->sink_master || fa->source_master != fb->source_master)
         return 1;
     if ((r = strcmp(fa->name, fb->name)))
         return r;
@@ -101,15 +104,19 @@ static int filter_compare(const void *a, const void *b) {
     return 0;
 }
 
-static struct filter *filter_new(const char *name, pa_object* parent_obj, pa_bool_t is_sink) {
+static struct filter *filter_new(const char *name, pa_sink *sink, pa_source *source) {
     struct filter *f;
 
+    pa_assert(sink || source);
+
     f = pa_xnew(struct filter, 1);
     f->name = pa_xstrdup(name);
-    pa_assert_se(f->parent_obj = parent_obj);
-    f->is_sink = is_sink;
+    f->sink_master = sink;
+    f->source_master = source;
     f->module_index = PA_INVALID_INDEX;
-    f->obj = NULL;
+    f->sink = NULL;
+    f->source = NULL;
+
     return f;
 }
 
@@ -140,12 +147,15 @@ static const char* should_filter(pa_object *o, pa_bool_t is_sink_input) {
     return NULL;
 }
 
-static pa_bool_t nothing_attached(pa_object *obj, pa_bool_t is_sink)
-{
-    if (is_sink)
-        return pa_idxset_isempty(PA_SINK(obj)->inputs);
-    else
-        return pa_idxset_isempty(PA_SOURCE(obj)->outputs);
+static pa_bool_t nothing_attached(struct filter *f) {
+    pa_bool_t no_si = TRUE, no_so = TRUE;
+
+    if (f->sink)
+        no_si = pa_idxset_isempty(f->sink->inputs);
+    else if (f->source)
+        no_so = pa_idxset_isempty(f->source->outputs);
+
+    return no_si && no_so;
 }
 
 static void housekeeping_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) {
@@ -162,7 +172,7 @@ static void housekeeping_time_callback(pa_mainloop_api*a, pa_time_event* e, cons
     u->housekeeping_time_event = NULL;
 
     PA_HASHMAP_FOREACH(filter, u->filters, state) {
-        if (filter->obj && nothing_attached(filter->obj, filter->is_sink)) {
+        if (nothing_attached(filter)) {
             uint32_t idx;
 
             pa_log_debug("Detected filter %s as no longer used. Unloading.", filter->name);
@@ -203,13 +213,13 @@ static void move_object_for_filter(pa_object *o, struct filter* filter, pa_bool_
     pa_assert(o);
     pa_assert(filter);
 
-    pa_assert_se(parent = (restore ? filter->parent_obj : filter->obj));
-
     if (is_sink_input) {
         pl = PA_SINK_INPUT(o)->proplist;
+        pa_assert_se(parent = PA_OBJECT(restore ? filter->sink_master : filter->sink));
         name = PA_SINK(parent)->name;
     } else {
         pl = PA_SOURCE_OUTPUT(o)->proplist;
+        pa_assert_se(parent = PA_OBJECT(restore ? filter->source_master : filter->source));
         name = PA_SOURCE(parent)->name;
     }
 
@@ -235,9 +245,9 @@ static void find_filters_for_module(struct userdata *u, pa_module *m, const char
         if (sink->module == m) {
             pa_assert(sink->input_to_master != NULL);
 
-            fltr = filter_new(name, PA_OBJECT(sink->input_to_master->sink), TRUE);
+            fltr = filter_new(name, sink->input_to_master->sink, NULL);
             fltr->module_index = m->index;
-            fltr->obj = PA_OBJECT(sink);
+            fltr->sink = sink;
 
             pa_hashmap_put(u->filters, fltr, fltr);
         }
@@ -247,9 +257,9 @@ static void find_filters_for_module(struct userdata *u, pa_module *m, const char
         if (source->module == m && !source->monitor_of) {
             pa_assert(source->output_from_master != NULL);
 
-            fltr = filter_new(name, PA_OBJECT(source->output_from_master->source), FALSE);
+            fltr = filter_new(name, NULL, source->output_from_master->source);
             fltr->module_index = m->index;
-            fltr->obj = PA_OBJECT(source);
+            fltr->source = source;
 
             pa_hashmap_put(u->filters, fltr, fltr);
         }
@@ -262,7 +272,7 @@ static pa_bool_t can_unload_module(struct userdata *u, uint32_t idx) {
 
     /* Check if any other struct filters point to the same module */
     PA_HASHMAP_FOREACH(filter, u->filters, state) {
-        if (filter->module_index == idx && !nothing_attached(filter->obj, pa_sink_isinstance(filter->obj)))
+        if (filter->module_index == idx && !nothing_attached(filter))
             return FALSE;
     }
 
@@ -272,23 +282,23 @@ static pa_bool_t can_unload_module(struct userdata *u, uint32_t idx) {
 static pa_hook_result_t process(struct userdata *u, pa_object *o, pa_bool_t is_sink_input) {
     const char *want;
     pa_bool_t done_something = FALSE;
-
-    pa_object *parent; /* source/sink of the given source-output/sink-input */
-    const char *parent_name;
+    pa_sink *sink = NULL;
+    pa_source *source = NULL;
+    const char *sink_name = NULL, *source_name = NULL;
     pa_module *module;
 
     if (is_sink_input) {
-        parent = PA_OBJECT(PA_SINK_INPUT(o)->sink);
-        parent_name = PA_SINK_INPUT(o)->sink->name;
-        module = PA_SINK_INPUT(o)->sink->module;
+        sink = PA_SINK_INPUT(o)->sink;
+        sink_name = sink->name;
+        module = sink->module;
     } else {
-        parent = PA_OBJECT(PA_SOURCE_OUTPUT(o)->source);
-        parent_name = PA_SOURCE_OUTPUT(o)->source->name;
-        module = PA_SOURCE_OUTPUT(o)->source->module;
+        source = PA_SOURCE_OUTPUT(o)->source;
+        source_name = source->name;
+        module = source->module;
     }
 
-    /* If there is no sink yet, we can't do much */
-    if (!parent)
+    /* If there is no sink/source yet, we can't do much */
+    if ((is_sink_input && !sink) || (!is_sink_input && !source))
         return PA_HOOK_OK;
 
     /* If the stream doesn't what any filter, then let it be. */
@@ -309,13 +319,14 @@ static pa_hook_result_t process(struct userdata *u, pa_object *o, pa_bool_t is_s
             return PA_HOOK_OK;
         }
 
-        fltr = filter_new(want, parent, is_sink_input);
+        fltr = filter_new(want, sink, source);
 
         if (!(filter = pa_hashmap_get(u->filters, fltr))) {
             char *args;
             pa_module *m;
 
-            args = pa_sprintf_malloc("autoloaded=1 %s_master=%s", is_sink_input ? "sink" : "source", parent_name);
+            args = pa_sprintf_malloc("autoloaded=1 %s_master=%s", is_sink_input ? "sink" : "source",
+                    is_sink_input ? sink_name : source_name);
             pa_log_debug("Loading %s with arguments '%s'", module_name, args);
 
             if ((m = pa_module_load(u->core, module_name, args))) {
@@ -329,15 +340,15 @@ static pa_hook_result_t process(struct userdata *u, pa_object *o, pa_bool_t is_s
         pa_xfree(fltr);
 
         if (!filter) {
-            pa_log("Unable to load %s for <%s>", module_name, parent_name);
+            pa_log("Unable to load %s for <%s>", module_name, is_sink_input ? sink_name : source_name);
             pa_xfree(module_name);
             return PA_HOOK_OK;
         }
         pa_xfree(module_name);
 
-        if (filter->obj) {
-            /* We can move the sink_input now as the know the destination.
-             * If this isn't true, we will do it later when the sink appears. */
+        /* We can move the stream now as we know the destination. If this
+         * isn't true, we will do it later when the sink appears. */
+        if ((is_sink_input && filter->sink) || (!is_sink_input && filter->source)) {
             move_object_for_filter(o, filter, FALSE, is_sink_input);
             done_something = TRUE;
         }
@@ -348,7 +359,7 @@ static pa_hook_result_t process(struct userdata *u, pa_object *o, pa_bool_t is_s
         /* We do not want to filter... but are we already filtered?
          * This can happen if an input's proplist changes */
         PA_HASHMAP_FOREACH(filter, u->filters, state) {
-            if (parent == filter->obj) {
+            if ((is_sink_input && sink == filter->sink) || (!is_sink_input && source == filter->source)) {
                 move_object_for_filter(o, filter, TRUE, is_sink_input);
                 done_something = TRUE;
                 break;
@@ -409,13 +420,13 @@ static pa_hook_result_t sink_unlink_cb(pa_core *core, pa_sink *sink, struct user
     /* If either the parent or the sink we've loaded disappears,
      * we should remove it from our hashmap */
     PA_HASHMAP_FOREACH(filter, u->filters, state) {
-        if (filter->parent_obj == PA_OBJECT(sink) || filter->obj == PA_OBJECT(sink)) {
+        if (filter->sink_master == sink || filter->sink == sink) {
             uint32_t idx;
 
             /* Attempt to rescue any streams to the parent sink as this is likely
              * the best course of action (as opposed to a generic rescue via
              * module-rescue-streams */
-            if (filter->obj == PA_OBJECT(sink)) {
+            if (filter->sink == sink) {
                 pa_sink_input *i;
 
                 PA_IDXSET_FOREACH(i, sink->inputs, idx)
@@ -481,13 +492,13 @@ static pa_hook_result_t source_unlink_cb(pa_core *core, pa_source *source, struc
     /* If either the parent or the source we've loaded disappears,
      * we should remove it from our hashmap */
     PA_HASHMAP_FOREACH(filter, u->filters, state) {
-        if (filter->parent_obj == PA_OBJECT(source) || filter->obj == PA_OBJECT(source)) {
+        if (filter->source_master == source || filter->source == source) {
             uint32_t idx;
 
             /* Attempt to rescue any streams to the parent source as this is likely
              * the best course of action (as opposed to a generic rescue via
              * module-rescue-streams */
-            if (filter->obj == PA_OBJECT(source)) {
+            if (filter->source == source) {
                 pa_source_output *o;
 
                 PA_IDXSET_FOREACH(o, source->outputs, idx)

commit aaf0f5bd6e29c86dd5b96f2185bedc520d745ad4
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date:   Wed Nov 23 16:46:12 2011 +0530

    filters: Fix the master source/sink when autoloaded
    
    When autoloaded, it is expected that module-filter-apply (or whatever is
    loading us) will take care of applying the filter on the correct
    sink/source master. Instead of adding complexity by tracking what is
    currently being filtered, we just disallow filtering anything except the
    original master sink/source and let module-filter-apply or whatever is
    loading us deal with dynamic sink/source changes.

diff --git a/src/modules/echo-cancel/module-echo-cancel.c b/src/modules/echo-cancel/module-echo-cancel.c
index b810a4e..64e17bf 100644
--- a/src/modules/echo-cancel/module-echo-cancel.c
+++ b/src/modules/echo-cancel/module-echo-cancel.c
@@ -1399,7 +1399,7 @@ static pa_bool_t source_output_may_move_to_cb(pa_source_output *o, pa_source *de
     pa_assert_ctl_context();
     pa_assert_se(u = o->userdata);
 
-    if (u->dead)
+    if (u->dead || u->autoloaded)
         return FALSE;
 
     return (u->source != dest) && (u->sink != dest->monitor_of);
@@ -1412,7 +1412,7 @@ static pa_bool_t sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
 
-    if (u->dead)
+    if (u->dead || u->autoloaded)
         return FALSE;
 
     return u->sink != dest;
diff --git a/src/modules/module-equalizer-sink.c b/src/modules/module-equalizer-sink.c
index e83a41d..006b3d1 100644
--- a/src/modules/module-equalizer-sink.c
+++ b/src/modules/module-equalizer-sink.c
@@ -1055,6 +1055,9 @@ static pa_bool_t sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
 
+    if (u->autoloaded)
+        return FALSE;
+
     return u->sink != dest;
 }
 

commit ac3d66f978f4276317e11ba9f1f156926a90b30c
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date:   Tue Nov 22 13:24:22 2011 +0530

    echo-cancel: Use more human-friendly descriptions
    
    This makes what devices are being cancelled clearer in the UI (at the
    cost of being somewhat less clear when multiple devices of the same name
    are plugged, but at least that's a much smaller set than everyone).

diff --git a/src/modules/echo-cancel/module-echo-cancel.c b/src/modules/echo-cancel/module-echo-cancel.c
index c063734..b810a4e 100644
--- a/src/modules/echo-cancel/module-echo-cancel.c
+++ b/src/modules/echo-cancel/module-echo-cancel.c
@@ -1433,13 +1433,14 @@ static void source_output_moving_cb(pa_source_output *o, pa_source *dest) {
         pa_source_set_asyncmsgq(u->source, NULL);
 
     if (u->source_auto_desc && dest) {
-        const char *z;
+        const char *y, *z;
         pa_proplist *pl;
 
         pl = pa_proplist_new();
+        y = pa_proplist_gets(u->sink_input->sink->proplist, PA_PROP_DEVICE_DESCRIPTION);
         z = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
-        pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "Echo-Cancel Source %s on %s",
-                         pa_proplist_gets(u->source->proplist, "device.echo-cancel.name"), z ? z : dest->name);
+        pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "%s (echo cancelled with %s)", z ? z : dest->name,
+                y ? y : u->sink_input->sink->name);
 
         pa_source_update_proplist(u->source, PA_UPDATE_REPLACE, pl);
         pa_proplist_free(pl);
@@ -1460,13 +1461,14 @@ static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
         pa_sink_set_asyncmsgq(u->sink, NULL);
 
     if (u->sink_auto_desc && dest) {
-        const char *z;
+        const char *y, *z;
         pa_proplist *pl;
 
         pl = pa_proplist_new();
+        y = pa_proplist_gets(u->source_output->source->proplist, PA_PROP_DEVICE_DESCRIPTION);
         z = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
-        pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "Echo-Cancel Sink %s on %s",
-                         pa_proplist_gets(u->sink->proplist, "device.echo-cancel.name"), z ? z : dest->name);
+        pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "%s (echo cancelled with %s)", z ? z : dest->name,
+                         y ? y : u->source_output->source->name);
 
         pa_sink_update_proplist(u->sink, PA_UPDATE_REPLACE, pl);
         pa_proplist_free(pl);
@@ -1709,7 +1711,6 @@ int pa__init(pa_module*m) {
     pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
     if (!u->autoloaded)
         pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_INTENDED_ROLES, "phone");
-    pa_proplist_sets(source_data.proplist, "device.echo-cancel.name", source_data.name);
 
     if (pa_modargs_get_proplist(ma, "source_properties", source_data.proplist, PA_UPDATE_REPLACE) < 0) {
         pa_log("Invalid properties");
@@ -1718,10 +1719,12 @@ int pa__init(pa_module*m) {
     }
 
     if ((u->source_auto_desc = !pa_proplist_contains(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
-        const char *z;
+        const char *y, *z;
 
+        y = pa_proplist_gets(sink_master->proplist, PA_PROP_DEVICE_DESCRIPTION);
         z = pa_proplist_gets(source_master->proplist, PA_PROP_DEVICE_DESCRIPTION);
-        pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Echo-Cancel Source %s on %s", source_data.name, z ? z : source_master->name);
+        pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "%s (echo cancelled with %s)",
+                z ? z : source_master->name, y ? y : sink_master->name);
     }
 
     u->source = pa_source_new(m->core, &source_data, (source_master->flags & (PA_SOURCE_LATENCY | PA_SOURCE_DYNAMIC_LATENCY))
@@ -1759,7 +1762,6 @@ int pa__init(pa_module*m) {
     pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
     if (!u->autoloaded)
         pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_INTENDED_ROLES, "phone");
-    pa_proplist_sets(sink_data.proplist, "device.echo-cancel.name", sink_data.name);
 
     if (pa_modargs_get_proplist(ma, "sink_properties", sink_data.proplist, PA_UPDATE_REPLACE) < 0) {
         pa_log("Invalid properties");
@@ -1768,10 +1770,12 @@ int pa__init(pa_module*m) {
     }
 
     if ((u->sink_auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
-        const char *z;
+        const char *y, *z;
 
+        y = pa_proplist_gets(source_master->proplist, PA_PROP_DEVICE_DESCRIPTION);
         z = pa_proplist_gets(sink_master->proplist, PA_PROP_DEVICE_DESCRIPTION);
-        pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Echo-Cancel Sink %s on %s", sink_data.name, z ? z : sink_master->name);
+        pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "%s (echo cancelled with %s)",
+                z ? z : sink_master->name, y ? y : source_master->name);
     }
 
     u->sink = pa_sink_new(m->core, &sink_data, (sink_master->flags & (PA_SINK_LATENCY | PA_SINK_DYNAMIC_LATENCY))



More information about the pulseaudio-commits mailing list