]> code.delx.au - pulseaudio/blobdiff - src/modules/module-hal-detect.c
avoid duplicate loading of modules
[pulseaudio] / src / modules / module-hal-detect.c
index ca22d70be0c87b898bae3b9234e93f342602e39e..d73ca0ce10119be87f31c5eafa1b7a67b5af3803 100644 (file)
@@ -299,7 +299,8 @@ static struct device* hal_device_add(struct userdata *u, const char *udi) {
 
     pa_assert(u);
     pa_assert(u->capability);
-
+    pa_assert(!pa_hashmap_get(u->devices, udi));
+    
 #ifdef HAVE_ALSA
     if (strcmp(u->capability, CAPABILITY_ALSA) == 0)
         m = hal_device_load_alsa(u, udi, &sink_name, &source_name);
@@ -374,22 +375,25 @@ static dbus_bool_t device_has_capability(LibHalContext *context, const char *udi
 static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, const struct timeval *tv, void *userdata) {
     DBusError error;
     struct timerdata *td = userdata;
-    int b;
-    struct device *d;
 
     dbus_error_init(&error);
-    
-    b = libhal_device_exists(td->u->context, td->udi, &error);
-    
-    if (dbus_error_is_set(&error)) {
-        pa_log_error("Error adding device: %s: %s", error.name, error.message);
-        dbus_error_free(&error);
-    } else if (b) {
-        if (!(d = hal_device_add(td->u, td->udi))) 
-            pa_log_debug("Not loaded device %s", td->udi);
-        else {
-            if (d->sink_name)
-                pa_scache_play_item_by_name(td->u->core, "pulse-hotplug", d->sink_name, PA_VOLUME_NORM, 0);
+
+    if (!pa_hashmap_get(td->u->devices, td->udi)) {
+        int b;
+        struct device *d;
+        
+        b = libhal_device_exists(td->u->context, td->udi, &error);
+        
+        if (dbus_error_is_set(&error)) {
+            pa_log_error("Error adding device: %s: %s", error.name, error.message);
+            dbus_error_free(&error);
+        } else if (b) {
+            if (!(d = hal_device_add(td->u, td->udi))) 
+                pa_log_debug("Not loaded device %s", td->udi);
+            else {
+                if (d->sink_name)
+                    pa_scache_play_item_by_name(td->u->core, "pulse-hotplug", d->sink_name, PA_VOLUME_NORM, 0);
+            }
         }
     }
 
@@ -406,6 +410,9 @@ static void device_added_cb(LibHalContext *context, const char *udi) {
     int good = 0;
 
     pa_assert_se(u = libhal_ctx_get_user_data(context));
+
+    if (pa_hashmap_get(u->devices, udi))
+        return;
     
     pa_log_debug("HAL Device added: %s", udi);
 
@@ -503,7 +510,6 @@ static void lost_capability_cb(LibHalContext *context, const char *udi, const ch
         device_removed_cb(context, udi);
 }
 
-
 static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, void *userdata) {
     struct userdata*u = userdata;
     DBusError error;
@@ -540,9 +546,21 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
                 if (d->sink_name) {
                     pa_sink *sink;
                     
-                    if ((sink = pa_namereg_get(u->core, d->sink_name, PA_NAMEREG_SINK, 0)))
-                        if (pa_sink_suspend(sink, suspend) >= 0)
-                            pa_scache_play_item_by_name(u->core, "pulse-access", d->sink_name, PA_VOLUME_NORM, 0);
+                    if ((sink = pa_namereg_get(u->core, d->sink_name, PA_NAMEREG_SINK, 0))) {
+                        
+                        int prev_suspended = pa_sink_get_state(sink) == PA_SINK_SUSPENDED;
+
+                        if (pa_sink_suspend(sink, suspend) >= 0) {
+                            if (!suspend && prev_suspended)
+                                pa_scache_play_item_by_name(u->core, "pulse-access", d->sink_name, PA_VOLUME_NORM, 0);
+                            else if (suspend && !prev_suspended) {
+                                DBusMessage *msg;
+                                msg = dbus_message_new_signal(udi, "org.pulseaudio.Server", "DirtyGiveUpMessage");
+                                dbus_connection_send(pa_dbus_connection_get(u->connection), msg, NULL);
+                                dbus_message_unref(msg);
+                            }
+                        }
+                    }
                 }
 
                 if (d->source_name) {
@@ -551,10 +569,49 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
                     if ((source = pa_namereg_get(u->core, d->source_name, PA_NAMEREG_SOURCE, 0)))
                         pa_source_suspend(source, suspend);
                 }
-            }
-
+                
+            } else if (!suspend)
+                device_added_cb(u->context, udi);
         }
         
+    } else if (dbus_message_is_signal(message, "org.pulseaudio.Server", "DirtyGiveUpMessage")) {
+        /* We use this message to avoid a dirty race condition when we
+           get an ACLAdded message before the previously owning PA
+           sever has closed the device. We can remove this as
+           soon as HAL learns frevoke() */
+
+        const char *udi;
+        struct device *d;
+
+        pa_log_debug("Got dirty give up message, trying resume ...");
+
+        udi = dbus_message_get_path(message);
+        
+        if ((d = pa_hashmap_get(u->devices, udi))) {
+
+            if (d->sink_name) {
+                pa_sink *sink;
+                
+                if ((sink = pa_namereg_get(u->core, d->sink_name, PA_NAMEREG_SINK, 0))) {
+
+                    int prev_suspended = pa_sink_get_state(sink) == PA_SINK_SUSPENDED;
+                    
+                    if (pa_sink_suspend(sink, 0) >= 0)
+                        if (prev_suspended && !prev_suspended)
+                            pa_scache_play_item_by_name(u->core, "pulse-access", d->sink_name, PA_VOLUME_NORM, 0);
+                }
+            }
+            
+            if (d->source_name) {
+                pa_source *source;
+                
+                if ((source = pa_namereg_get(u->core, d->source_name, PA_NAMEREG_SOURCE, 0)))
+                    pa_source_suspend(source, 0);
+            }
+            
+        } else 
+            /* Yes, we don't check the UDI for validity, but hopefully HAL will */
+            device_added_cb(u->context, udi);
     }
 
 finish:
@@ -643,7 +700,7 @@ int pa__init(pa_core *c, pa_module*m) {
     n = hal_device_add_all(u, CAPABILITY_ALSA);
 #endif
 #if defined(HAVE_ALSA) && defined(HAVE_OSS)
-    if (n <= 0)
+    if (!u->capability)
 #endif        
 #ifdef HAVE_OSS
         n += hal_device_add_all(u, CAPABILITY_OSS);
@@ -670,6 +727,12 @@ int pa__init(pa_core *c, pa_module*m) {
         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(conn), "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);