diff options
-rw-r--r-- | polyp/autoload.c | 74 | ||||
-rw-r--r-- | polyp/autoload.h | 17 | ||||
-rw-r--r-- | polyp/play-memchunk.c | 76 | ||||
-rw-r--r-- | polyp/play-memchunk.h | 8 | ||||
-rw-r--r-- | polyp/sound-file.c | 64 | ||||
-rw-r--r-- | polyp/sound-file.h | 9 | ||||
-rw-r--r-- | polyp/xmalloc.c | 76 | ||||
-rw-r--r-- | polyp/xmalloc.h | 14 |
8 files changed, 338 insertions, 0 deletions
diff --git a/polyp/autoload.c b/polyp/autoload.c new file mode 100644 index 00000000..f0d70d2d --- /dev/null +++ b/polyp/autoload.c @@ -0,0 +1,74 @@ +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +#include "autoload.h" +#include "module.h" +#include "xmalloc.h" + +static void entry_free(struct pa_autoload_entry *e) { + assert(e); + pa_xfree(e->name); + pa_xfree(e->module); + pa_xfree(e->argument); + pa_xfree(e); +} + +void pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument) { + struct pa_autoload_entry *e = NULL; + assert(c && name && module); + + if (c->autoload_hashmap && (e = pa_hashmap_get(c->autoload_hashmap, name))) { + pa_xfree(e->module); + pa_xfree(e->argument); + } else { + e = pa_xmalloc(sizeof(struct pa_autoload_entry)); + e->name = pa_xstrdup(name); + + if (!c->autoload_hashmap) + c->autoload_hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + assert(c->autoload_hashmap); + + pa_hashmap_put(c->autoload_hashmap, e->name, e); + } + + e->module = pa_xstrdup(module); + e->argument = pa_xstrdup(argument); + e->type = type; +} + +int pa_autoload_remove(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))) + return -1; + + pa_hashmap_remove(c->autoload_hashmap, e->name); + entry_free(e); + return 0; +} + +void pa_autoload_request(struct pa_core *c, const char *name, enum pa_namereg_type type) { + struct pa_autoload_entry *e; + struct pa_module *m; + assert(c && name); + + if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || (e->type != type)) + return; + + if ((m = pa_module_load(c, e->module, e->argument))) + m->auto_unload = 1; +} + +static void free_func(void *p, void *userdata) { + struct pa_autoload_entry *e = p; + 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); +} diff --git a/polyp/autoload.h b/polyp/autoload.h new file mode 100644 index 00000000..f1862e77 --- /dev/null +++ b/polyp/autoload.h @@ -0,0 +1,17 @@ +#ifndef fooautoloadhfoo +#define fooautoloadhfoo + +#include "namereg.h" + +struct pa_autoload_entry { + char *name; + enum pa_namereg_type type; + char *module, *argument; +}; + +void pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument); +void pa_autoload_free(struct pa_core *c); +int pa_autoload_remove(struct pa_core *c, const char*name, enum pa_namereg_type type); +void pa_autoload_request(struct pa_core *c, const char *name, enum pa_namereg_type type); + +#endif diff --git a/polyp/play-memchunk.c b/polyp/play-memchunk.c new file mode 100644 index 00000000..5c448a75 --- /dev/null +++ b/polyp/play-memchunk.c @@ -0,0 +1,76 @@ +#include <stdlib.h> +#include <assert.h> + +#include "play-memchunk.h" +#include "sink-input.h" +#include "xmalloc.h" + +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); + pa_xfree(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; + + if (c->length <= 0) + return -1; + + assert(c->memblock && c->memblock->length); + *chunk = *c; + pa_memblock_ref(c->memblock); + + return 0; +} + +static void si_kill(void *i) { + sink_input_kill(i); +} + +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) + pa_mainloop_api_once(i->sink->core->mainloop, si_kill, i); +} + +int pa_play_memchunk(struct pa_sink *sink, const char *name, const struct pa_sample_spec *ss, const struct pa_memchunk *chunk, uint32_t volume) { + struct pa_sink_input *si; + struct pa_memchunk *nchunk; + + assert(sink && chunk); + + if (volume <= 0) + return 0; + + if (!(si = pa_sink_input_new(sink, name, ss))) + return -1; + + si->volume = volume; + si->peek = sink_input_peek; + si->drop = sink_input_drop; + si->kill = sink_input_kill; + + si->userdata = nchunk = pa_xmalloc(sizeof(struct pa_memchunk)); + *nchunk = *chunk; + + pa_memblock_ref(chunk->memblock); + + pa_sink_notify(sink); + + return 0; +} diff --git a/polyp/play-memchunk.h b/polyp/play-memchunk.h new file mode 100644 index 00000000..76f9dbd0 --- /dev/null +++ b/polyp/play-memchunk.h @@ -0,0 +1,8 @@ +#ifndef fooplaychunkhfoo +#define fooplaychunkhfoo + +#include "sink.h" + +int pa_play_memchunk(struct pa_sink *sink, const char *name, const struct pa_sample_spec *ss, const struct pa_memchunk *chunk, uint32_t volume); + +#endif diff --git a/polyp/sound-file.c b/polyp/sound-file.c new file mode 100644 index 00000000..b0df7185 --- /dev/null +++ b/polyp/sound-file.c @@ -0,0 +1,64 @@ +#include <string.h> +#include <assert.h> + +#include <sndfile.h> + +#include "sound-file.h" +#include "sample.h" + +#define MAX_FILE_SIZE (1024*1024) + +int pa_sound_file_load(const char *fname, struct pa_sample_spec *ss, struct pa_memchunk *chunk) { + SNDFILE*sf = NULL; + SF_INFO sfinfo; + int ret = -1; + size_t l; + assert(fname && ss && chunk); + + memset(&sfinfo, 0, sizeof(sfinfo)); + + chunk->memblock = NULL; + chunk->index = chunk->length = 0; + + if (!(sf = sf_open(fname, SFM_READ, &sfinfo))) { + fprintf(stderr, __FILE__": Failed to open file %s\n", fname); + goto finish; + } + + ss->format = PA_SAMPLE_FLOAT32; + ss->rate = sfinfo.samplerate; + ss->channels = sfinfo.channels; + + if (!pa_sample_spec_valid(ss)) { + fprintf(stderr, __FILE__": Unsupported sample format in file %s\n", fname); + goto finish; + } + + if ((l = pa_frame_size(ss)*sfinfo.frames) > MAX_FILE_SIZE) { + fprintf(stderr, __FILE__": File to large\n"); + goto finish; + } + + chunk->memblock = pa_memblock_new(l); + assert(chunk->memblock); + chunk->index = 0; + chunk->length = l; + + if (sf_readf_float(sf, chunk->memblock->data, sfinfo.frames) != sfinfo.frames) { + fprintf(stderr, __FILE__": Premature file end\n"); + goto finish; + } + + ret = 0; + +finish: + + if (sf) + sf_close(sf); + + if (ret != 0 && chunk->memblock) + pa_memblock_unref(chunk->memblock); + + return ret; + +} diff --git a/polyp/sound-file.h b/polyp/sound-file.h new file mode 100644 index 00000000..3a6fa415 --- /dev/null +++ b/polyp/sound-file.h @@ -0,0 +1,9 @@ +#ifndef soundfilehfoo +#define soundfilehfoo + +#include "memchunk.h" +#include "sample.h" + +int pa_sound_file_load(const char *fname, struct pa_sample_spec *ss, struct pa_memchunk *chunk); + +#endif diff --git a/polyp/xmalloc.c b/polyp/xmalloc.c new file mode 100644 index 00000000..8ff3054d --- /dev/null +++ b/polyp/xmalloc.c @@ -0,0 +1,76 @@ +#include <stdlib.h> +#include <signal.h> +#include <assert.h> + +#include "memory.h" +#include "util.h" + +#define MAX_ALLOC_SIZE (1024*1024*20) + +#undef malloc +#undef free +#undef realloc +#undef strndup +#undef strdup + +static void oom(void) { + static const char e[] = "Not enough memory\n"; + pa_loop_write(2, e, sizeof(e)-1); + raise(SIGQUIT); + exit(1); +} + +void* pa_xmalloc(size_t size) { + void *p; + assert(size > 0); + assert(size < MAX_ALLOC_SIZE); + + if (!(p = malloc(size))) + oom(); + + return p; +} + +void* pa_xmalloc0(size_t size) { + void *p; + assert(size > 0); + assert(size < MAX_ALLOC_SIZE); + + if (!(p = calloc(1, size))) + oom(); + + return p; +} + +void *pa_xrealloc(void *ptr, size_t size) { + void *p; + assert(size > 0); + assert(size < MAX_ALLOC_SIZE); + + if (!(p = realloc(ptr, size))) + oom(); + return p; +} + +char *pa_xstrdup(const char *s) { + if (!s) + return NULL; + else { + char *r = strdup(s); + if (!r) + oom(); + + return r; + } +} + +char *pa_xstrndup(const char *s, size_t l) { + if (!s) + return NULL; + else { + char *r = strndup(s, l); + if (!r) + oom(); + return r; + } +} diff --git a/polyp/xmalloc.h b/polyp/xmalloc.h new file mode 100644 index 00000000..5f58a8ad --- /dev/null +++ b/polyp/xmalloc.h @@ -0,0 +1,14 @@ +#ifndef foomemoryhfoo +#define foomemoryhfoo + +#include <sys/types.h> + +void* pa_xmalloc(size_t l); +void *pa_xmalloc0(size_t l); +void *pa_xrealloc(void *ptr, size_t size); +#define pa_xfree free + +char *pa_xstrdup(const char *s); +char *pa_xstrndup(const char *s, size_t l); + +#endif |