diff options
author | Alfred E. Heggestad <aeh@db.org> | 2014-04-11 19:22:25 +0200 |
---|---|---|
committer | Alfred E. Heggestad <aeh@db.org> | 2014-04-11 19:22:25 +0200 |
commit | 272b15cbc366890ebaccd37fdf4ab27087b74064 (patch) | |
tree | dd07e8a1a1e3485752ea1709441c497389a47ea9 | |
parent | 5fc1c61109c1368fc781a287d6cfc0ef1abe1d35 (diff) | |
parent | bca1461f503407fc9c8f7a692ec75c968a0acf27 (diff) |
Merge branch 'master' into next
-rw-r--r-- | docs/README | 1 | ||||
-rw-r--r-- | modules/sndio/module.mk | 11 | ||||
-rw-r--r-- | modules/sndio/sndio.c | 307 |
3 files changed, 319 insertions, 0 deletions
diff --git a/docs/README b/docs/README index 2468bfd..f1efe03 100644 --- a/docs/README +++ b/docs/README @@ -187,6 +187,7 @@ selfview Video selfview module silk SILK audio codec snapshot Save video-stream as PNG images sndfile Audio dumper using libsndfile +sndio Audio driver for OpenBSD speex Speex audio codec speex_aec Acoustic Echo Cancellation (AEC) using libspeexdsp speex_pp Audio pre-processor using libspeexdsp diff --git a/modules/sndio/module.mk b/modules/sndio/module.mk new file mode 100644 index 0000000..79ace67 --- /dev/null +++ b/modules/sndio/module.mk @@ -0,0 +1,11 @@ +# +# module.mk +# +# Copyright (C) 2014 Creytiv.com +# + +MOD := sndio +$(MOD)_SRCS += sndio.c +$(MOD)_LFLAGS += -lsndio + +include mk/mod.mk diff --git a/modules/sndio/sndio.c b/modules/sndio/sndio.c new file mode 100644 index 0000000..ee0fd46 --- /dev/null +++ b/modules/sndio/sndio.c @@ -0,0 +1,307 @@ +/** + * @file sndio.c SndIO sound driver + * + * Copyright (C) 2014 Creytiv.com + */ +#include <stdlib.h> +#include <string.h> +#include <sndio.h> +#include <pthread.h> +#include <re.h> +#include <rem.h> +#include <baresip.h> + + +struct ausrc_st { + struct ausrc *as; + struct sio_hdl *hdl; + pthread_t thread; + size_t nbytes; + void *buf; + int run; + ausrc_read_h *rh; + void *arg; +}; + +struct auplay_st { + struct auplay *ap; + struct sio_hdl *hdl; + pthread_t thread; + size_t nbytes; + void *buf; + int run; + auplay_write_h *wh; + void *arg; +}; + +static struct ausrc *ausrc; +static struct auplay *auplay; + + +static struct sio_par *sndio_initpar(void *arg) +{ + struct sio_par *par; + struct auplay_prm *prm = arg; + + if ((par = malloc(sizeof(struct sio_par))) == NULL) + return NULL; + + sio_initpar(par); + + /* sndio doesn't support a-low and u-low */ + prm->fmt = AUFMT_S16LE; + par->bits = 16; + par->bps = SIO_BPS(par->bits); + par->sig = 1; + par->le = 1; + + par->rchan = prm->ch; + par->pchan = prm->ch; + par->rate = prm->srate; + + return par; +} + + +static void *read_thread(void *arg) +{ + struct ausrc_st *st = arg; + + if (!sio_start(st->hdl)) { + warning("sndio: could not start record\n"); + goto out; + } + + while (st->run) { + sio_read(st->hdl, st->buf, st->nbytes); + st->rh(st->buf, st->nbytes, st->arg); + } + + out: + return NULL; +} + + +static void *write_thread(void *arg) +{ + struct auplay_st *st = arg; + + if (!sio_start(st->hdl)) { + warning("sndio: could not start playback\n"); + goto out; + } + + while (st->run) { + st->wh(st->buf, st->nbytes, st->arg); + sio_write(st->hdl, st->buf, st->nbytes); + } + + out: + return NULL; +} + + +static void ausrc_destructor(void *arg) +{ + struct ausrc_st *st = arg; + + if (st->run) { + st->run = false; + (void)pthread_join(st->thread, NULL); + } + + sio_close(st->hdl); + + mem_deref(st->buf); + mem_deref(st->as); +} + + +static void auplay_destructor(void *arg) +{ + struct auplay_st *st = arg; + + if (st->run) { + st->run = false; + (void)pthread_join(st->thread, NULL); + } + + sio_close(st->hdl); + + mem_deref(st->buf); + mem_deref(st->ap); +} + + +static int src_alloc(struct ausrc_st **stp, struct ausrc *as, + struct media_ctx **ctx, + struct ausrc_prm *prm, const char *device, + ausrc_read_h *rh, ausrc_error_h *errh, void *arg) +{ + struct ausrc_st *st; + struct sio_par *par; + int err; + const char *name; + + (void)ctx; + (void)errh; + + if (!stp || !as || !prm) + return EINVAL; + + name = (str_isset(device)) ? device : SIO_DEVANY; + + if ((st = mem_zalloc(sizeof(*st), ausrc_destructor)) == NULL) + return ENOMEM; + + st->as = mem_ref(as); + st->rh = rh; + st->arg = arg; + st->hdl = sio_open(name, SIO_REC, 0); + + if (!st->hdl) { + warning("sndio: could not open ausrc device '%s'\n", name); + err = EINVAL; + goto out; + } + + par = sndio_initpar(prm); + if (!par) { + err = ENOMEM; + goto out; + } + + if (!sio_setpar(st->hdl, par)) { + free(par); + err = EINVAL; + goto out; + } + + if (!sio_getpar(st->hdl, par)) { + free(par); + err = EINVAL; + goto out; + } + + st->nbytes = 2 * par->appbufsz; + st->buf = mem_alloc(st->nbytes, NULL); + if (!st->buf) { + free(par); + err = ENOMEM; + goto out; + } + + free(par); + + st->run = true; + err = pthread_create(&st->thread, NULL, read_thread, st); + if (err) + st->run = false; + + out: + if (err) + mem_deref(st); + else + *stp = st; + + return err; +} + + +static int play_alloc(struct auplay_st **stp, struct auplay *ap, + struct auplay_prm *prm, const char *device, + auplay_write_h *wh, void *arg) +{ + struct auplay_st *st; + struct sio_par *par; + int err; + const char *name; + + if (!stp || !ap || !prm) + return EINVAL; + + name = (str_isset(device)) ? device : SIO_DEVANY; + + if ((st = mem_zalloc(sizeof(*st), auplay_destructor)) == NULL) + return ENOMEM; + + st->ap = mem_ref(ap); + st->wh = wh; + st->arg = arg; + st->hdl = sio_open(name, SIO_PLAY, 0); + + if (!st->hdl) { + warning("sndio: could not open auplay device '%s'\n", name); + err = EINVAL; + goto out; + } + + par = sndio_initpar(prm); + if (!par) { + err = ENOMEM; + goto out; + } + + if (!sio_setpar(st->hdl, par)) { + free(par); + err = EINVAL; + goto out; + } + + if (!sio_getpar(st->hdl, par)) { + free(par); + err = EINVAL; + goto out; + } + + st->nbytes = 2 * par->appbufsz; + st->buf = mem_alloc(st->nbytes, NULL); + if (!st->buf) { + free(par); + err = ENOMEM; + goto out; + } + + free(par); + + st->run = true; + err = pthread_create(&st->thread, NULL, write_thread, st); + if (err) + st->run = false; + + out: + if (err) + mem_deref(st); + else + *stp = st; + + return err; +} + + +static int sndio_init(void) +{ + int err = 0; + + err |= ausrc_register(&ausrc, "sndio", src_alloc); + err |= auplay_register(&auplay, "sndio", play_alloc); + + return err; +} + + +static int sndio_close(void) +{ + ausrc = mem_deref(ausrc); + auplay = mem_deref(auplay); + + return 0; +} + + +EXPORT_SYM const struct mod_export DECL_EXPORTS(sndio) = { + "sndio", + "sound", + sndio_init, + sndio_close +}; |