]> code.delx.au - pulseaudio/blobdiff - src/modules/module-hal-detect.c
Merge commit 'origin/master-tx'
[pulseaudio] / src / modules / module-hal-detect.c
index 309b0060d3b549496893f1f469cd19cd7dd3dba3..b6139e4388793e3ed8b5fd0177b858869e4078ef 100644 (file)
@@ -6,7 +6,7 @@
 
     PulseAudio is free software; you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published
-    by the Free Software Foundation; either version 2 of the License,
+    by the Free Software Foundation; either version 2.1 of the License,
     or (at your option) any later version.
 
     PulseAudio is distributed in the hope that it will be useful, but
 #include <pulsecore/namereg.h>
 #include <pulsecore/core-scache.h>
 #include <pulsecore/modargs.h>
+#include <pulsecore/dbus-shared.h>
 
 #include <hal/libhal.h>
 
-#include "dbus-util.h"
 #include "module-hal-detect-symdef.h"
 
 PA_MODULE_AUTHOR("Shahms King");
@@ -121,6 +121,7 @@ static const char *strip_udi(const char *udi) {
 enum alsa_type {
     ALSA_TYPE_PLAYBACK,
     ALSA_TYPE_CAPTURE,
+    ALSA_TYPE_CONTROL,
     ALSA_TYPE_OTHER
 };
 
@@ -141,6 +142,8 @@ static enum alsa_type hal_alsa_device_get_type(LibHalContext *context, const cha
         t = ALSA_TYPE_PLAYBACK;
     else if (pa_streq(type, "capture"))
         t = ALSA_TYPE_CAPTURE;
+    else if (pa_streq(type, "control"))
+        t = ALSA_TYPE_CONTROL;
 
     libhal_free_string(type);
 
@@ -171,7 +174,8 @@ static pa_bool_t hal_alsa_device_is_modem(LibHalContext *context, const char *ud
 
 finish:
     if (dbus_error_is_set(&error)) {
-        pa_log_error("D-Bus error while parsing HAL ALSA data: %s: %s", error.name, error.message);
+        if (!dbus_error_has_name(&error, "org.freedesktop.Hal.NoSuchProperty"))
+            pa_log_error("D-Bus error while parsing HAL ALSA data: %s: %s", error.name, error.message);
         dbus_error_free(&error);
     }
 
@@ -180,7 +184,7 @@ finish:
 
 static int hal_device_load_alsa(struct userdata *u, const char *udi, struct device *d) {
     enum alsa_type type;
-    int device, card;
+    int card;
     DBusError error;
     pa_module *m;
     char *args, *originating_udi = NULL, *card_name = NULL;
@@ -193,16 +197,24 @@ static int hal_device_load_alsa(struct userdata *u, const char *udi, struct devi
 
     /* We only care for PCM devices */
     type = hal_alsa_device_get_type(u->context, udi);
-    if (type == ALSA_TYPE_OTHER)
-        goto fail;
 
-    /* We don't care for modems */
-    if (hal_alsa_device_is_modem(u->context, udi))
+    /* For each ALSA card that appears the control device will be the
+     * last one to be created, this is considered part of the ALSA
+     * usperspace API. We rely on this and load our modules only when
+     * the control device is available assuming that *all* device
+     * nodes have been properly created and assigned the right ACLs at
+     * that time. Also see:
+     *
+     * http://mailman.alsa-project.org/pipermail/alsa-devel/2009-April/015958.html
+     *
+     * and the associated thread.*/
+
+    if (type != ALSA_TYPE_CONTROL)
         goto fail;
 
-    /* We only care for the main device */
-    device = libhal_device_get_property_int(u->context, udi, "alsa.device", &error);
-    if (dbus_error_is_set(&error) || device != 0)
+    /* We don't care for modems -- this is most likely not set for
+     * control devices, so kind of pointless here. */
+    if (hal_alsa_device_is_modem(u->context, udi))
         goto fail;
 
     /* We store only one entry per card, hence we look for the originating device */
@@ -375,6 +387,7 @@ static struct device* hal_device_add(struct userdata *u, const char *udi) {
     d->originating_udi = NULL;
     d->module = PA_INVALID_INDEX;
     d->sink_name = d->source_name = d->card_name = NULL;
+    r = -1;
 
 #ifdef HAVE_ALSA
     if (pa_streq(u->capability, CAPABILITY_ALSA))
@@ -415,9 +428,10 @@ static int hal_device_add_all(struct userdata *u) {
         for (i = 0; i < n; i++) {
             struct device *d;
 
-            if ((d = hal_device_add(u, udis[i])))
+            if ((d = hal_device_add(u, udis[i]))) {
                 count++;
-            else
+                pa_log_debug("Loaded device %s", udis[i]);
+            } else
                 pa_log_debug("Not loaded device %s", udis[i]);
         }
     }
@@ -453,10 +467,13 @@ static void device_added_cb(LibHalContext *context, const char *udi) {
 
     if (!hal_device_add(u, udi))
         pa_log_debug("Not loaded device %s", udi);
+    else
+        pa_log_debug("Loaded device %s", udi);
 
 finish:
     if (dbus_error_is_set(&error)) {
-        pa_log_error("D-Bus error while parsing HAL data: %s: %s", error.name, error.message);
+        if (!dbus_error_has_name(&error, "org.freedesktop.Hal.NoSuchProperty"))
+            pa_log_error("D-Bus error while parsing HAL data: %s: %s", error.name, error.message);
         dbus_error_free(&error);
     }
 }
@@ -773,18 +790,15 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    dbus_bus_add_match(pa_dbus_connection_get(u->connection), "type='signal',sender='org.freedesktop.Hal', interface='org.freedesktop.Hal.Device.AccessControl'", &error);
-    if (dbus_error_is_set(&error)) {
+    if (pa_dbus_add_matches(
+                pa_dbus_connection_get(u->connection), &error,
+                "type='signal',sender='org.freedesktop.Hal',interface='org.freedesktop.Hal.Device.AccessControl',member='ACLAdded'",
+                "type='signal',sender='org.freedesktop.Hal',interface='org.freedesktop.Hal.Device.AccessControl',member='ACLRemoved'",
+                "type='signal',interface='org.pulseaudio.Server',member='DirtyGiveUpMessage'", NULL) < 0) {
         pa_log_error("Unable to subscribe to HAL ACL signals: %s: %s", error.name, error.message);
         goto fail;
     }
 
-    dbus_bus_add_match(pa_dbus_connection_get(u->connection), "type='signal',interface='org.pulseaudio.Server'", &error);
-    if (dbus_error_is_set(&error)) {
-        pa_log_error("Unable to subscribe to PulseAudio signals: %s: %s", error.name, error.message);
-        goto fail;
-    }
-
     pa_log_info("Loaded %i modules.", n);
 
     pa_modargs_free(ma);
@@ -801,7 +815,6 @@ fail:
     return -1;
 }
 
-
 void pa__done(pa_module *m) {
     struct userdata *u;
 
@@ -826,17 +839,13 @@ void pa__done(pa_module *m) {
     }
 
     if (u->connection) {
-        DBusError error;
-        dbus_error_init(&error);
-
-        dbus_bus_remove_match(pa_dbus_connection_get(u->connection), "type='signal',sender='org.freedesktop.Hal', interface='org.freedesktop.Hal.Device.AccessControl'", &error);
-        dbus_error_free(&error);
-
-        dbus_bus_remove_match(pa_dbus_connection_get(u->connection), "type='signal',interface='org.pulseaudio.Server'", &error);
-        dbus_error_free(&error);
+        pa_dbus_remove_matches(
+                pa_dbus_connection_get(u->connection),
+                "type='signal',sender='org.freedesktop.Hal',interface='org.freedesktop.Hal.Device.AccessControl',member='ACLAdded'",
+                "type='signal',sender='org.freedesktop.Hal',interface='org.freedesktop.Hal.Device.AccessControl',member='ACLRemoved'",
+                "type='signal',interface='org.pulseaudio.Server',member='DirtyGiveUpMessage'", NULL);
 
         dbus_connection_remove_filter(pa_dbus_connection_get(u->connection), filter_cb, u);
-
         pa_dbus_connection_unref(u->connection);
     }