]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/module.c
don't allow --start in system mode
[pulseaudio] / src / pulsecore / module.c
index dce91a71027273b54d57247fc05a54cd0e834931..e003dd7cd78d5079eef582d66585433f96ecc760 100644 (file)
@@ -1,5 +1,3 @@
-/* $Id$ */
-
 /***
   This file is part of PulseAudio.
 
@@ -46,6 +44,7 @@
 
 #define PA_SYMBOL_INIT "pa__init"
 #define PA_SYMBOL_DONE "pa__done"
+#define PA_SYMBOL_LOAD_ONCE "pa__load_once"
 
 #define UNLOAD_POLL_TIME 2
 
@@ -66,6 +65,7 @@ static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED
 
 pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) {
     pa_module *m = NULL;
+    pa_bool_t (*load_once)(void);
 
     pa_assert(c);
     pa_assert(name);
@@ -82,6 +82,22 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) {
         goto fail;
     }
 
+    if ((load_once = (pa_bool_t (*)(void)) pa_load_sym(m->dl, name, PA_SYMBOL_LOAD_ONCE))) {
+
+        if (load_once() && c->modules) {
+            pa_module *i;
+            uint32_t idx;
+            /* OK, the module only wants to be loaded once, let's make sure it is */
+
+            for (i = pa_idxset_first(c->modules, &idx); i; i = pa_idxset_next(c->modules, &idx)) {
+                if (strcmp(name, i->name) == 0) {
+                    pa_log("Module \"%s\" should be loaded once at most. Refusing to load.", name);
+                    goto fail;
+                }
+            }
+        }
+    }
+
     if (!(m->init = (int (*)(pa_module*_m)) pa_load_sym(m->dl, name, PA_SYMBOL_INIT))) {
         pa_log("Failed to load module \"%s\": symbol \""PA_SYMBOL_INIT"\" not found.", name);
         goto fail;
@@ -91,8 +107,8 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) {
     m->userdata = NULL;
     m->core = c;
     m->n_used = -1;
-    m->auto_unload = 0;
-    m->unload_requested = 0;
+    m->auto_unload = FALSE;
+    m->unload_requested = FALSE;
 
     if (m->init(m) < 0) {
         pa_log_error("Failed to load  module \"%s\" (argument: \"%s\"): initialization failed.", name, argument ? argument : "");
@@ -102,7 +118,7 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) {
     if (!c->modules)
         c->modules = pa_idxset_new(NULL, NULL);
 
-    if (!c->module_auto_unload_event) {
+    if (m->auto_unload && !c->module_auto_unload_event) {
         struct timeval ntv;
         pa_gettimeofday(&ntv);
         pa_timeval_add(&ntv, UNLOAD_POLL_TIME*1000000);
@@ -178,25 +194,19 @@ void pa_module_unload_by_index(pa_core *c, uint32_t idx) {
     pa_module_free(m);
 }
 
-static void free_callback(void *p, PA_GCC_UNUSED void *userdata) {
-    pa_module *m = p;
-    pa_assert(m);
-    pa_module_free(m);
-}
-
 void pa_module_unload_all(pa_core *c) {
-    pa_module *m;
 
     pa_assert(c);
 
-    if (!c->modules)
-        return;
+    if (c->modules) {
+        pa_module *m;
 
-    while ((m = pa_idxset_first(c->modules, NULL)))
-        pa_module_unload(c, m);
+        while ((m = pa_idxset_steal_first(c->modules, NULL)))
+            pa_module_free(m);
 
-    pa_idxset_free(c->modules, free_callback, NULL);
-    c->modules = NULL;
+        pa_idxset_free(c->modules, NULL, NULL);
+        c->modules = NULL;
+    }
 
     if (c->module_auto_unload_event) {
         c->mainloop->time_free(c->module_auto_unload_event);
@@ -209,61 +219,53 @@ void pa_module_unload_all(pa_core *c) {
     }
 }
 
-static int unused_callback(void *p, PA_GCC_UNUSED uint32_t idx, int *del, void *userdata) {
-    pa_module *m = p;
-    time_t *now = userdata;
-
-    pa_assert(m);
-    pa_assert(del);
-    pa_assert(now);
-
-    if (m->n_used == 0 && m->auto_unload && m->last_used_time+m->core->module_idle_time <= *now) {
-        pa_module_free(m);
-        *del = 1;
-    }
-
-    return 0;
-}
-
 void pa_module_unload_unused(pa_core *c) {
+    void *state = NULL;
     time_t now;
+    pa_module *m;
+
     pa_assert(c);
 
     if (!c->modules)
         return;
 
     time(&now);
-    pa_idxset_foreach(c->modules, unused_callback, &now);
-}
 
-static int unload_callback(void *p, PA_GCC_UNUSED uint32_t idx, int *del, PA_GCC_UNUSED void *userdata) {
-    pa_module *m = p;
-    pa_assert(m);
+    while ((m = pa_idxset_iterate(c->modules, &state, NULL))) {
 
-    if (m->unload_requested) {
-        pa_module_free(m);
-        *del = 1;
-    }
+        if (m->n_used > 0)
+            continue;
 
-    return 0;
+        if (!m->auto_unload)
+            continue;
+
+        if (m->last_used_time + m->core->module_idle_time > now)
+            continue;
+
+        pa_module_unload(c, m);
+    }
 }
 
 static void defer_cb(pa_mainloop_api*api, pa_defer_event *e, void *userdata) {
-    pa_core *core = PA_CORE(userdata);
+    void *state = NULL;
+    pa_core *c = PA_CORE(userdata);
+    pa_module *m;
 
-    pa_core_assert_ref(core);
+    pa_core_assert_ref(c);
     api->defer_enable(e, 0);
 
-    if (!core->modules)
+    if (!c->modules)
         return;
 
-    pa_idxset_foreach(core->modules, unload_callback, NULL);
+    while ((m = pa_idxset_iterate(c->modules, &state, NULL)))
+        if (m->unload_requested)
+            pa_module_unload(c, m);
 }
 
 void pa_module_unload_request(pa_module *m) {
     pa_assert(m);
 
-    m->unload_requested = 1;
+    m->unload_requested = TRUE;
 
     if (!m->core->module_defer_unload_event)
         m->core->module_defer_unload_event = m->core->mainloop->defer_new(m->core->mainloop, defer_cb, m->core);