summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--polyp/autoload.c74
-rw-r--r--polyp/autoload.h17
-rw-r--r--polyp/play-memchunk.c76
-rw-r--r--polyp/play-memchunk.h8
-rw-r--r--polyp/sound-file.c64
-rw-r--r--polyp/sound-file.h9
-rw-r--r--polyp/xmalloc.c76
-rw-r--r--polyp/xmalloc.h14
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