From a74cd2a1bd92eac6a4140d0794ac4b557be6c133 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 27 Jun 2004 22:42:17 +0000 Subject: add name registrar git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@39 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 5 +- src/core.c | 4 ++ src/core.h | 3 + src/hashset.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++ src/hashset.h | 16 ++++++ src/idxset.c | 28 +++++++--- src/idxset.h | 8 ++- src/module-oss-mmap.c | 4 +- src/module-oss.c | 4 +- src/module-pipe-sink.c | 2 +- src/namereg.c | 97 +++++++++++++++++++++++++++++++++ src/namereg.h | 17 ++++++ src/sink.c | 15 ++++- src/sink.h | 2 +- src/source.c | 12 +++- src/source.h | 2 +- src/todo | 16 ++++-- 17 files changed, 354 insertions(+), 26 deletions(-) create mode 100644 src/hashset.c create mode 100644 src/hashset.h create mode 100644 src/namereg.c create mode 100644 src/namereg.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 75da02c1..a67f395e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -49,7 +49,10 @@ polypaudio_SOURCES = idxset.c idxset.h \ module.c module.h \ mainloop-signal.c mainloop-signal.h \ mainloop-api.c mainloop-api.h \ - util.c util.h + util.c util.h \ + hashset.c hashset.h \ + namereg.c namereg.h + polypaudio_CFLAGS = $(AM_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) diff --git a/src/core.c b/src/core.c index d9df38e1..ec38da91 100644 --- a/src/core.c +++ b/src/core.c @@ -6,6 +6,7 @@ #include "module.h" #include "sink.h" #include "source.h" +#include "namereg.h" struct core* core_new(struct pa_mainloop_api *m) { struct core* c; @@ -22,6 +23,7 @@ struct core* core_new(struct pa_mainloop_api *m) { c->default_source_index = c->default_sink_index = IDXSET_INVALID; c->modules = NULL; + c->namereg = NULL; return c; }; @@ -47,6 +49,8 @@ void core_free(struct core *c) { assert(idxset_isempty(c->sink_inputs)); idxset_free(c->sink_inputs, NULL, NULL); + namereg_free(c); + free(c); }; diff --git a/src/core.h b/src/core.h index 8c4c6233..289bec85 100644 --- a/src/core.h +++ b/src/core.h @@ -2,6 +2,7 @@ #define foocorehfoo #include "idxset.h" +#include "hashset.h" #include "mainloop-api.h" struct core { @@ -9,6 +10,8 @@ struct core { struct idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules; + struct hashset *namereg; + uint32_t default_source_index, default_sink_index; }; diff --git a/src/hashset.c b/src/hashset.c new file mode 100644 index 00000000..298650d5 --- /dev/null +++ b/src/hashset.c @@ -0,0 +1,145 @@ +#include +#include +#include + +#include "hashset.h" +#include "idxset.h" + +struct hashset_entry { + struct hashset_entry *next, *previous, *bucket_next, *bucket_previous; + unsigned hash; + const void *key; + void *value; +}; + +struct hashset { + unsigned size; + struct hashset_entry **data; + struct hashset_entry *first_entry; + + unsigned n_entries; + unsigned (*hash_func) (const void *p); + int (*compare_func) (const void*a, const void*b); +}; + +struct hashset *hashset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { + struct hashset *h; + h = malloc(sizeof(struct hashset)); + assert(h); + h->data = malloc(sizeof(struct hashset_entry*)*(h->size = 1023)); + assert(h->data); + memset(h->data, 0, sizeof(struct hashset_entry*)*(h->size = 1023)); + h->first_entry = NULL; + h->n_entries = 0; + h->hash_func = hash_func ? hash_func : idxset_trivial_hash_func; + h->compare_func = compare_func ? compare_func : idxset_trivial_compare_func; + return h; +} + +static void remove(struct hashset *h, struct hashset_entry *e) { + assert(e); + + if (e->next) + e->next->previous = e->previous; + if (e->previous) + e->previous->next = e->next; + else + h->first_entry = e->next; + + if (e->bucket_next) + e->bucket_next->bucket_previous = e->bucket_previous; + if (e->bucket_previous) + e->bucket_previous->bucket_next = e->bucket_next; + else + h->data[e->hash] = e->bucket_next; + + free(e); + h->n_entries--; +} + +void hashset_free(struct hashset*h, void (*free_func)(void *p, void *userdata), void *userdata) { + assert(h); + + while (h->first_entry) { + if (free_func) + free_func(h->first_entry->value, userdata); + remove(h, h->first_entry); + } + + free(h->data); + free(h); +} + +static struct hashset_entry *get(struct hashset *h, unsigned hash, const void *key) { + struct hashset_entry *e; + + for (e = h->data[hash]; e; e = e->bucket_next) + if (h->compare_func(e->key, key) == 0) + return e; + + return NULL; +} + +int hashset_put(struct hashset *h, const void *key, void *value) { + struct hashset_entry *e; + unsigned hash; + assert(h && key); + + hash = h->hash_func(key) % h->size; + + if ((e = get(h, hash, key))) + return -1; + + e = malloc(sizeof(struct hashset_entry)); + assert(e); + + e->hash = hash; + e->key = key; + e->value = value; + + e->previous = NULL; + e->next = h->first_entry; + if (h->first_entry) + h->first_entry->previous = e; + h->first_entry = e; + + e->bucket_previous = NULL; + e->bucket_next = h->data[hash]; + if (h->data[hash]) + h->data[hash]->bucket_previous = e; + h->data[hash] = e; + + h->n_entries ++; + return 0; +} + +void* hashset_get(struct hashset *h, const void *key) { + unsigned hash; + struct hashset_entry *e; + assert(h && key); + + hash = h->hash_func(key) % h->size; + + if (!(e = get(h, hash, key))) + return NULL; + + return e->value; +} + +int hashset_remove(struct hashset *h, const void *key) { + struct hashset_entry *e; + unsigned hash; + assert(h && key); + + hash = h->hash_func(key) % h->size; + + if (!(e = get(h, hash, key))) + return 1; + + remove(h, e); + return 0; +} + +unsigned hashset_ncontents(struct hashset *h) { + return h->n_entries; +} diff --git a/src/hashset.h b/src/hashset.h new file mode 100644 index 00000000..7e035c02 --- /dev/null +++ b/src/hashset.h @@ -0,0 +1,16 @@ +#ifndef foohashsethfoo +#define foohashsethfoo + +struct hashset; + +struct hashset *hashset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)); +void hashset_free(struct hashset*, void (*free_func)(void *p, void *userdata), void *userdata); + +int hashset_put(struct hashset *h, const void *key, void *value); +void* hashset_get(struct hashset *h, const void *key); + +int hashset_remove(struct hashset *h, const void *key); + +unsigned hashset_ncontents(struct hashset *h); + +#endif diff --git a/src/idxset.c b/src/idxset.c index ea609f60..090bfc72 100644 --- a/src/idxset.c +++ b/src/idxset.c @@ -15,29 +15,43 @@ struct idxset_entry { }; struct idxset { - unsigned (*hash_func) (void *p); - int (*compare_func)(void *a, void *b); + unsigned (*hash_func) (const void *p); + int (*compare_func)(const void *a, const void *b); unsigned hash_table_size, n_entries; struct idxset_entry **hash_table, **array, *iterate_list_head, *iterate_list_tail; uint32_t index, start_index, array_size; }; -static unsigned trivial_hash_func(void *p) { +unsigned idxset_string_hash_func(const void *p) { + unsigned hash = 0; + const char *c; + + for (c = p; *c; c++) + hash = 31 * hash + *c; + + return hash; +} + +int idxset_string_compare_func(const void *a, const void *b) { + return strcmp(a, b); +} + +unsigned idxset_trivial_hash_func(const void *p) { return (unsigned) p; } -static int trivial_compare_func(void *a, void *b) { +int idxset_trivial_compare_func(const void *a, const void *b) { return a != b; } -struct idxset* idxset_new(unsigned (*hash_func) (void *p), int (*compare_func) (void*a, void*b)) { +struct idxset* idxset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { struct idxset *s; s = malloc(sizeof(struct idxset)); assert(s); - s->hash_func = hash_func ? hash_func : trivial_hash_func; - s->compare_func = compare_func ? compare_func : trivial_compare_func; + s->hash_func = hash_func ? hash_func : idxset_trivial_hash_func; + s->compare_func = compare_func ? compare_func : idxset_trivial_compare_func; s->hash_table_size = 1023; s->hash_table = malloc(sizeof(struct idxset_entry*)*s->hash_table_size); assert(s->hash_table); diff --git a/src/idxset.h b/src/idxset.h index 90b9d247..61503977 100644 --- a/src/idxset.h +++ b/src/idxset.h @@ -5,9 +5,15 @@ #define IDXSET_INVALID ((uint32_t) -1) +unsigned idxset_trivial_hash_func(const void *p); +int idxset_trivial_compare_func(const void *a, const void *b); + +unsigned idxset_string_hash_func(const void *p); +int idxset_string_compare_func(const void *a, const void *b); + struct idxset; -struct idxset* idxset_new(unsigned (*hash_func) (void *p), int (*compare_func) (void*a, void*b)); +struct idxset* idxset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)); void idxset_free(struct idxset *s, void (*free_func) (void *p, void *userdata), void *userdata); int idxset_put(struct idxset*s, void *p, uint32_t *index); diff --git a/src/module-oss-mmap.c b/src/module-oss-mmap.c index f08dd7d3..3997c490 100644 --- a/src/module-oss-mmap.c +++ b/src/module-oss-mmap.c @@ -262,7 +262,7 @@ int module_init(struct core *c, struct module*m) { } } else { - u->source = source_new(c, "dsp", &u->sample_spec); + u->source = source_new(c, "dsp", 0, &u->sample_spec); assert(u->source); u->source->userdata = u; @@ -293,7 +293,7 @@ int module_init(struct core *c, struct module*m) { } else { silence_memory(u->out_mmap, u->out_mmap_length, &u->sample_spec); - u->sink = sink_new(c, "dsp", &u->sample_spec); + u->sink = sink_new(c, "dsp", 0, &u->sample_spec); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; u->sink->userdata = u; diff --git a/src/module-oss.c b/src/module-oss.c index b5d1427a..75082a7f 100644 --- a/src/module-oss.c +++ b/src/module-oss.c @@ -180,7 +180,7 @@ int module_init(struct core *c, struct module*m) { u->core = c; if (mode != O_RDONLY) { - u->sink = sink_new(c, "dsp", &ss); + u->sink = sink_new(c, "dsp", 0, &ss); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; u->sink->userdata = u; @@ -188,7 +188,7 @@ int module_init(struct core *c, struct module*m) { u->sink = NULL; if (mode != O_WRONLY) { - u->source = source_new(c, "dsp", &ss); + u->source = source_new(c, "dsp", 0, &ss); assert(u->source); u->source->userdata = u; } else diff --git a/src/module-pipe-sink.c b/src/module-pipe-sink.c index 9dcf5d23..6cc4de88 100644 --- a/src/module-pipe-sink.c +++ b/src/module-pipe-sink.c @@ -109,7 +109,7 @@ int module_init(struct core *c, struct module*m) { u->filename = strdup(p); assert(u->filename); u->core = c; - u->sink = sink_new(c, "fifo", &ss); + u->sink = sink_new(c, "fifo", 0, &ss); assert(u->sink); u->sink->notify = notify_cb; u->sink->userdata = u; diff --git a/src/namereg.c b/src/namereg.c new file mode 100644 index 00000000..b286171d --- /dev/null +++ b/src/namereg.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include + +#include "namereg.h" + +struct namereg_entry { + enum namereg_type type; + char *name; + void *data; +}; + +void namereg_free(struct core *c) { + assert(c); + if (!c->namereg) + return; + assert(hashset_ncontents(c->namereg) == 0); + hashset_free(c->namereg, NULL, NULL); +} + +const char *namereg_register(struct core *c, const char *name, enum namereg_type type, void *data, int fail) { + struct namereg_entry *e; + char *n = NULL; + int r; + + assert(c && name && data); + + if (!c->namereg) { + c->namereg = hashset_new(idxset_string_hash_func, idxset_string_compare_func); + assert(c->namereg); + } + + if ((e = hashset_get(c->namereg, name)) && fail) + return NULL; + + if (!e) + n = strdup(name); + else { + unsigned i; + size_t l = strlen(name); + n = malloc(l+3); + assert(n); + + for (i = 1; i <= 99; i++) { + snprintf(n, l+2, "%s%u", name, i); + + if (!(e = hashset_get(c->namereg, n))) + break; + } + + if (e) { + free(n); + return NULL; + } + } + + assert(n); + e = malloc(sizeof(struct namereg_entry)); + assert(e); + e->type = type; + e->name = n; + e->data = data; + + r = hashset_put(c->namereg, e->name, e); + assert (r >= 0); + + return e->name; + +} + +void namereg_unregister(struct core *c, const char *name) { + struct namereg_entry *e; + int r; + assert(c && name); + + e = hashset_get(c->namereg, name); + assert(e); + + r = hashset_remove(c->namereg, name); + assert(r >= 0); + + free(e->name); + free(e); +} + +void* namereg_get(struct core *c, const char *name, enum namereg_type type) { + struct namereg_entry *e; + assert(c && name); + + if (!(e = hashset_get(c->namereg, name))) + if (e->type == e->type) + return e->data; + + return NULL; +} diff --git a/src/namereg.h b/src/namereg.h new file mode 100644 index 00000000..5632143b --- /dev/null +++ b/src/namereg.h @@ -0,0 +1,17 @@ +#ifndef foonamereghfoo +#define foonamereghfoo + +#include "core.h" + +enum namereg_type { + NAMEREG_SINK, + NAMEREG_SOURCE +}; + +void namereg_free(struct core *c); + +const char *namereg_register(struct core *c, const char *name, enum namereg_type type, void *data, int fail); +void namereg_unregister(struct core *c, const char *name); +void* namereg_get(struct core *c, const char *name, enum namereg_type type); + +#endif diff --git a/src/sink.c b/src/sink.c index a334424c..5ab1a7a7 100644 --- a/src/sink.c +++ b/src/sink.c @@ -7,10 +7,11 @@ #include "sinkinput.h" #include "strbuf.h" #include "sample-util.h" +#include "namereg.h" #define MAX_MIX_CHANNELS 32 -struct sink* sink_new(struct core *core, const char *name, const struct pa_sample_spec *spec) { +struct sink* sink_new(struct core *core, const char *name, int fail, const struct pa_sample_spec *spec) { struct sink *s; char *n = NULL; int r; @@ -18,8 +19,13 @@ struct sink* sink_new(struct core *core, const char *name, const struct pa_sampl s = malloc(sizeof(struct sink)); assert(s); + + if (!(name = namereg_register(core, name, NAMEREG_SINK, s, fail))) { + free(s); + return NULL; + } - s->name = name ? strdup(name) : NULL; + s->name = strdup(name); s->core = core; s->sample_spec = *spec; s->inputs = idxset_new(NULL, NULL); @@ -29,7 +35,8 @@ struct sink* sink_new(struct core *core, const char *name, const struct pa_sampl sprintf(n, "%s_monitor", name); } - s->monitor_source = source_new(core, n, spec); + s->monitor_source = source_new(core, n, 0, spec); + assert(s->monitor_source); free(n); s->volume = 0xFF; @@ -50,6 +57,8 @@ void sink_free(struct sink *s) { struct sink_input *i, *j = NULL; assert(s); + namereg_unregister(s->core, s->name); + while ((i = idxset_first(s->inputs, NULL))) { assert(i != j); sink_input_kill(i); diff --git a/src/sink.h b/src/sink.h index d9f80059..a5b1ff68 100644 --- a/src/sink.h +++ b/src/sink.h @@ -27,7 +27,7 @@ struct sink { void *userdata; }; -struct sink* sink_new(struct core *core, const char *name, const struct pa_sample_spec *spec); +struct sink* sink_new(struct core *core, const char *name, int fail, const struct pa_sample_spec *spec); void sink_free(struct sink* s); int sink_render(struct sink*s, size_t length, struct memchunk *result); diff --git a/src/source.c b/src/source.c index 21ac24f3..deacfb3d 100644 --- a/src/source.c +++ b/src/source.c @@ -6,8 +6,9 @@ #include "source.h" #include "sourceoutput.h" #include "strbuf.h" +#include "namereg.h" -struct source* source_new(struct core *core, const char *name, const struct pa_sample_spec *spec) { +struct source* source_new(struct core *core, const char *name, int fail, const struct pa_sample_spec *spec) { struct source *s; int r; assert(core && spec); @@ -15,7 +16,12 @@ struct source* source_new(struct core *core, const char *name, const struct pa_s s = malloc(sizeof(struct source)); assert(s); - s->name = name ? strdup(name) : NULL; + if (!(name = namereg_register(core, name, NAMEREG_SOURCE, s, fail))) { + free(s); + return NULL; + } + + s->name = strdup(name); s->core = core; s->sample_spec = *spec; s->outputs = idxset_new(NULL, NULL); @@ -35,6 +41,8 @@ void source_free(struct source *s) { struct source_output *o, *j = NULL; assert(s); + namereg_unregister(s->core, s->name); + while ((o = idxset_first(s->outputs, NULL))) { assert(o != j); source_output_kill(o); diff --git a/src/source.h b/src/source.h index 04f3984f..afae5a68 100644 --- a/src/source.h +++ b/src/source.h @@ -21,7 +21,7 @@ struct source { void *userdata; }; -struct source* source_new(struct core *core, const char *name, const struct pa_sample_spec *spec); +struct source* source_new(struct core *core, const char *name, int fail, const struct pa_sample_spec *spec); void source_free(struct source *s); /* Pass a new memory block to all output streams */ diff --git a/src/todo b/src/todo index 47344ab4..78768be0 100644 --- a/src/todo +++ b/src/todo @@ -1,13 +1,19 @@ -- sync() function in native library -- name registrar -- native protocol/library -- simple control protocol: kill client/input/output; set_volume +- native library/protocol: + recording + sync() function + more functions +- simple library +- simple control protocol: + kill client/input/output + set_volume - resampling +- volume adjust on single sink input +- fp volume scaling (both < and > 1) - esound protocol - config parser/cmdline - record testing + -- 0.1 -- optimierung von rebuild_pollfds() - future cancellation - client-ui - clip cache -- cgit