add name registrar

git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@39 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
Lennart Poettering 2004-06-27 22:42:17 +00:00
parent 010378643e
commit a74cd2a1bd
17 changed files with 354 additions and 26 deletions

View file

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

View file

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

View file

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

145
src/hashset.c Normal file
View file

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

16
src/hashset.h Normal file
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

97
src/namereg.c Normal file
View file

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

17
src/namereg.h Normal file
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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