summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2004-06-27 22:42:17 +0000
committerLennart Poettering <lennart@poettering.net>2004-06-27 22:42:17 +0000
commita74cd2a1bd92eac6a4140d0794ac4b557be6c133 (patch)
treefdb341d0c7fecdbafc8f42cdc612076ebb23e024 /src
parent010378643e89e2ca4ea3502cb7dc6d8e16480832 (diff)
add name registrar
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@39 fefdeb5f-60dc-0310-8127-8f9354f1896f
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am5
-rw-r--r--src/core.c4
-rw-r--r--src/core.h3
-rw-r--r--src/hashset.c145
-rw-r--r--src/hashset.h16
-rw-r--r--src/idxset.c28
-rw-r--r--src/idxset.h8
-rw-r--r--src/module-oss-mmap.c4
-rw-r--r--src/module-oss.c4
-rw-r--r--src/module-pipe-sink.c2
-rw-r--r--src/namereg.c97
-rw-r--r--src/namereg.h17
-rw-r--r--src/sink.c15
-rw-r--r--src/sink.h2
-rw-r--r--src/source.c12
-rw-r--r--src/source.h2
-rw-r--r--src/todo16
17 files changed, 354 insertions, 26 deletions
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 <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#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 <string.h>
+#include <assert.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdio.h>
+
+#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