]> code.delx.au - pulseaudio/commitdiff
make autoload list use idxset
authorLennart Poettering <lennart@poettering.net>
Wed, 27 Oct 2004 16:23:23 +0000 (16:23 +0000)
committerLennart Poettering <lennart@poettering.net>
Wed, 27 Oct 2004 16:23:23 +0000 (16:23 +0000)
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@262 fefdeb5f-60dc-0310-8127-8f9354f1896f

doc/todo
polyp/autoload.c
polyp/autoload.h
polyp/cli-command.c
polyp/cli-text.c
polyp/core.c
polyp/core.h
polyp/pactl.c
polyp/polyplib-introspect.c
polyp/polyplib-introspect.h
polyp/protocol-native.c

index fa97b4a3761ce893b6e0c5dfb8a140f0a809ba22..1ffdee4918ae75b20fb2090a317d6f5fa91baaa0 100644 (file)
--- a/doc/todo
+++ b/doc/todo
@@ -1,6 +1,6 @@
 *** $Id$ ***
 
-*** 0.6 ****
+*** 0.7 ****
 - per-channel volume
 - unix socket directories include user name
 - add sample directory
@@ -9,7 +9,6 @@
 - improve module-oss-mmap latency measurement
 - filter capture data in client through alignment
 - add radio module
-- make autoload list use idxset
 - add sync API
 - make most buffer sizes dependant on the sample type
 
index 12cd1f91e1bd218792f5d85e562662d8e05b03b5..d6207962d3a88cdd372a40aeefd4841de22d5b0a 100644 (file)
@@ -45,6 +45,14 @@ static void entry_free(struct pa_autoload_entry *e) {
     pa_xfree(e);
 }
 
+static void entry_remove_and_free(struct pa_autoload_entry *e) {
+    assert(e && e->core);
+
+    pa_idxset_remove_by_data(e->core->autoload_idxset, e, NULL);
+    pa_hashmap_remove(e->core->autoload_hashmap, e->name);
+    entry_free(e);
+}
+
 static struct pa_autoload_entry* entry_new(struct pa_core *c, const char *name) {
     struct pa_autoload_entry *e = NULL;
     assert(c && name);
@@ -64,12 +72,16 @@ static struct pa_autoload_entry* entry_new(struct pa_core *c, const char *name)
     
     pa_hashmap_put(c->autoload_hashmap, e->name, e);
 
-    pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_AUTOLOAD|PA_SUBSCRIPTION_EVENT_NEW, PA_INVALID_INDEX);
+    if (!c->autoload_idxset)
+        c->autoload_idxset = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
+    pa_idxset_put(c->autoload_idxset, e, &e->index);
+
+    pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_AUTOLOAD|PA_SUBSCRIPTION_EVENT_NEW, e->index);
     
     return e;
 }
 
-int pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument) {
+int pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument, uint32_t *index) {
     struct pa_autoload_entry *e = NULL;
     assert(c && name && module && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE));
     
@@ -79,18 +91,32 @@ int pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type typ
     e->module = pa_xstrdup(module);
     e->argument = pa_xstrdup(argument);
     e->type = type;
+
+    if (index)
+        *index = e->index;
+    
     return 0;
 }
 
-int pa_autoload_remove(struct pa_core *c, const char*name, enum pa_namereg_type type) {
+int pa_autoload_remove_by_name(struct pa_core *c, const char*name, enum pa_namereg_type type) {
     struct pa_autoload_entry *e;
     assert(c && name && type);
 
-    if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)))
+    if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || e->type != type)
         return -1;
 
-    pa_hashmap_remove(c->autoload_hashmap, e->name);
-    entry_free(e);
+    entry_remove_and_free(e);
+    return 0;
+}
+
+int pa_autoload_remove_by_index(struct pa_core *c, uint32_t index) {
+    struct pa_autoload_entry *e;
+    assert(c && index != PA_IDXSET_INVALID);
+
+    if (!c->autoload_idxset || !(e = pa_idxset_get_by_index(c->autoload_idxset, index)))
+        return -1;
+
+    entry_remove_and_free(e);
     return 0;
 }
 
@@ -117,12 +143,38 @@ void pa_autoload_request(struct pa_core *c, const char *name, enum pa_namereg_ty
 
 static void free_func(void *p, void *userdata) {
     struct pa_autoload_entry *e = p;
+    pa_idxset_remove_by_data(e->core->autoload_idxset, e, NULL);
     entry_free(e);
 }
 
 void pa_autoload_free(struct pa_core *c) {
-    if (!c->autoload_hashmap)
-        return;
+    if (c->autoload_hashmap) {
+        pa_hashmap_free(c->autoload_hashmap, free_func, NULL);
+        c->autoload_hashmap = NULL;
+    }
+    
+    if (c->autoload_idxset) {
+        pa_idxset_free(c->autoload_idxset, NULL, NULL);
+        c->autoload_idxset = NULL;
+    }
+}
+
+const struct pa_autoload_entry* pa_autoload_get_by_name(struct pa_core *c, const char*name, enum pa_namereg_type type) {
+    struct pa_autoload_entry *e;
+    assert(c && name);
+    
+    if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || e->type != type)
+        return NULL;
 
-    pa_hashmap_free(c->autoload_hashmap, free_func, NULL);
+    return e;
+}
+
+const struct pa_autoload_entry* pa_autoload_get_by_index(struct pa_core *c, uint32_t index) {
+    struct pa_autoload_entry *e;
+    assert(c && index != PA_IDXSET_INVALID);
+    
+    if (!c->autoload_idxset || !(e = pa_idxset_get_by_index(c->autoload_idxset, index)))
+        return NULL;
+
+    return e;
 }
index f80b1f0dd88b67aed30bdc45ce848da3ee98b11b..ec7d38f1058fa23aae780c84902a107e6759eb19 100644 (file)
 
 struct pa_autoload_entry {
     struct pa_core *core;
+    uint32_t index;
     char *name;
     enum pa_namereg_type type;
     int in_action;
     char *module, *argument;   
 };
 
-int pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument);
+int pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument, uint32_t *index);
 void pa_autoload_free(struct pa_core *c);
-int pa_autoload_remove(struct pa_core *c, const char*name, enum pa_namereg_type type);
+int pa_autoload_remove_by_name(struct pa_core *c, const char*name, enum pa_namereg_type type);
+int pa_autoload_remove_by_index(struct pa_core *c, uint32_t index);
 void pa_autoload_request(struct pa_core *c, const char *name, enum pa_namereg_type type);
 
+const struct pa_autoload_entry* pa_autoload_get_by_name(struct pa_core *c, const char*name, enum pa_namereg_type type);
+const struct pa_autoload_entry* pa_autoload_get_by_index(struct pa_core *c, uint32_t index);
+
 #endif
index 39ea9cc1ed0f9d949698352693cc08c6417867e7..62981b4d9dc63ac6e2467102fd266412b04a24d2 100644 (file)
@@ -570,7 +570,7 @@ static int pa_cli_command_autoload_add(struct pa_core *c, struct pa_tokenizer *t
         return -1;
     }
 
-    pa_autoload_add(c, a, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, b, pa_tokenizer_get(t, 3));
+    pa_autoload_add(c, a, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, b, pa_tokenizer_get(t, 3), NULL);
     
     return 0;
 }
@@ -584,7 +584,7 @@ static int pa_cli_command_autoload_remove(struct pa_core *c, struct pa_tokenizer
         return -1;
     }
 
-    if (pa_autoload_remove(c, name, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE) < 0) {
+    if (pa_autoload_remove_by_name(c, name, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE) < 0) {
         pa_strbuf_puts(buf, "Failed to remove autload entry\n");
         return -1;
     }
index f9bc6c7a7805b2cce896d948965e3aeaf7510654..c08b0d9cf3de95d27494128bd3711d8229af7d86 100644 (file)
@@ -243,7 +243,7 @@ char *pa_scache_list_to_string(struct pa_core *c) {
             }
             
             pa_strbuf_printf(
-                s, "    name: <%s>\n\tindex: <%i>\n\tsample_spec: <%s>\n\tlength: <%u>\n\tduration: <%0.1fs>\n\tvolume: <0x%04x>\n\tlazy: %s\n\tfilename: %s\n",
+                s, "    name: <%s>\n\tindex: <%u>\n\tsample_spec: <%s>\n\tlength: <%u>\n\tduration: <%0.1fs>\n\tvolume: <0x%04x>\n\tlazy: %s\n\tfilename: %s\n",
                 e->name,
                 e->index,
                 ss,
@@ -273,9 +273,10 @@ char *pa_autoload_list_to_string(struct pa_core *c) {
 
         while ((e = pa_hashmap_iterate(c->autoload_hashmap, &state))) {
             pa_strbuf_printf(
-                s, "    name: <%s>\n\ttype: <%s>\n\tmodule_name: <%s>\n\targuments: <%s>\n",
+                s, "    name: <%s>\n\ttype: <%s>\n\tindex: <%u>\n\tmodule_name: <%s>\n\targuments: <%s>\n",
                 e->name,
                 e->type == PA_NAMEREG_SOURCE ? "source" : "sink",
+                e->index,
                 e->module,
                 e->argument);
 
index cf2d383c4870dab05fe74097b829b0bfe4c7b688..c53d2e4ee38f0931df80b24e45bebbc8c9437ca5 100644 (file)
@@ -56,7 +56,7 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) {
     c->modules = NULL;
     c->namereg = NULL;
     c->scache = NULL;
-
+    c->autoload_idxset = NULL;
     c->autoload_hashmap = NULL;
 
     c->default_sample_spec.format = PA_SAMPLE_S16NE;
index 62959d0afece1a48b324ef7e9b6feffd310a7a18..c457c3fd6e6a50c17f7726d88ec2696d18be4b56 100644 (file)
@@ -31,7 +31,7 @@
 struct pa_core {
     struct pa_mainloop_api *mainloop;
 
-    struct pa_idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules, *scache;
+    struct pa_idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules, *scache, *autoload_idxset;
 
     struct pa_hashmap *namereg, *autoload_hashmap;
 
index fbedc6fa8d9ce38df9c42d22bde874062e4e6724..29c06f913de929e77a7099aa70ab867c408d72c4 100644 (file)
@@ -437,11 +437,12 @@ static void get_autoload_info_callback(struct pa_context *c, const struct pa_aut
         printf("\n");
     nl = 1;
 
-    printf("*** Autoload Entry ***\n"
+    printf("*** Autoload Entry #%u ***\n"
            "Name: %s\n"
            "Type: %s\n"
            "Module: %s\n"
            "Argument: %s\n",
+           i->index,
            i->name,
            i->type == PA_AUTOLOAD_SINK ? "sink" : "source",
            i->module,
index 267af95b7badeaf380fced6f93a2426162aad4a1..af5fd168e579b1430fce870edf15f64fece42bb1 100644 (file)
@@ -823,7 +823,8 @@ static void context_get_autoload_info_callback(struct pa_pdispatch *pd, uint32_t
         while (!pa_tagstruct_eof(t)) {
             struct pa_autoload_info i;
             
-            if (pa_tagstruct_gets(t, &i.name) < 0 ||
+            if (pa_tagstruct_getu32(t, &i.index) < 0 ||
+                pa_tagstruct_gets(t, &i.name) < 0 ||
                 pa_tagstruct_getu32(t, &i.type) < 0 ||
                 pa_tagstruct_gets(t, &i.module) < 0 ||
                 pa_tagstruct_gets(t, &i.argument) < 0) {
@@ -848,7 +849,7 @@ finish:
     pa_operation_unref(o);
 }
 
-struct pa_operation* pa_context_get_autoload_info(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata) {
+struct pa_operation* pa_context_get_autoload_info_by_name(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata) {
     struct pa_tagstruct *t;
     struct pa_operation *o;
     uint32_t tag;
@@ -869,10 +870,58 @@ struct pa_operation* pa_context_get_autoload_info(struct pa_context *c, const ch
     return pa_operation_ref(o);
 }
 
+struct pa_operation* pa_context_get_autoload_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata) {
+    struct pa_tagstruct *t;
+    struct pa_operation *o;
+    uint32_t tag;
+    assert(c && cb && index != PA_INVALID_INDEX);
+
+    o = pa_operation_new(c, NULL);
+    o->callback = cb;
+    o->userdata = userdata;
+
+    t = pa_tagstruct_new(NULL, 0);
+    pa_tagstruct_putu32(t, PA_COMMAND_GET_AUTOLOAD_INFO);
+    pa_tagstruct_putu32(t, tag = c->ctag++);
+    pa_tagstruct_putu32(t, index);
+    pa_pstream_send_tagstruct(c->pstream, t);
+    pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_autoload_info_callback, o);
+
+    return pa_operation_ref(o);
+}
+
 struct pa_operation* pa_context_get_autoload_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata) {
     return pa_context_send_simple_command(c, PA_COMMAND_GET_AUTOLOAD_INFO_LIST, context_get_autoload_info_callback, cb, userdata);
 }
 
+static void context_add_autoload_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+    struct pa_operation *o = userdata;
+    uint32_t index;
+    assert(pd && o && o->context && o->ref >= 1);
+
+    if (command != PA_COMMAND_REPLY) {
+        if (pa_context_handle_error(o->context, command, t) < 0)
+            goto finish;
+
+        index = PA_INVALID_INDEX;
+    } else if (pa_tagstruct_getu32(t, &index) ||
+               !pa_tagstruct_eof(t)) {
+        pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+        goto finish;
+    }
+
+    if (o->callback) {
+        void (*cb)(struct pa_context *s, uint32_t index, void *userdata) = o->callback;
+        cb(o->context, index, o->userdata);
+    }
+
+
+finish:
+    pa_operation_done(o);
+    pa_operation_unref(o);
+}
+
+
 struct pa_operation* pa_context_add_autoload(struct pa_context *c, const char *name, enum pa_autoload_type type, const char *module, const char*argument, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata) {
     struct pa_operation *o;
     struct pa_tagstruct *t;
@@ -891,12 +940,12 @@ struct pa_operation* pa_context_add_autoload(struct pa_context *c, const char *n
     pa_tagstruct_puts(t, module);
     pa_tagstruct_puts(t, argument);
     pa_pstream_send_tagstruct(c->pstream, t);
-    pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
+    pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_add_autoload_callback, o);
 
     return pa_operation_ref(o);
 }
 
-struct pa_operation* pa_context_remove_autoload(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata) {
+struct pa_operation* pa_context_remove_autoload_by_name(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata) {
     struct pa_operation *o;
     struct pa_tagstruct *t;
     uint32_t tag;
@@ -916,3 +965,23 @@ struct pa_operation* pa_context_remove_autoload(struct pa_context *c, const char
 
     return pa_operation_ref(o);
 }
+
+struct pa_operation* pa_context_remove_autoload_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata) {
+    struct pa_operation *o;
+    struct pa_tagstruct *t;
+    uint32_t tag;
+    assert(c && index != PA_INVALID_INDEX);
+
+    o = pa_operation_new(c, NULL);
+    o->callback = cb;
+    o->userdata = userdata;
+
+    t = pa_tagstruct_new(NULL, 0);
+    pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_AUTOLOAD);
+    pa_tagstruct_putu32(t, tag = c->ctag++);
+    pa_tagstruct_putu32(t, index);
+    pa_pstream_send_tagstruct(c->pstream, t);
+    pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
+
+    return pa_operation_ref(o);
+}
index 9e6c31b28a4fbf3c485a4dc0926b9a0245fbbed7..f4dbd185e54b72adc6fb493fe11cda42ba9fd11d 100644 (file)
@@ -234,23 +234,31 @@ enum pa_autoload_type {
 
 /** Stores information about autoload entries. \since 0.5 */
 struct pa_autoload_info {
+    uint32_t index;               /**< Index of this autoload entry */
     const char *name;             /**< Name of the sink or source */
     enum pa_autoload_type type;   /**< Type of the autoload entry */
     const char *module;           /**< Module name to load */
     const char *argument;         /**< Argument string for module */
 };
 
-/** Get info about a specific autoload entry. \since 0.5 */
-struct pa_operation* pa_context_get_autoload_info(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata);
+/** Get info about a specific autoload entry. \since 0.6 */
+struct pa_operation* pa_context_get_autoload_info_by_name(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata);
+
+/** Get info about a specific autoload entry. \since 0.6 */
+struct pa_operation* pa_context_get_autoload_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata);
 
 /** Get the complete list of autoload entries. \since 0.5 */
 struct pa_operation* pa_context_get_autoload_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata);
 
 /** Add a new autoload entry. \since 0.5 */
-struct pa_operation* pa_context_add_autoload(struct pa_context *c, const char *name, enum pa_autoload_type type, const char *module, const char*argument, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata);
+struct pa_operation* pa_context_add_autoload(struct pa_context *c, const char *name, enum pa_autoload_type type, const char *module, const char*argument, void (*cb)(struct pa_context *c, int index, void *userdata), void* userdata);
+
+/** Remove an autoload entry. \since 0.6 */
+struct pa_operation* pa_context_remove_autoload_by_name(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata);
+
+/** Remove an autoload entry. \since 0.6 */
+struct pa_operation* pa_context_remove_autoload_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata);
 
-/** Remove an autoload entry. \since 0.5 */
-struct pa_operation* pa_context_remove_autoload(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata);
 
 PA_C_DECL_END
 
index 31ab4ab8c548e85e4f499ed7b1df112956f70ba3..7af8bdda40051c41016e2c20d9e7cce666e54afe 100644 (file)
@@ -1729,6 +1729,8 @@ static void command_add_autoload(struct pa_pdispatch *pd, uint32_t command, uint
     struct connection *c = userdata;
     const char *name, *module, *argument;
     uint32_t type;
+    uint32_t index;
+    struct pa_tagstruct *reply;
     assert(c && t);
 
     if (pa_tagstruct_gets(t, &name) < 0 || !name ||
@@ -1745,22 +1747,30 @@ static void command_add_autoload(struct pa_pdispatch *pd, uint32_t command, uint
         return;
     }
 
-    if (pa_autoload_add(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, module, argument) < 0) {
+    if (pa_autoload_add(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, module, argument, &index) < 0) {
         pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST);
         return;
     }
 
-    pa_pstream_send_simple_ack(c->pstream, tag);
+    reply = pa_tagstruct_new(NULL, 0);
+    pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
+    pa_tagstruct_putu32(reply, tag);
+    pa_tagstruct_putu32(reply, index);
+    pa_pstream_send_tagstruct(c->pstream, reply);
 }
 
 static void command_remove_autoload(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
     struct connection *c = userdata;
-    const char *name;
-    uint32_t type;
+    const char *name = NULL;
+    uint32_t type, index = PA_IDXSET_INVALID;
+    int r;
     assert(c && t);
 
-    if (pa_tagstruct_gets(t, &name) < 0 || !name ||
-        pa_tagstruct_getu32(t, &type) < 0 || type > 1 ||
+    if ((pa_tagstruct_getu32(t, &index) < 0 &&
+        (pa_tagstruct_gets(t, &name) < 0 ||
+         pa_tagstruct_getu32(t, &type) < 0)) ||
+        (!name && index == PA_IDXSET_INVALID) ||
+        (name && type > 1) ||
         !pa_tagstruct_eof(t)) {
         protocol_error(c);
         return;
@@ -1771,7 +1781,12 @@ static void command_remove_autoload(struct pa_pdispatch *pd, uint32_t command, u
         return;
     }
 
-    if (pa_autoload_remove(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE) < 0) {
+    if (name) 
+        r = pa_autoload_remove_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE);
+    else
+        r = pa_autoload_remove_by_index(c->protocol->core, index);
+
+    if (r < 0) {
         pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
         return;
     }
@@ -1779,8 +1794,10 @@ static void command_remove_autoload(struct pa_pdispatch *pd, uint32_t command, u
     pa_pstream_send_simple_ack(c->pstream, tag);
 }
 
-static void autoload_fill_tagstruct(struct pa_tagstruct *t, struct pa_autoload_entry *e) {
+static void autoload_fill_tagstruct(struct pa_tagstruct *t, const struct pa_autoload_entry *e) {
     assert(t && e);
+
+    pa_tagstruct_putu32(t, e->index);
     pa_tagstruct_puts(t, e->name);
     pa_tagstruct_putu32(t, e->type == PA_NAMEREG_SINK ? 0 : 1);
     pa_tagstruct_puts(t, e->module);
@@ -1789,14 +1806,17 @@ static void autoload_fill_tagstruct(struct pa_tagstruct *t, struct pa_autoload_e
 
 static void command_get_autoload_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
     struct connection *c = userdata;
-    struct pa_autoload_entry *a = NULL;
-    uint32_t type;
+    const struct pa_autoload_entry *a = NULL;
+    uint32_t type, index;
     const char *name;
     struct pa_tagstruct *reply;
     assert(c && t);
-    
-    if (pa_tagstruct_gets(t, &name) < 0 || name ||
-        pa_tagstruct_getu32(t, &type) < 0 || type > 1 ||
+
+    if ((pa_tagstruct_getu32(t, &index) < 0 &&
+        (pa_tagstruct_gets(t, &name) < 0 ||
+         pa_tagstruct_getu32(t, &type) < 0)) ||
+        (!name && index == PA_IDXSET_INVALID) ||
+        (name && type > 1) ||
         !pa_tagstruct_eof(t)) {
         protocol_error(c);
         return;
@@ -1807,7 +1827,13 @@ static void command_get_autoload_info(struct pa_pdispatch *pd, uint32_t command,
         return;
     }
 
-    if (!c->protocol->core->autoload_hashmap || !(a = pa_hashmap_get(c->protocol->core->autoload_hashmap, name)) || (a->type == PA_NAMEREG_SINK && type != 0) || (a->type == PA_NAMEREG_SOURCE && type != 1)) {
+
+    if (name)
+        a = pa_autoload_get_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE);
+    else
+        a = pa_autoload_get_by_index(c->protocol->core, index);
+
+    if (!a) {
         pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
         return;
     }