]> code.delx.au - pulseaudio/blobdiff - src/modules/reserve-monitor.c
modules: Fix resource leak in stream-restore
[pulseaudio] / src / modules / reserve-monitor.c
index 13ecde2b0fdcfdc29055c661d29420b49d31b309..70de870ac95e00b1b0a883818d758b5ed5324263 100644 (file)
 #include <assert.h>
 
 #include "reserve-monitor.h"
+#include "reserve.h"
 
 struct rm_monitor {
        int ref;
 
        char *device_name;
        char *service_name;
+       char *match;
 
        DBusConnection *connection;
 
@@ -51,12 +53,35 @@ struct rm_monitor {
 
 #define SERVICE_PREFIX "org.freedesktop.ReserveDevice1."
 
+#define SERVICE_FILTER                         \
+       "type='signal',"                        \
+       "sender='" DBUS_SERVICE_DBUS "',"       \
+       "interface='" DBUS_INTERFACE_DBUS "',"  \
+       "member='NameOwnerChanged',"            \
+       "arg0='%s'"
+
+static unsigned get_busy(
+       DBusConnection *c,
+       const char *name_owner) {
+
+       const char *un;
+
+       if (!name_owner || !*name_owner)
+               return FALSE;
+
+       /* If we ourselves own the device, then don't consider this 'busy' */
+       if ((un = dbus_bus_get_unique_name(c)))
+               if (strcmp(name_owner, un) == 0)
+                       return FALSE;
+
+       return TRUE;
+}
+
 static DBusHandlerResult filter_handler(
        DBusConnection *c,
        DBusMessage *s,
        void *userdata) {
 
-       DBusMessage *reply;
        rm_monitor *m;
        DBusError error;
 
@@ -78,18 +103,11 @@ static DBusHandlerResult filter_handler(
                        goto invalid;
 
                if (strcmp(name, m->service_name) == 0) {
-                       m->busy = !!(new && *new);
+                       unsigned old_busy = m->busy;
 
-                       /* If we ourselves own the device, then don't consider this 'busy' */
-                       if (m->busy) {
-                               const char *un;
+                       m->busy = get_busy(c, new);
 
-                               if ((un = dbus_bus_get_unique_name(c)))
-                                       if (strcmp(new, un) == 0)
-                                               m->busy = FALSE;
-                       }
-
-                       if (m->change_cb) {
+                       if (m->busy != old_busy && m->change_cb) {
                                m->ref++;
                                m->change_cb(m);
                                rm_release(m);
@@ -97,41 +115,21 @@ static DBusHandlerResult filter_handler(
                }
        }
 
-       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
 invalid:
-       if (!(reply = dbus_message_new_error(
-                     s,
-                     DBUS_ERROR_INVALID_ARGS,
-                     "Invalid arguments")))
-               goto oom;
-
-       if (!dbus_connection_send(c, reply, NULL))
-               goto oom;
-
-       dbus_message_unref(reply);
-
        dbus_error_free(&error);
 
-       return DBUS_HANDLER_RESULT_HANDLED;
-
-oom:
-       if (reply)
-               dbus_message_unref(reply);
-
-       dbus_error_free(&error);
-
-       return DBUS_HANDLER_RESULT_NEED_MEMORY;
+       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
 
 int rm_watch(
        rm_monitor **_m,
        DBusConnection *connection,
-       const char*device_name,
+       const char *device_name,
        rm_change_cb_t change_cb,
        DBusError *error)  {
 
        rm_monitor *m = NULL;
+       char *name_owner;
        int r;
        DBusError _error;
 
@@ -175,11 +173,13 @@ int rm_watch(
 
        m->filtering = 1;
 
-       dbus_bus_add_match(m->connection,
-                          "type='signal',"
-                          "sender='" DBUS_SERVICE_DBUS "',"
-                          "interface='" DBUS_INTERFACE_DBUS "',"
-                          "member='NameOwnerChanged'", error);
+       if (!(m->match = malloc(sizeof(SERVICE_FILTER) - 2 + strlen(m->service_name)))) {
+               r = -ENOMEM;
+               goto fail;
+       }
+
+       sprintf(m->match, SERVICE_FILTER, m->service_name);
+       dbus_bus_add_match(m->connection, m->match, error);
 
        if (dbus_error_is_set(error)) {
                r = -EIO;
@@ -188,12 +188,11 @@ int rm_watch(
 
        m->matching = 1;
 
-       m->busy = dbus_bus_name_has_owner(m->connection, m->service_name, error);
-
-       if (dbus_error_is_set(error)) {
-               r = -EIO;
+       if ((r = rd_dbus_get_name_owner(m->connection, m->service_name, &name_owner, error)) < 0)
                goto fail;
-       }
+
+       m->busy = get_busy(m->connection, name_owner);
+       free(name_owner);
 
        *_m = m;
        return 0;
@@ -220,10 +219,8 @@ void rm_release(rm_monitor *m) {
        if (m->matching)
                dbus_bus_remove_match(
                        m->connection,
-                       "type='signal',"
-                       "sender='" DBUS_SERVICE_DBUS "',"
-                       "interface='" DBUS_INTERFACE_DBUS "',"
-                       "member='NameOwnerChanged'", NULL);
+                       m->match,
+                       NULL);
 
        if (m->filtering)
                dbus_connection_remove_filter(
@@ -233,6 +230,7 @@ void rm_release(rm_monitor *m) {
 
        free(m->device_name);
        free(m->service_name);
+       free(m->match);
 
        if (m->connection)
                dbus_connection_unref(m->connection);