make autoload list use idxset

git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@262 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
Lennart Poettering 2004-10-27 16:23:23 +00:00
parent f252edb794
commit 1bcec3ef5b
11 changed files with 205 additions and 44 deletions

View file

@ -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

View 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;
pa_hashmap_free(c->autoload_hashmap, free_func, NULL);
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;
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;
}

View file

@ -26,15 +26,20 @@
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

View 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;
}

View 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);

View 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;

View 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;

View 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,

View 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);
}

View 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

View 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;
}