[pulseaudio-discuss] [PATCH] pactl: Added unloading modules by name

poljar poljarinho at gmail.com
Wed May 16 13:39:12 PDT 2012


pactl should allow unloading modules by name.
pactl and the native protocol were expanded to handle names while
unloading modules.

BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=48289
---
 src/map-file                    |    3 ++-
 src/pulse/introspect.c          |   46 +++++++++++++++++++++++++++++++++++++--
 src/pulse/introspect.h          |    8 +++++--
 src/pulsecore/protocol-native.c |   29 ++++++++++++++++++++----
 src/utils/pactl.c               |   13 ++++++++---
 5 files changed, 87 insertions(+), 12 deletions(-)

diff --git a/src/map-file b/src/map-file
index 69cf25b..82fdd06 100644
--- a/src/map-file
+++ b/src/map-file
@@ -113,7 +113,8 @@ pa_context_suspend_sink_by_index;
 pa_context_suspend_sink_by_name;
 pa_context_suspend_source_by_index;
 pa_context_suspend_source_by_name;
-pa_context_unload_module;
+pa_context_unload_module_by_index;
+pa_context_unload_module_by_name;
 pa_context_unref;
 pa_cvolume_avg;
 pa_cvolume_avg_mask;
diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index 38a9d1c..332733b 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -1864,8 +1864,50 @@ pa_operation* pa_context_load_module(pa_context *c, const char*name, const char
     return o;
 }
 
-pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) {
-    return command_kill(c, PA_COMMAND_UNLOAD_MODULE, idx, cb, userdata);
+pa_operation* pa_context_unload_module_by_index(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) {
+    pa_operation *o;
+    pa_tagstruct *t;
+    uint32_t tag;
+
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+    PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
+
+    o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+    t = pa_tagstruct_command(c, PA_COMMAND_UNLOAD_MODULE, &tag);
+    pa_tagstruct_putu32(t, idx);
+    pa_tagstruct_puts(t, NULL);
+    pa_pstream_send_tagstruct(c->pstream, t);
+    pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+    return o;
+}
+
+pa_operation* pa_context_unload_module_by_name(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
+    pa_operation *o;
+    pa_tagstruct *t;
+    uint32_t tag;
+
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+    PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
+
+    o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+    t = pa_tagstruct_command(c, PA_COMMAND_UNLOAD_MODULE, &tag);
+    pa_tagstruct_putu32(t, PA_INVALID_INDEX);
+    pa_tagstruct_puts(t, name);
+    pa_pstream_send_tagstruct(c->pstream, t);
+    pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+    return o;
 }
 
 /*** Autoload stuff ***/
diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h
index 0072f5d..f80fb86 100644
--- a/src/pulse/introspect.h
+++ b/src/pulse/introspect.h
@@ -409,8 +409,12 @@ typedef void (*pa_context_index_cb_t)(pa_context *c, uint32_t idx, void *userdat
 /** Load a module. */
 pa_operation* pa_context_load_module(pa_context *c, const char*name, const char *argument, pa_context_index_cb_t cb, void *userdata);
 
-/** Unload a module. */
-pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
+/** Unload a module by its index. */
+pa_operation* pa_context_unload_module_by_index(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
+
+
+/** Unload a module by its name. */
+pa_operation* pa_context_unload_module_by_name(pa_context *c, const char*name, pa_context_success_cb_t cb, void *userdata);
 
 /** @} */
 
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 396e143..56722e4 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -4434,23 +4434,44 @@ static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag
 static void command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
     uint32_t idx;
+    const char *name;
     pa_module *m;
 
     pa_native_connection_assert_ref(c);
     pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &idx) < 0 ||
+        pa_tagstruct_gets(t, &name) < 0 ||
         !pa_tagstruct_eof(t)) {
         protocol_error(c);
         return;
     }
 
     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
-    m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
-    CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOENTITY);
 
-    pa_module_unload_request(m, FALSE);
-    pa_pstream_send_simple_ack(c->pstream, tag);
+    if (idx != PA_INVALID_INDEX) {
+        CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
+
+        m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
+
+        CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOENTITY);
+
+        pa_module_unload_request(m, FALSE);
+        pa_pstream_send_simple_ack(c->pstream, tag);
+    }
+    else {
+        CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name) && !strchr(name, '/'), tag, PA_ERR_INVALID);
+
+        /* Traverse the module list and unload all modules with the matching name */
+        for (m = pa_idxset_first(c->protocol->core->modules, &idx); m; m = pa_idxset_next(c->protocol->core->modules, &idx)) {
+            if (strcmp(name, m->name) == 0) {
+                CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOENTITY);
+
+                pa_module_unload_request(m, FALSE);
+                pa_pstream_send_simple_ack(c->pstream, tag);
+            }
+        }
+    }
 }
 
 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
diff --git a/src/utils/pactl.c b/src/utils/pactl.c
index 05a1519..b1f72f8 100644
--- a/src/utils/pactl.c
+++ b/src/utils/pactl.c
@@ -32,6 +32,7 @@
 #include <stdlib.h>
 #include <getopt.h>
 #include <locale.h>
+#include <ctype.h>
 
 #include <sndfile.h>
 
@@ -1152,7 +1153,10 @@ static void context_state_callback(pa_context *c, void *userdata) {
                     break;
 
                 case UNLOAD_MODULE:
-                    pa_operation_unref(pa_context_unload_module(c, module_index, simple_callback, NULL));
+                    if (module_name)
+                        pa_operation_unref(pa_context_unload_module_by_name(c, module_name, simple_callback, NULL));
+                    else
+                        pa_operation_unref(pa_context_unload_module_by_index(c, module_index, simple_callback, NULL));
                     break;
 
                 case SUSPEND_SINK:
@@ -1345,7 +1349,7 @@ static void help(const char *argv0) {
     printf("%s %s %s %s\n", argv0, _("[options]"), "play-sample ", _("NAME [SINK]"));
     printf("%s %s %s %s\n", argv0, _("[options]"), "remove-sample ", _("NAME"));
     printf("%s %s %s %s\n", argv0, _("[options]"), "load-module ", _("NAME [ARGS ...]"));
-    printf("%s %s %s %s\n", argv0, _("[options]"), "unload-module ", _("#N"));
+    printf("%s %s %s %s\n", argv0, _("[options]"), "unload-module ", _("NAME|#N"));
     printf("%s %s %s %s\n", argv0, _("[options]"), "move-(sink-input|source-output)", _("#N SINK|SOURCE"));
     printf("%s %s %s %s\n", argv0, _("[options]"), "suspend-(sink|source)", _("NAME|#N 1|0"));
     printf("%s %s %s %s\n", argv0, _("[options]"), "set-card-profile ", _("CARD PROFILE"));
@@ -1572,7 +1576,10 @@ int main(int argc, char *argv[]) {
                 goto quit;
             }
 
-            module_index = (uint32_t) atoi(argv[optind+1]);
+            if (isdigit(argv[optind+1][0]))
+                module_index = (uint32_t) atoi(argv[optind+1]);
+            else
+                module_name = argv[optind+1];
 
         } else if (pa_streq(argv[optind], "suspend-sink")) {
             action = SUSPEND_SINK;
-- 
1.7.10.2



More information about the pulseaudio-discuss mailing list