[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master, updated. v1.0-dev-288-g2f7eb35

Colin Guthrie gitmailer-noreply at 0pointer.de
Fri Apr 29 04:40:20 PDT 2011


This is an automated email from the git hooks/post-receive script. It was
generated because of a push to the "PulseAudio Sound Server" repository.

The master branch has been updated
      from  495c1ed2361f7bab5eaa6978d2fda624a2944bb9 (commit)

- Log -----------------------------------------------------------------
2f7eb35 dbus: Fix the order of freeing stuff when unloading module-dbus-protocol.
7055694 dbus: Fix connection idxset freeing when unloading the module.
2ee398f match: Support for both merging and replacing proplist updates.
-----------------------------------------------------------------------

Summary of changes:
 src/modules/dbus/module-dbus-protocol.c |   29 +++++-----
 src/modules/module-match.c              |   97 +++++++++++++++++++------------
 2 files changed, 75 insertions(+), 51 deletions(-)

-----------------------------------------------------------------------

commit 2ee398fd94fd9bbfaff61d0743c945f0a3411fa8
Author: Tanu Kaskinen <tanu.kaskinen at digia.com>
Date:   Fri Apr 29 13:45:29 2011 +0300

    match: Support for both merging and replacing proplist updates.
    
    This patch adds a new update mode specifier that can be optionally
    given in match rules after the regexp. Property list updates triggered
    by the rule will honour the given mode. The two allowed modes are 'merge'
    and 'replace', corresponding to PA_UPDATE_MERGE and PA_UPDATE_REPLACE
    respectively. If omitted, the mode defaults to PA_UPDATE_MERGE, ie. to
    the original behavior.
    
    For example, to force 'media.role' to be overwritten with 'bar' for
    streams matching foo you can use an entry like this:
    
    foo replace "bar"
    
    This will really overwrite media.role to bar even if it has already been
    set to something else by the application.
    
    Thanks to Krisztian Litkey for the original patch and the description
    above. In addition to implementing the new feature, this patch fixes
    a number of bugs in the parsing code.

diff --git a/src/modules/module-match.c b/src/modules/module-match.c
index b3316d4..c94ef79 100644
--- a/src/modules/module-match.c
+++ b/src/modules/module-match.c
@@ -60,6 +60,9 @@ PA_MODULE_USAGE("table=<filename> "
 #define DEFAULT_MATCH_TABLE_FILE PA_DEFAULT_CONFIG_DIR"/match.table"
 #define DEFAULT_MATCH_TABLE_FILE_USER "match.table"
 
+#define UPDATE_REPLACE "replace"
+#define UPDATE_MERGE "merge"
+
 static const char* const valid_modargs[] = {
     "table",
     "key",
@@ -70,6 +73,7 @@ struct rule {
     regex_t regex;
     pa_volume_t volume;
     pa_proplist *proplist;
+    pa_update_mode_t mode;
     struct rule *next;
 };
 
@@ -101,13 +105,14 @@ static int load_rules(struct userdata *u, const char *filename) {
     pa_lock_fd(fileno(f), 1);
 
     while (!feof(f)) {
-        char *d, *v;
+        char *token_end, *value_str;
         pa_volume_t volume = PA_VOLUME_NORM;
         uint32_t k;
         regex_t regex;
         char ln[256];
         struct rule *rule;
         pa_proplist *proplist = NULL;
+        pa_update_mode_t mode = (pa_update_mode_t) -1;
 
         if (!fgets(ln, sizeof(ln), f))
             break;
@@ -119,51 +124,72 @@ static int load_rules(struct userdata *u, const char *filename) {
         if (ln[0] == '#' || !*ln )
             continue;
 
-        d = ln+strcspn(ln, WHITESPACE);
-        v = d+strspn(d, WHITESPACE);
+        token_end = ln + strcspn(ln, WHITESPACE);
+        value_str = token_end + strspn(token_end, WHITESPACE);
+        *token_end = 0;
 
+        if (!*ln) {
+            pa_log("[%s:%u] failed to parse line - missing regexp", fn, n);
+            goto finish;
+        }
 
-        if (!*v) {
-            pa_log(__FILE__ ": [%s:%u] failed to parse line - too few words", filename, n);
+        if (!*value_str) {
+            pa_log("[%s:%u] failed to parse line - too few words", fn, n);
             goto finish;
         }
 
-        *d = 0;
-        if (pa_atou(v, &k) >= 0) {
+        if (pa_atou(value_str, &k) >= 0)
             volume = (pa_volume_t) PA_CLAMP_VOLUME(k);
-        } else if (*v == '"') {
-            char *e;
-
-            e = strchr(v+1, '"');
-            if (!e) {
-                pa_log(__FILE__ ": [%s:%u] failed to parse line - missing role closing quote", filename, n);
-                goto finish;
-            }
-
-            *e = '\0';
-            e = pa_sprintf_malloc("media.role=\"%s\"", v+1);
-            proplist = pa_proplist_from_string(e);
-            pa_xfree(e);
-        } else {
-            char *e;
-
-            e = v+strspn(v, WHITESPACE);
-            if (!*e) {
-                pa_log(__FILE__ ": [%s:%u] failed to parse line - missing end of property list", filename, n);
-                goto finish;
-            }
-            *e = '\0';
-            proplist = pa_proplist_from_string(v);
+        else {
+            size_t len;
+
+            token_end = value_str + strcspn(value_str, WHITESPACE);
+
+            len = token_end - value_str;
+            if (len == (sizeof(UPDATE_REPLACE) - 1) && !strncmp(value_str, UPDATE_REPLACE, len))
+                mode = PA_UPDATE_REPLACE;
+            else if (len == (sizeof(UPDATE_MERGE) - 1) && !strncmp(value_str, UPDATE_MERGE, len))
+                mode = PA_UPDATE_MERGE;
+
+            if (mode != (pa_update_mode_t) -1) {
+                value_str = token_end + strspn(token_end, WHITESPACE);
+
+                if (!*value_str) {
+                    pa_log("[%s:%u] failed to parse line - too few words", fn, n);
+                    goto finish;
+                }
+            } else
+                mode = PA_UPDATE_MERGE;
+
+            if (*value_str == '"') {
+                value_str++;
+
+                token_end = strchr(value_str, '"');
+                if (!token_end) {
+                    pa_log("[%s:%u] failed to parse line - missing role closing quote", fn, n);
+                    goto finish;
+                }
+            } else
+                token_end = value_str + strcspn(value_str, WHITESPACE);
+
+            *token_end = 0;
+
+            value_str = pa_sprintf_malloc("media.role=\"%s\"", value_str);
+            proplist = pa_proplist_from_string(value_str);
+            pa_xfree(value_str);
         }
 
         if (regcomp(&regex, ln, REG_EXTENDED|REG_NOSUB) != 0) {
-            pa_log("[%s:%u] invalid regular expression", filename, n);
+            pa_log("[%s:%u] invalid regular expression", fn, n);
+            if (proplist)
+                pa_proplist_free(proplist);
             goto finish;
         }
 
         rule = pa_xnew(struct rule, 1);
         rule->regex = regex;
         rule->proplist = proplist;
+        rule->mode = mode;
         rule->volume = volume;
         rule->next = NULL;
 
@@ -172,8 +198,6 @@ static int load_rules(struct userdata *u, const char *filename) {
         else
             u->rules = rule;
         end = rule;
-
-        *d = 0;
     }
 
     ret = 0;
@@ -184,8 +208,7 @@ finish:
         fclose(f);
     }
 
-    if (fn)
-        pa_xfree(fn);
+    pa_xfree(fn);
 
     return ret;
 }
@@ -206,7 +229,7 @@ static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_n
         if (!regexec(&r->regex, n, 0, NULL, 0)) {
             if (r->proplist) {
                 pa_log_debug("updating proplist of sink input '%s'", n);
-                pa_proplist_update(si->proplist, PA_UPDATE_MERGE, r->proplist);
+                pa_proplist_update(si->proplist, r->mode, r->proplist);
             } else if (si->volume_writable) {
                 pa_cvolume cv;
                 pa_log_debug("changing volume of sink input '%s' to 0x%03x", n, r->volume);
@@ -231,7 +254,7 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    u = pa_xnew(struct userdata, 1);
+    u = pa_xnew0(struct userdata, 1);
     u->rules = NULL;
     m->userdata = u;
 

commit 7055694023a9feffb5591d51f823794216b3d2b2
Author: Tanu Kaskinen <tanu.kaskinen at digia.com>
Date:   Fri Apr 29 13:58:42 2011 +0300

    dbus: Fix connection idxset freeing when unloading the module.
    
    If u->connections isn't empty when module-dbus-protocol is
    unloaded, then connection_free() is called for the
    remaining connections when the idxset is freed.
    connection_free() tries to remove the connection from the
    idxset, but that fails, because the item has already been
    removed from the idxset in this scenario.
    
    The problem is solved by not trying to remove the connection
    from the idxset in connection_free(). Instead, whoever wants
    to delete connections, has to remove the connection from the
    idxset in addition to calling connection_free().

diff --git a/src/modules/dbus/module-dbus-protocol.c b/src/modules/dbus/module-dbus-protocol.c
index aa11cdf..276c6ba 100644
--- a/src/modules/dbus/module-dbus-protocol.c
+++ b/src/modules/dbus/module-dbus-protocol.c
@@ -105,7 +105,6 @@ static void connection_free(struct connection *c) {
     pa_assert_se(pa_dbus_protocol_unregister_connection(c->server->userdata->dbus_protocol, pa_dbus_wrap_connection_get(c->wrap_conn)) >= 0);
 
     pa_client_free(c->client);
-    pa_assert_se(pa_idxset_remove_by_data(c->server->userdata->connections, c, NULL));
     pa_dbus_wrap_connection_free(c->wrap_conn);
     pa_xfree(c);
 }
@@ -514,8 +513,10 @@ static void cleanup_cb(pa_mainloop_api *a, pa_defer_event *e, void *userdata) {
     uint32_t idx;
 
     PA_IDXSET_FOREACH(conn, u->connections, idx) {
-        if (!dbus_connection_get_is_connected(pa_dbus_wrap_connection_get(conn->wrap_conn)))
+        if (!dbus_connection_get_is_connected(pa_dbus_wrap_connection_get(conn->wrap_conn))) {
+            pa_idxset_remove_by_data(u->connections, conn, NULL);
             connection_free(conn);
+        }
     }
 
     u->module->core->mainloop->defer_enable(e, 0);
@@ -579,17 +580,9 @@ fail:
     return -1;
 }
 
-/* Called by idxset when the connection set is freed. */
-static void connection_free_cb(void *p, void *userdata) {
-    struct connection *conn = p;
-
-    pa_assert(conn);
-
-    connection_free(conn);
-}
-
 void pa__done(pa_module *m) {
     struct userdata *u;
+    struct connection *c;
 
     pa_assert(m);
 
@@ -602,8 +595,10 @@ void pa__done(pa_module *m) {
     if (u->cleanup_event)
         m->core->mainloop->defer_free(u->cleanup_event);
 
-    if (u->connections)
-        pa_idxset_free(u->connections, connection_free_cb, NULL);
+    while ((c = pa_idxset_steal_first(u->connections, NULL)))
+        connection_free(c);
+
+    pa_idxset_free(u->connections, NULL, NULL);
 
     if (u->tcp_server)
         server_free(u->tcp_server);

commit 2f7eb35f370bb79c12f229d109fc4dd2b74c9f47
Author: Tanu Kaskinen <tanu.kaskinen at digia.com>
Date:   Fri Apr 29 13:58:43 2011 +0300

    dbus: Fix the order of freeing stuff when unloading module-dbus-protocol.

diff --git a/src/modules/dbus/module-dbus-protocol.c b/src/modules/dbus/module-dbus-protocol.c
index 276c6ba..4969585 100644
--- a/src/modules/dbus/module-dbus-protocol.c
+++ b/src/modules/dbus/module-dbus-protocol.c
@@ -592,14 +592,20 @@ void pa__done(pa_module *m) {
     if (u->core_iface)
         pa_dbusiface_core_free(u->core_iface);
 
-    if (u->cleanup_event)
-        m->core->mainloop->defer_free(u->cleanup_event);
-
     while ((c = pa_idxset_steal_first(u->connections, NULL)))
         connection_free(c);
 
     pa_idxset_free(u->connections, NULL, NULL);
 
+    /* This must not be called before the connections are freed, because if
+     * there are any connections left, they will emit the
+     * org.freedesktop.DBus.Local.Disconnected signal, and
+     * disconnection_filter_cb() will be called. disconnection_filter_cb() then
+     * tries to enable the defer event, and if it's already freed, an assertion
+     * will be hit in mainloop.c. */
+    if (u->cleanup_event)
+        m->core->mainloop->defer_free(u->cleanup_event);
+
     if (u->tcp_server)
         server_free(u->tcp_server);
 

-- 
hooks/post-receive
PulseAudio Sound Server



More information about the pulseaudio-commits mailing list