diff options
author | Lennart Poettering <lennart@poettering.net> | 2004-07-20 01:07:06 +0000 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2004-07-20 01:07:06 +0000 |
commit | bb0b105b83c0f4ee56b4c7e9a179606aee296aa9 (patch) | |
tree | c7a83efa8830adee3b4c94a8e28d5c03c9573f20 /polyp/scache.c | |
parent | 527faf01d0605a6ced9a73017cc8155adba59d24 (diff) |
sample cache work
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@98 fefdeb5f-60dc-0310-8127-8f9354f1896f
Diffstat (limited to 'polyp/scache.c')
-rw-r--r-- | polyp/scache.c | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/polyp/scache.c b/polyp/scache.c new file mode 100644 index 00000000..d2a84827 --- /dev/null +++ b/polyp/scache.c @@ -0,0 +1,181 @@ +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +#include "scache.h" +#include "sink-input.h" + +static void free_entry(struct pa_scache_entry *e) { + assert(e); + free(e->name); + if (e->memchunk.memblock) + pa_memblock_unref(e->memchunk.memblock); + free(e); +} + +void pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index) { + struct pa_scache_entry *e; + int put; + assert(c && name); + + if (c->scache_hashmap && (e = pa_hashmap_get(c->scache_hashmap, name))) { + put = 0; + if (e->memchunk.memblock) + pa_memblock_unref(e->memchunk.memblock); + } else { + put = 1; + e = malloc(sizeof(struct pa_scache_entry)); + assert(e); + e->name = strdup(name); + assert(e->name); + } + + if (ss) + e->sample_spec = *ss; + else + memset(&e->sample_spec, 0, sizeof(struct pa_sample_spec)); + + if (chunk) { + e->memchunk = *chunk; + pa_memblock_ref(e->memchunk.memblock); + } else { + e->memchunk.memblock = NULL; + e->memchunk.index = e->memchunk.length = 0; + } + + if (put) { + if (!c->scache_hashmap) { + c->scache_hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + assert(c->scache_hashmap); + } + + if (!c->scache_idxset) { + c->scache_idxset = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + assert(c->scache_idxset); + } + + pa_idxset_put(c->scache_idxset, e, &e->index); + pa_hashmap_put(c->scache_hashmap, e->name, e); + } + + if (index) + *index = e->index; +} + +int pa_scache_remove_item(struct pa_core *c, const char *name) { + struct pa_scache_entry *e; + assert(c && name); + + if (!c->scache_hashmap || !(e = pa_hashmap_get(c->scache_hashmap, name))) + return -1; + + pa_hashmap_remove(c->scache_hashmap, name); + pa_idxset_remove_by_index(c->scache_idxset, e->index); + free_entry(e); + return 0; +} + +static void free_cb(void *p, void *userdata) { + struct pa_scache_entry *e = p; + assert(e); + free_entry(e); +} + +void pa_scache_free(struct pa_core *c) { + assert(c); + + if (c->scache_hashmap) { + pa_hashmap_free(c->scache_hashmap, free_cb, NULL); + c->scache_hashmap = NULL; + } + + if (c->scache_idxset) { + pa_idxset_free(c->scache_idxset, NULL, NULL); + c->scache_idxset = NULL; + } +} + +static void sink_input_kill(struct pa_sink_input *i) { + struct pa_memchunk *c; + assert(i && i->userdata); + c = i->userdata; + + pa_memblock_unref(c->memblock); + free(c); + pa_sink_input_free(i); +} + +static int sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { + struct pa_memchunk *c; + assert(i && chunk && i->userdata); + c = i->userdata; + + assert(c->length && c->memblock && c->memblock->length); + *chunk = *c; + pa_memblock_ref(c->memblock); + + return 0; +} + +static void sink_input_drop(struct pa_sink_input *i, size_t length) { + struct pa_memchunk *c; + assert(i && length && i->userdata); + c = i->userdata; + + assert(length <= c->length); + + c->length -= length; + c->index += length; + + if (c->length <= 0) + sink_input_kill(i); +} + +int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sink, uint32_t volume) { + struct pa_sink_input *si; + struct pa_scache_entry *e; + struct pa_memchunk *chunk; + assert(c && name && sink); + + if (!c->scache_hashmap || !(e = pa_hashmap_get(c->scache_hashmap, name))) + return -1; + + if (!e->memchunk.memblock) + return -1; + + if (!(si = pa_sink_input_new(sink, name, &e->sample_spec))) + return -1; + + si->volume = volume; + + si->peek = sink_input_peek; + si->drop = sink_input_drop; + si->kill = sink_input_kill; + si->userdata = chunk = malloc(sizeof(struct pa_memchunk)); + assert(chunk); + *chunk = e->memchunk; + pa_memblock_ref(chunk->memblock); + + return 0; +} + +const char * pa_scache_get_name_by_id(struct pa_core *c, uint32_t id) { + struct pa_scache_entry *e; + assert(c && id != PA_IDXSET_INVALID); + + if (!c->scache_idxset || !(e = pa_idxset_get_by_index(c->scache_idxset, id))) + return NULL; + + return e->name; + +} + +uint32_t pa_scache_get_id_by_name(struct pa_core *c, const char *name) { + struct pa_scache_entry *e; + assert(c && name); + + if (!c->scache_hashmap || !(e = pa_hashmap_get(c->scache_hashmap, name))) + return PA_IDXSET_INVALID; + + return e->index; +} |