[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(®ex, 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