From af6aa1c03bad837c366dcb603b6d922a07c52814 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 15 May 2016 21:03:38 +0100 Subject: OpenBSD compilable : - md5sum is not available. - adding sndio support from Jacob Meuser . - various patches from ajacoutot@, jasper@ and sthen@ --- drivers/sndio/Makefile.am | 13 + drivers/sndio/sndio_driver.c | 997 +++++++++++++++++++++++++++++++++++++++++++ drivers/sndio/sndio_driver.h | 74 ++++ 3 files changed, 1084 insertions(+) create mode 100644 drivers/sndio/Makefile.am create mode 100644 drivers/sndio/sndio_driver.c create mode 100644 drivers/sndio/sndio_driver.h (limited to 'drivers/sndio') diff --git a/drivers/sndio/Makefile.am b/drivers/sndio/Makefile.am new file mode 100644 index 0000000..1e22bef --- /dev/null +++ b/drivers/sndio/Makefile.am @@ -0,0 +1,13 @@ +MAINTAINCLEANFILES = Makefile.in + +AM_CFLAGS = $(JACK_CFLAGS) + +plugindir = $(ADDON_DIR) + +plugin_LTLIBRARIES = jack_sndio.la + +jack_sndio_la_LDFLAGS = -module -avoid-version +jack_sndio_la_LIBADD = $(SNDIO_LIBS) +jack_sndio_la_SOURCES = sndio_driver.c sndio_driver.h + +noinst_HEADERS = sndio_driver.h diff --git a/drivers/sndio/sndio_driver.c b/drivers/sndio/sndio_driver.c new file mode 100644 index 0000000..49ab79f --- /dev/null +++ b/drivers/sndio/sndio_driver.c @@ -0,0 +1,997 @@ +/* + * Copyright (c) 2009 Jacob Meuser + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#ifndef _REENTRANT +#define _REENTRANT +#endif +#ifndef _THREAD_SAFE +#define _THREAD_SAFE +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "sndio_driver.h" + + +#define SNDIO_DRIVER_N_PARAMS 10 +const static jack_driver_param_desc_t sndio_params[SNDIO_DRIVER_N_PARAMS] = { + { "rate", + 'r', + JackDriverParamUInt, + { .ui = SNDIO_DRIVER_DEF_FS }, + NULL, + "sample rate", + "sample rate" + }, + { "period", + 'p', + JackDriverParamUInt, + { .ui = SNDIO_DRIVER_DEF_BLKSIZE }, + NULL, + "period size", + "period size" + }, + { "nperiods", + 'n', + JackDriverParamUInt, + { .ui = SNDIO_DRIVER_DEF_NPERIODS }, + NULL, + "number of periods in buffer", + "number of periods in buffer" + }, + { "wordlength", + 'w', + JackDriverParamInt, + { .i = SNDIO_DRIVER_DEF_BITS }, + NULL, + "word length", + "word length" + }, + { "inchannels", + 'i', + JackDriverParamUInt, + { .ui = SNDIO_DRIVER_DEF_INS }, + NULL, + "capture channels", + "capture channels" + }, + { "outchannels", + 'o', + JackDriverParamUInt, + { .ui = SNDIO_DRIVER_DEF_OUTS }, + NULL, + "playback channels", + "playback channels" + }, + { "device", + 'd', + JackDriverParamString, + { }, + NULL, + "device", + "device" + }, + { "ignorehwbuf", + 'b', + JackDriverParamBool, + { }, + NULL, + "ignore hardware period size", + "ignore hardware period size" + }, + { "input latency", + 'I', + JackDriverParamUInt, + { .ui = 0 }, + NULL, + "system capture latency", + "system capture latency" + }, + { "output latency", + 'O', + JackDriverParamUInt, + { .ui = 0 }, + NULL, + "system playback latency", + "system playback latency" + } +}; + + +/* internal functions */ + + +static void +set_period_size (sndio_driver_t *driver, jack_nframes_t new_period_size) +{ + driver->period_size = new_period_size; + + driver->period_usecs = + ((double)driver->period_size / + (double)driver->sample_rate) * 1e6; + driver->last_wait_ust = 0; + driver->poll_timeout = (int)(driver->period_usecs / 666); +} + + +static void +sndio_driver_write_silence (sndio_driver_t *driver, jack_nframes_t nframes) +{ + size_t localsize, io_res, nbytes, offset; + void *localbuf; + + localsize = nframes * driver->sample_bytes * driver->playback_channels; + localbuf = malloc(localsize); + if (localbuf == NULL) + { + jack_error("sndio_driver: malloc() failed: %s@%i", + __FILE__, __LINE__); + return; + } + memset(localbuf, 0, localsize); + + offset = 0; + nbytes = localsize; + while (nbytes > 0) + { + io_res = sio_write(driver->hdl, localbuf + offset, nbytes); + if (io_res == 0) + { + jack_error("sndio_driver: sio_write() failed: " + "count=%d/%d: %s@%i", io_res, localsize, + __FILE__, __LINE__); + } + offset += io_res; + nbytes -= io_res; + } + free(localbuf); +} + + +static void +sndio_driver_read_silence (sndio_driver_t *driver, jack_nframes_t nframes) +{ + size_t localsize, io_res, nbytes, offset; + void *localbuf; + + localsize = nframes * driver->sample_bytes * driver->capture_channels; + localbuf = malloc(localsize); + if (localbuf == NULL) + { + jack_error("sndio_driver: malloc() failed: %s@%i", + __FILE__, __LINE__); + return; + } + + offset = 0; + nbytes = localsize; + while (nbytes > 0) { + io_res = sio_read(driver->hdl, localbuf + offset, nbytes); + if (io_res == 0) { + jack_error("sndio_driver: sio_read() failed: " + "count=%d/%d: %s@%i", io_res, nbytes, + __FILE__, __LINE__); + break; + } + offset +=- io_res; + nbytes -= io_res; + } + free(localbuf); +} + + +static int +sndio_driver_start (sndio_driver_t *driver) +{ + if (!sio_start(driver->hdl)) + jack_error("sio_start failed: %s@%i", + __FILE__, __LINE__); + + /* prime playback buffers */ + if (driver->playback_channels > 0) + sndio_driver_write_silence(driver, driver->pprime); + + return 0; +} + + +static int +sndio_driver_set_parameters (sndio_driver_t *driver) +{ + struct sio_par par; + unsigned int period_size = 0; + unsigned int nperiods; + int mode = 0; + + if (driver->capture_channels > 0) + mode |= SIO_REC; + + if (driver->playback_channels > 0) + mode |= SIO_PLAY; + + driver->hdl = sio_open(driver->dev, mode, 0); + if (driver->hdl == NULL) + { + jack_error("sndio_driver: failed to open device " + "%s: %s@%i", (driver->dev == NULL) ? + "default" : driver->dev, __FILE__, __LINE__); + return -1; + } + + if (driver->bits != 16 && driver->bits != 24 && driver->bits != 32) + { + jack_error("sndio_driver: invalid sample bits"); + return -1; + } + + sio_initpar(&par); + par.sig = 1; + par.bits = driver->bits; + par.pchan = driver->playback_channels; + par.rchan = driver->capture_channels; + par.rate = driver->sample_rate; + par.appbufsz = driver->period_size * driver->nperiods; + par.round = driver->period_size; + par.xrun = SIO_SYNC; + + if (!sio_setpar(driver->hdl, &par)) + { + jack_error("sndio_driver: failed to set parameters: %s@%i", + __FILE__, __LINE__); + return -1; + } + + if (!sio_getpar(driver->hdl, &par)) + { + jack_error("sndio_driver: sio_getpar() failed: %s@%i", + __FILE__, __LINE__); + return -1; + } + + if (par.sig != 1 || par.bits != driver->bits || + par.pchan != driver->playback_channels || + par.rchan != driver->capture_channels || + par.rate != driver->sample_rate) + { + jack_error("sndio_driver: setting parameters failed: %s@%i", + __FILE__, __LINE__); + return -1; + } + + period_size = par.round; + nperiods = par.appbufsz / par.round; + driver->sample_bytes = par.bps; + driver->pprime = par.bufsz; + + if (period_size != 0 && !driver->ignorehwbuf && + (period_size != driver->period_size || + nperiods != driver->nperiods)) + { + printf("sndio_driver: buffer update: " + "period_size=%u, nperiods=%u\n", period_size, nperiods); + + driver->nperiods = nperiods; + set_period_size(driver, period_size); + + if (driver->engine) + driver->engine->set_buffer_size(driver->engine, + driver->period_size); + } + + driver->capbufsize = 0; + driver->capbuf = NULL; + if (driver->capture_channels != 0) + { + driver->capbufsize = driver->period_size * + driver->capture_channels * driver->sample_bytes; + driver->capbuf = malloc(driver->capbufsize); + if (driver->capbuf == NULL) + { + jack_error("sndio_driver: malloc() failed: %s@%i", + __FILE__, __LINE__); + return -1; + } + memset(driver->capbuf, 0, driver->capbufsize); + } + + driver->playbufsize = 0; + driver->playbuf = NULL; + if (driver->playback_channels > 0) + { + driver->playbufsize = driver->period_size * + driver->playback_channels * driver->sample_bytes; + driver->playbuf = malloc(driver->playbufsize); + if (driver->playbuf == NULL) + { + jack_error("sndio_driver: malloc() failed: %s@%i", + __FILE__, __LINE__); + return -1; + } + memset(driver->playbuf, 0, driver->playbufsize); + } + + printf("sndio_driver: capbuf %zd B, playbuf %zd B\n", + driver->capbufsize, driver->playbufsize); + + return 0; +} + + +static int +sndio_driver_stop (sndio_driver_t *driver) +{ + if (driver->hdl != NULL) + sio_stop(driver->hdl); + + return 0; +} + + +static jack_nframes_t +sndio_driver_wait (sndio_driver_t *driver, int *status, float *iodelay) +{ + struct pollfd pfd; + nfds_t snfds, nfds; + jack_time_t poll_ret; + int need_capture, need_playback; + int events, revents; + + *status = 0; + *iodelay = 0; + + need_capture = need_playback = 0; + + if (driver->capture_channels > 0) + need_capture = 1; + + if (driver->playback_channels > 0) + need_playback = 1; + + if (jack_get_microseconds() > driver->poll_next) + { + /* late. don't count as wakeup delay. */ + driver->poll_next = 0; + } + + snfds = sio_nfds(driver->hdl); + + while (need_capture || need_playback) + { + events = 0; + if (need_capture) + events |= POLLIN; + + if (need_playback) + events |= POLLOUT; + + if (snfds != sio_pollfd(driver->hdl, &pfd, events)) { + jack_error("sndio_driver: sio_pollfd failed: %s@%i", + __FILE__, __LINE__); + *status = -1; + return 0; + } + nfds = poll(&pfd, snfds, 1000); + if (nfds == -1) + { + jack_error("sndio_driver: poll() error: %s: %s@%i", + strerror(errno), __FILE__, __LINE__); + *status = -1; + return 0; + } + else if (nfds == 0) + { + jack_error("sndio_driver: poll() time out: %s@%i", + __FILE__, __LINE__); + *status = -1; + return 0; + } + revents = sio_revents(driver->hdl, &pfd); + if (revents & (POLLERR | POLLHUP | POLLNVAL)) + { + jack_error("sndio_driver: poll() error: %s@%i", + __FILE__, __LINE__); + *status = -1; + return 0; + } + + if (revents & POLLIN) + need_capture = 0; + + if (revents & POLLOUT) + need_playback = 0; + + if (sio_eof(driver->hdl)) + { + jack_error("sndio_driver: sio_eof(): %s@%i", + __FILE__, __LINE__); + *status = -1; + return 0; + } + } + poll_ret = jack_get_microseconds(); + + if (driver->poll_next && poll_ret > driver->poll_next) + *iodelay = poll_ret - driver->poll_next; + + driver->poll_next = poll_ret + driver->period_usecs; + driver->engine->transport_cycle_start(driver->engine, poll_ret); + + driver->last_wait_ust = poll_ret; + + return driver->period_size; +} + + +static inline int +sndio_driver_run_cycle (sndio_driver_t *driver) +{ + jack_nframes_t nframes; + int wait_status; + float iodelay; + + nframes = sndio_driver_wait(driver, &wait_status, &iodelay); + + if (wait_status < 0) + return -1; + + return driver->engine->run_cycle(driver->engine, nframes, iodelay); +} + + +static void +copy_and_convert_in (jack_sample_t *dst, void *src, + size_t nframes, int channel, int chcount, int bits) +{ + int srcidx, dstidx; + signed short *s16src = (signed short *)src; + signed int *s32src = (signed int *)src; + jack_sample_t scale; + + srcidx = channel; + switch (bits) + { + case 16: + scale = 1.0f / 0x7fff; + for (dstidx = 0; dstidx < nframes; dstidx++) + { + dst[dstidx] = (jack_sample_t) + s16src[srcidx] * scale; + srcidx += chcount; + } + break; + case 24: + case 32: + scale = 1.0f / 0x7fffffff; + for (dstidx = 0; dstidx < nframes; dstidx++) + { + dst[dstidx] = (jack_sample_t) + s32src[srcidx] * scale; + srcidx += chcount; + } + break; + } +} + + +static void +copy_and_convert_out (void *dst, jack_sample_t *src, + size_t nframes, int channel, int chcount, int bits) +{ + int srcidx; + int dstidx; + signed short *s16dst = (signed short *)dst; + signed int *s32dst = (signed int *)dst; + jack_sample_t scale; + + dstidx = channel; + switch (bits) + { + case 16: + scale = 0x7fff; + for (srcidx = 0; srcidx < nframes; srcidx++) + { + s16dst[dstidx] = (signed short) + (src[srcidx] >= 0.0f) ? + (src[srcidx] * scale + 0.5f) : + (src[srcidx] * scale - 0.5f); + dstidx += chcount; + } + break; + case 24: + case 32: + scale = 0x7fffffff; + for (srcidx = 0; srcidx < nframes; srcidx++) + { + s32dst[dstidx] = (signed int) + (src[srcidx] >= 0.0f) ? + (src[srcidx] * scale + 0.5f) : + (src[srcidx] * scale - 0.5f); + dstidx += chcount; + } + break; + } +} + + +/* jack driver interface */ + +static int +sndio_driver_attach (sndio_driver_t *driver) +{ + int port_flags; + int channel; + char channel_name[64]; + jack_port_t *port; + jack_latency_range_t range; + + driver->engine->set_buffer_size(driver->engine, driver->period_size); + driver->engine->set_sample_rate(driver->engine, driver->sample_rate); + + port_flags = JackPortIsOutput|JackPortIsPhysical|JackPortIsTerminal; + + for (channel = 0; channel < driver->capture_channels; channel++) + { + snprintf(channel_name, sizeof(channel_name), + "capture_%u", channel + 1); + port = jack_port_register(driver->client, channel_name, + JACK_DEFAULT_AUDIO_TYPE, port_flags, 0); + if (port == NULL) + { + jack_error("sndio_driver: cannot register port for %s: " + "%s@%i", channel_name, __FILE__, __LINE__); + break; + } + range.min = range.max = driver->period_size + + driver->sys_cap_latency; + jack_port_set_latency_range(port, JackCaptureLatency, &range); + driver->capture_ports = + jack_slist_append(driver->capture_ports, port); + } + + port_flags = JackPortIsInput|JackPortIsPhysical|JackPortIsTerminal; + for (channel = 0; channel < driver->playback_channels; channel++) + { + snprintf(channel_name, sizeof(channel_name), + "playback_%u", channel + 1); + port = jack_port_register(driver->client, channel_name, + JACK_DEFAULT_AUDIO_TYPE, port_flags, 0); + if (port == NULL) + { + jack_error("sndio_driver: cannot register port for " + "%s: %s@%i", channel_name, __FILE__, __LINE__); + break; + } + range.min = range.max = driver->period_size + + driver->sys_play_latency; + jack_port_set_latency_range(port, JackPlaybackLatency, &range); + driver->playback_ports = + jack_slist_append(driver->playback_ports, port); + } + + return jack_activate(driver->client); +} + + +static int +sndio_driver_detach (sndio_driver_t *driver) +{ + JSList *node; + + if (driver->engine == NULL) + return 0; + + node = driver->capture_ports; + while (node != NULL) + { + jack_port_unregister(driver->client, + ((jack_port_t *) node->data)); + node = jack_slist_next(node); + } + if (driver->capture_ports != NULL) + { + jack_slist_free(driver->capture_ports); + driver->capture_ports = NULL; + } + + node = driver->playback_ports; + while (node != NULL) + { + jack_port_unregister(driver->client, + ((jack_port_t *) node->data)); + node = jack_slist_next(node); + } + if (driver->playback_ports != NULL) + { + jack_slist_free(driver->playback_ports); + driver->playback_ports = NULL; + } + + return 0; +} + + +static int +sndio_driver_read (sndio_driver_t *driver, jack_nframes_t nframes) +{ + jack_nframes_t nbytes, offset; + int channel; + size_t io_res; + jack_sample_t *portbuf; + JSList *node; + jack_port_t *port; + + if (driver->engine->freewheeling || driver->capture_channels == 0) + return 0; + + if (nframes > driver->period_size) + { + jack_error("sndio_driver: read failed: nframes > period_size: " + "(%u/%u): %s@%i", nframes, driver->period_size, + __FILE__, __LINE__); + return -1; + } + + node = driver->capture_ports; + channel = 0; + while (node != NULL) + { + port = (jack_port_t *)node->data; + + if (jack_port_connected(port)) + { + portbuf = jack_port_get_buffer(port, nframes); + copy_and_convert_in(portbuf, driver->capbuf, + nframes, channel, + driver->capture_channels, + driver->bits); + } + + node = jack_slist_next(node); + channel++; + } + + io_res = offset = 0; + nbytes = nframes * driver->capture_channels * driver->sample_bytes; + while (nbytes > 0) + { + io_res = sio_read(driver->hdl, driver->capbuf + offset, nbytes); + if (io_res == 0) + { + jack_error("sndio_driver: sio_read() failed: %s@%i", + __FILE__, __LINE__); + break; + } + offset += io_res; + nbytes -= io_res; + } + return 0; +} + + +static int +sndio_driver_write (sndio_driver_t *driver, jack_nframes_t nframes) +{ + jack_nframes_t nbytes; + int channel; + size_t io_res, offset; + jack_sample_t *portbuf; + JSList *node; + jack_port_t *port; + + if (driver->engine->freewheeling || driver->playback_channels == 0) + return 0; + + if (nframes > driver->period_size) + { + jack_error("sndio_driver: write failed: nframes > period_size " + "(%u/%u): %s@%i", nframes, driver->period_size, + __FILE__, __LINE__); + return -1; + } + + node = driver->playback_ports; + channel = 0; + while (node != NULL) + { + port = (jack_port_t *)node->data; + + if (jack_port_connected(port)) + { + portbuf = jack_port_get_buffer(port, nframes); + copy_and_convert_out(driver->playbuf, portbuf, + nframes, channel, + driver->playback_channels, + driver->bits); + } + + node = jack_slist_next(node); + channel++; + } + + io_res = offset = 0; + nbytes = nframes * driver->playback_channels * driver->sample_bytes; + while (nbytes > 0) + { + io_res = sio_write(driver->hdl, driver->playbuf + offset, nbytes); + if (io_res == 0) + { + jack_error("sndio_driver: sio_write() failed: %s@%i", + __FILE__, __LINE__); + break; + } + offset += io_res; + nbytes -= io_res; + } + memset(driver->playbuf, 0, driver->playbufsize); + return 0; +} + + +static int +sndio_driver_null_cycle (sndio_driver_t *driver, jack_nframes_t nframes) +{ + if (nframes > driver->period_size) + { + jack_error("sndio_driver: null cycle failed: " + "nframes > period_size (%u/%u): %s@%i", nframes, + driver->period_size, __FILE__, __LINE__); + return -1; + } + + printf("sndio_driver: running null cycle\n"); + + if (driver->playback_channels > 0) + sndio_driver_write_silence (driver, nframes); + + if (driver->capture_channels > 0) + sndio_driver_read_silence (driver, nframes); + + return 0; +} + + +static int +sndio_driver_bufsize (sndio_driver_t *driver, jack_nframes_t nframes) +{ + return sndio_driver_set_parameters(driver); +} + + +static void +sndio_driver_delete (sndio_driver_t *driver) +{ + if (driver->hdl != NULL) + { + sio_close(driver->hdl); + driver->hdl = NULL; + } + + if (driver->capbuf != NULL) + { + free(driver->capbuf); + driver->capbuf = NULL; + } + if (driver->playbuf != NULL) + { + free(driver->playbuf); + driver->playbuf = NULL; + } + + if (driver->dev != NULL) + { + free(driver->dev); + driver->dev = NULL; + } + + jack_driver_nt_finish((jack_driver_nt_t *) driver); + + if (driver != NULL) + { + free(driver); + driver = NULL; + } +} + + +void +driver_finish (jack_driver_t *driver) +{ + sndio_driver_delete((sndio_driver_t *)driver); +} + + +static jack_driver_t * +sndio_driver_new (char *dev, jack_client_t *client, + jack_nframes_t sample_rate, jack_nframes_t period_size, + jack_nframes_t nperiods, int bits, + int capture_channels, int playback_channels, + jack_nframes_t cap_latency, jack_nframes_t play_latency, + int ignorehwbuf) +{ + sndio_driver_t *driver; + + driver = (sndio_driver_t *)calloc(1, sizeof(sndio_driver_t)); + if (driver == NULL) + { + jack_error("sndio_driver: malloc() failed: %s: %s@%i", + strerror(errno), __FILE__, __LINE__); + return NULL; + } + driver->engine = NULL; + jack_driver_nt_init((jack_driver_nt_t *)driver); + + driver->nt_attach = (JackDriverNTAttachFunction)sndio_driver_attach; + driver->nt_detach = (JackDriverNTDetachFunction)sndio_driver_detach; + driver->read = (JackDriverReadFunction)sndio_driver_read; + driver->write = (JackDriverWriteFunction)sndio_driver_write; + driver->null_cycle = (JackDriverNullCycleFunction)sndio_driver_null_cycle; + driver->nt_bufsize = (JackDriverNTBufSizeFunction)sndio_driver_bufsize; + driver->nt_start = (JackDriverNTStartFunction)sndio_driver_start; + driver->nt_stop = (JackDriverNTStopFunction)sndio_driver_stop; + driver->nt_run_cycle = (JackDriverNTRunCycleFunction)sndio_driver_run_cycle; + + if (dev != NULL) + driver->dev = strdup(dev); + else + driver->dev = NULL; + + driver->ignorehwbuf = ignorehwbuf; + + driver->sample_rate = sample_rate; + driver->period_size = period_size; + driver->orig_period_size = period_size; + driver->nperiods = nperiods; + driver->bits = bits; + driver->capture_channels = capture_channels; + driver->playback_channels = playback_channels; + driver->sys_cap_latency = cap_latency; + driver->sys_play_latency = play_latency; + + set_period_size(driver, period_size); + + driver->hdl = NULL; + driver->capbuf = driver->playbuf = NULL; + driver->capture_ports = driver->playback_ports = NULL; + + driver->poll_next = 0; + + if (sndio_driver_set_parameters(driver) < 0) + { + free(driver); + return NULL; + } + + driver->client = client; + + return (jack_driver_t *)driver; +} + + +/* jack driver published interface */ + + +const char driver_client_name[] = "sndio"; + + +jack_driver_desc_t * +driver_get_descriptor () +{ + jack_driver_desc_t *desc; + jack_driver_param_desc_t *params; + + desc = (jack_driver_desc_t *)calloc(1, sizeof(jack_driver_desc_t)); + if (desc == NULL) + { + jack_error("sndio_driver: calloc() failed: %s: %s@%i", + strerror(errno), __FILE__, __LINE__); + return NULL; + } + strlcpy(desc->name, driver_client_name, sizeof(desc->name)); + desc->nparams = SNDIO_DRIVER_N_PARAMS; + + params = calloc(desc->nparams, sizeof(jack_driver_param_desc_t)); + if (params == NULL) + { + jack_error("sndio_driver: calloc() failed: %s: %s@%i", + strerror(errno), __FILE__, __LINE__); + return NULL; + } + memcpy(params, sndio_params, + desc->nparams * sizeof(jack_driver_param_desc_t)); + desc->params = params; + + return desc; +} + + +jack_driver_t * +driver_initialize (jack_client_t *client, JSList * params) +{ + int bits = SNDIO_DRIVER_DEF_BITS; + jack_nframes_t sample_rate = SNDIO_DRIVER_DEF_FS; + jack_nframes_t period_size = SNDIO_DRIVER_DEF_BLKSIZE; + jack_nframes_t cap_latency = 0; + jack_nframes_t play_latency = 0; + unsigned int nperiods = SNDIO_DRIVER_DEF_NPERIODS; + unsigned int capture_channels = SNDIO_DRIVER_DEF_INS; + unsigned int playback_channels = SNDIO_DRIVER_DEF_OUTS; + const JSList *pnode; + const jack_driver_param_t *param; + char *dev = NULL; + int ignorehwbuf = 0; + + pnode = params; + while (pnode != NULL) + { + param = (const jack_driver_param_t *)pnode->data; + + switch (param->character) + { + case 'r': + sample_rate = param->value.ui; + break; + case 'p': + period_size = param->value.ui; + break; + case 'n': + nperiods = param->value.ui; + break; + case 'w': + bits = param->value.i; + break; + case 'i': + capture_channels = param->value.ui; + break; + case 'o': + playback_channels = param->value.ui; + break; + case 'd': + dev = strdup(param->value.str); + break; + case 'b': + ignorehwbuf = 1; + break; + case 'I': + cap_latency = param->value.ui; + break; + case 'O': + play_latency = param->value.ui; + break; + } + pnode = jack_slist_next(pnode); + } + + return sndio_driver_new(dev, client, sample_rate, period_size, + nperiods, bits, capture_channels, playback_channels, + cap_latency, play_latency, ignorehwbuf); +} diff --git a/drivers/sndio/sndio_driver.h b/drivers/sndio/sndio_driver.h new file mode 100644 index 0000000..03df4f1 --- /dev/null +++ b/drivers/sndio/sndio_driver.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2009 Jacob Meuser + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __JACK_SNDIO_DRIVER_H__ +#define __JACK_SNDIO_DRIVER_H__ + +#include +#include +#include + +#include +#include +#include +#include + +#define SNDIO_DRIVER_DEF_DEV "default" +#define SNDIO_DRIVER_DEF_FS 44100 +#define SNDIO_DRIVER_DEF_BLKSIZE 1024 +#define SNDIO_DRIVER_DEF_NPERIODS 2 +#define SNDIO_DRIVER_DEF_BITS 16 +#define SNDIO_DRIVER_DEF_INS 2 +#define SNDIO_DRIVER_DEF_OUTS 2 + +typedef jack_default_audio_sample_t jack_sample_t; + +typedef struct _sndio_driver +{ + JACK_DRIVER_NT_DECL + + jack_nframes_t sample_rate; + jack_nframes_t period_size; + jack_nframes_t orig_period_size; + unsigned int nperiods; + int bits; + unsigned int capture_channels; + unsigned int playback_channels; + jack_nframes_t sys_cap_latency; + jack_nframes_t sys_play_latency; + int ignorehwbuf; + + struct sio_hdl *hdl; + char *dev; + + void *capbuf; + size_t capbufsize; + void *playbuf; + size_t playbufsize; + JSList *capture_ports; + JSList *playback_ports; + + int sample_bytes; + size_t pprime; + + int poll_timeout; + jack_time_t poll_next; + + jack_client_t *client; + +} sndio_driver_t; + +#endif -- cgit v1.2.1