From 2eb6dec8e9f0114bdbad59cf8f11f197f8fdaaf3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 25 Apr 2007 10:27:13 +0000 Subject: initial commit git-svn-id: file:///home/lennart/svn/public/libsydney/trunk@3 9ba3c220-e4d3-45a2-8aa3-73fcc9aff6ce --- common.c | 523 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 523 insertions(+) create mode 100644 common.c (limited to 'common.c') diff --git a/common.c b/common.c new file mode 100644 index 0000000..b7a92d7 --- /dev/null +++ b/common.c @@ -0,0 +1,523 @@ +#include "sydney.h" +#include "macro.h" +#include "malloc.h" +#include "common.h" +#include "driver.h" + +int sa_device_create_opaque(sa_device_t **dev, const char *client_name, sa_mode_t mode, const char *codec) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(client_name, SA_ERROR_INVALID); + sa_return_val_if_fail(mode == SA_MODE_RDONLY || mode == SA_MODE_WRONLY || mode == SA_MODE_RDWR, SA_ERROR_INVALID); + sa_return_val_if_fail(codec, SA_ERROR_INVALID); + + return device_create_opaque(dev, client_name, mode, codec); +} + +int sa_device_create_pcm(sa_device_t **dev, const char *client_name, sa_mode_t mode, sa_pcm_format_t format, unsigned rate, unsigned channels) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(client_name, SA_ERROR_INVALID); + sa_return_val_if_fail(mode == SA_MODE_RDONLY || mode == SA_MODE_WRONLY || mode == SA_MODE_RDWR, SA_ERROR_INVALID); + sa_return_val_if_fail(format < SA_PCM_FORMAT_MAX, SA_ERROR_INVALID); + sa_return_val_if_fail(rate > 0, SA_ERROR_INVALID); + sa_return_val_if_fail(channels > 0, SA_ERROR_INVALID); + + return device_create_pcm(dev, client_name, mode, format, rate, channels); +} + +int sa_device_open(sa_device_t *dev) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->state == SA_STATE_INIT, SA_ERROR_STATE); + + return device_open(dev); +} + +int sa_device_destroy(sa_device_t *dev) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + + return device_destroy(dev); +} + +int sa_device_set_write_lower_watermark(sa_device_t *dev, size_t size) { + + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(size > 0, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->state == SA_STATE_INIT, SA_ERROR_STATE); + + dev->write_lower_watermark = size; + return SA_SUCCESS; +} + +int sa_device_set_read_lower_watermark(sa_device_t *dev, size_t size) { + + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(size > 0, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->state == SA_STATE_INIT, SA_ERROR_STATE); + + dev->read_lower_watermark = size; + return SA_SUCCESS; +} + +int sa_device_set_write_upper_watermark(sa_device_t *dev, size_t size) { + + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(size > 0, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->state == SA_STATE_INIT, SA_ERROR_STATE); + + dev->write_upper_watermark = size; + return SA_SUCCESS; +} + +int sa_device_set_read_upper_watermark(sa_device_t *dev, size_t size) { + + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(size > 0, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->state == SA_STATE_INIT, SA_ERROR_STATE); + + dev->read_upper_watermark = size; + return SA_SUCCESS; +} + +int sa_device_set_channel_map(sa_device_t *dev, const sa_channel_t *map) { + const sa_channel_t *c; + sa_channel_t *m; + unsigned n; + + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(map, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->state == SA_STATE_INIT, SA_ERROR_STATE); + sa_return_val_if_fail(!dev->codec, SA_ERROR_STATE); + + for (c = map, n = dev->nchannels; n > 0; c++, n--) + if (*c >= SA_CHANNEL_MAX) + return SA_ERROR_INVALID; + + if (!(m = sa_memdup(map, sizeof(sa_channel_t) * dev->nchannels))) + return SA_ERROR_OOM; + + sa_free(dev->channel_map); + dev->channel_map = m; + + return SA_SUCCESS; +} + +int sa_device_set_xrun_mode(sa_device_t *dev, sa_xrun_mode_t mode) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(mode == SA_XRUN_MODE_STOP || mode == SA_XRUN_MODE_SPIN, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->state == SA_STATE_INIT, SA_ERROR_STATE); + + dev->xrun_mode = mode; + return SA_SUCCESS; +} + +int sa_device_set_ni(sa_device_t *dev, int enable) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->state == SA_STATE_INIT, SA_ERROR_INVALID); + sa_return_val_if_fail(!dev->codec, SA_ERROR_STATE); + + dev->ni_enabled = !!enable; + return SA_SUCCESS; +} + +int sa_device_set_dsr(sa_device_t *dev, int enable) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->state == SA_STATE_INIT, SA_ERROR_INVALID); + sa_return_val_if_fail(!dev->codec, SA_ERROR_STATE); + + dev->dsr_enabled = !!enable; + return SA_SUCCESS; +} + +int sa_device_set_driver(sa_device_t *dev, const char *driver) { + char *d; + + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(driver, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->state == SA_STATE_INIT, SA_ERROR_STATE); + + if (!(d = sa_strdup(driver))) + return SA_ERROR_OOM; + + sa_free(dev->driver); + dev->driver = d; + + return SA_SUCCESS; +} + +int sa_device_start_thread(sa_device_t *dev, sa_event_callback_t *callback) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(callback, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->state == SA_STATE_INIT, SA_ERROR_STATE); + + return device_start_thread(dev, callback); +} + +int sa_device_change_device(sa_device_t *dev, const char *device_name) { + char *d; + + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(device_name, SA_ERROR_INVALID); + + if (dev->state == SA_STATE_INIT) { + if (!(d = sa_strdup(device_name))) + return SA_ERROR_OOM; + + sa_free(dev->device); + dev->device = d; + + return SA_SUCCESS; + } + + return device_change_device(dev, device_name); +} + +int sa_device_change_input_volume(sa_device_t *dev, int *vol) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(vol, SA_ERROR_INVALID); + + if (dev->state == SA_STATE_INIT) { + dev->input_volume = *vol; + return SA_SUCCESS; + } + + return device_change_input_volume(dev, vol); +} + +int sa_device_change_output_volume(sa_device_t *dev, int *vol) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(vol, SA_ERROR_INVALID); + + if (dev->state == SA_STATE_INIT) { + dev->output_volume = *vol; + return SA_SUCCESS; + } + + return device_change_output_volume(dev, vol); +} + +int sa_device_change_sampling_rate(sa_device_t *dev, unsigned rate) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(rate > 0, SA_ERROR_INVALID); + sa_return_val_if_fail(!dev->codec, SA_ERROR_STATE); + sa_return_val_if_fail(dev->dsr_enabled || dev->state == SA_STATE_INIT, SA_ERROR_STATE); + + if (dev->state == SA_STATE_INIT) { + dev->rate = rate; + return SA_SUCCESS; + } + + return device_change_sampling_rate(dev, rate); +} + +int sa_device_change_client_name(sa_device_t *dev, const char *client_name) { + char *n; + + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(client_name, SA_ERROR_INVALID); + + if (dev->state == SA_STATE_INIT) { + if (!(n = sa_strdup(client_name))) + return SA_ERROR_OOM; + + sa_free(dev->client_name); + dev->client_name = n; + + return SA_SUCCESS; + } + + return device_change_client_name(dev, client_name); +} + +int sa_device_change_stream_name(sa_device_t *dev, const char *stream_name) { + char *n; + + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(stream_name, SA_ERROR_INVALID); + + if (dev->state == SA_STATE_INIT) { + if (!(n = sa_strdup(stream_name))) + return SA_ERROR_OOM; + + sa_free(dev->stream_name); + dev->stream_name = n; + + return SA_SUCCESS; + } + + return device_change_stream_name(dev, stream_name); +} + +int sa_device_change_user_data(sa_device_t *dev, void *value) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + + dev->user_data = value; + return SA_SUCCESS; +} + +int sa_device_adjust_rate(sa_device_t *dev, sa_adjust_t direction) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(!dev->codec, SA_ERROR_STATE); + sa_return_val_if_fail(dev->state == SA_STATE_INIT, SA_ERROR_STATE); + + dev->adjust_rate = direction; + return SA_SUCCESS; +} + +int sa_device_adjust_nchannels(sa_device_t *dev, sa_adjust_t direction) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(!dev->codec, SA_ERROR_STATE); + sa_return_val_if_fail(dev->state == SA_STATE_INIT, SA_ERROR_STATE); + + dev->adjust_rate = direction; + return SA_SUCCESS; +} + +int sa_device_adjust_pcm_format(sa_device_t *dev, sa_adjust_t direction) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(!dev->codec, SA_ERROR_STATE); + sa_return_val_if_fail(dev->state == SA_STATE_INIT, SA_ERROR_STATE); + + dev->adjust_pcm_format = direction; + return SA_SUCCESS; +} + +int sa_device_get_state(sa_device_t *dev, sa_state_t *state) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(state, SA_ERROR_INVALID); + + return device_get_state(dev, state); +} + +int sa_device_get_sampling_rate(sa_device_t *dev, unsigned *rate) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(rate, SA_ERROR_INVALID); + sa_return_val_if_fail(!dev->codec, SA_ERROR_STATE); + + *rate = dev->rate; + return SA_SUCCESS; +} + +int sa_device_get_nchannels(sa_device_t *dev, int *nchannels) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(nchannels, SA_ERROR_INVALID); + sa_return_val_if_fail(!dev->codec, SA_ERROR_STATE); + + *nchannels = dev->nchannels; + return SA_SUCCESS; +} + +int sa_device_get_pcm_format(sa_device_t *dev, sa_pcm_format_t *pcm_format) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(pcm_format, SA_ERROR_INVALID); + sa_return_val_if_fail(!dev->codec, SA_ERROR_STATE); + + *pcm_format = dev->pcm_format; + return SA_SUCCESS; +} + +int sa_device_get_user_data(sa_device_t *dev, void **value) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(value, SA_ERROR_INVALID); + + *value = dev->user_data; + return SA_SUCCESS; +} + +int sa_device_get_event_error(sa_device_t *dev, sa_error_t *error) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(error, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->event == SA_EVENT_ERROR, SA_ERROR_STATE); + + *error = dev->error; + return SA_SUCCESS; +} + +int sa_device_get_event_notify(sa_device_t *dev, sa_notify_t *notify) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(notify, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->event == SA_EVENT_NOTIFY, SA_ERROR_STATE); + + *notify = dev->notify; + return SA_SUCCESS; +} + +int sa_device_get_position(sa_device_t *dev, sa_position_t position, int64_t *pos) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(pos, SA_ERROR_INVALID); + sa_return_val_if_fail(position < SA_POSITION_MAX, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->state == SA_STATE_RUNNING || dev->state == SA_STATE_STOPPED, SA_ERROR_STATE); + + return device_get_position(dev, position, pos); +} + +int sa_device_read(sa_device_t *dev, void *data, size_t nbytes) { + return sa_device_pread(dev, data, nbytes, 0, SA_SEEK_RELATIVE); +} + +int sa_device_write(sa_device_t *dev, const void *data, size_t nbytes) { + return sa_device_pwrite(dev, data, nbytes, 0, SA_SEEK_RELATIVE); +} + +int sa_device_read_ni(sa_device_t *dev, unsigned channel, void *data, size_t nbytes) { + return sa_device_pread_ni(dev, channel, data, nbytes, 0, SA_SEEK_RELATIVE); +} + +int sa_device_write_ni(sa_device_t *dev, unsigned channel, const void *data, size_t nbytes) { + return sa_device_pwrite_ni(dev, channel, data, nbytes, 0, SA_SEEK_RELATIVE); +} + +int sa_device_pread(sa_device_t *dev, void *data, size_t nbytes, int64_t offset, sa_seek_t whence) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(data, SA_ERROR_INVALID); + sa_return_val_if_fail(nbytes > 0, SA_ERROR_INVALID); + sa_return_val_if_fail(whence == SA_SEEK_RELATIVE || whence == SA_SEEK_ABSOLUTE || whence == SA_SEEK_RELATIVE_END, SA_ERROR_INVALID); + sa_return_val_if_fail(!dev->ni_enabled, SA_ERROR_STATE); + sa_return_val_if_fail(dev->mode & SA_MODE_RDONLY, SA_ERROR_STATE); + sa_return_val_if_fail(dev->state == SA_STATE_RUNNING || dev->state == SA_STATE_STOPPED, SA_ERROR_STATE); + + return device_pread(dev, data, nbytes, offset, whence); +} + +int sa_device_pwrite(sa_device_t *dev, const void *data, size_t nbytes, int64_t offset, sa_seek_t whence) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(data, SA_ERROR_INVALID); + sa_return_val_if_fail(nbytes > 0, SA_ERROR_INVALID); + sa_return_val_if_fail(whence == SA_SEEK_RELATIVE || whence == SA_SEEK_ABSOLUTE || whence == SA_SEEK_RELATIVE_END, SA_ERROR_INVALID); + sa_return_val_if_fail(!dev->ni_enabled, SA_ERROR_STATE); + sa_return_val_if_fail(dev->mode & SA_MODE_WRONLY, SA_ERROR_STATE); + sa_return_val_if_fail(dev->state == SA_STATE_RUNNING || dev->state == SA_STATE_STOPPED, SA_ERROR_STATE); + + return device_pwrite(dev, data, nbytes, offset, whence); +} + +int sa_device_pread_ni(sa_device_t *dev, unsigned channel, void *data, size_t nbytes, int64_t offset, sa_seek_t whence) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(data, SA_ERROR_INVALID); + sa_return_val_if_fail(nbytes > 0, SA_ERROR_INVALID); + sa_return_val_if_fail(whence == SA_SEEK_RELATIVE || whence == SA_SEEK_ABSOLUTE || whence == SA_SEEK_RELATIVE_END, SA_ERROR_INVALID); + sa_return_val_if_fail(channel < dev->nchannels, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->ni_enabled, SA_ERROR_STATE); + sa_return_val_if_fail(dev->mode & SA_MODE_RDONLY, SA_ERROR_STATE); + sa_return_val_if_fail(dev->state == SA_STATE_RUNNING || dev->state == SA_STATE_STOPPED, SA_ERROR_STATE); + + return device_pread_ni(dev, channel, data, nbytes, offset, whence); +} + +int sa_device_pwrite_ni(sa_device_t *dev, unsigned channel, const void *data, size_t nbytes, int64_t offset, sa_seek_t whence) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(data, SA_ERROR_INVALID); + sa_return_val_if_fail(nbytes > 0, SA_ERROR_INVALID); + sa_return_val_if_fail(whence == SA_SEEK_RELATIVE || whence == SA_SEEK_ABSOLUTE || whence == SA_SEEK_RELATIVE_END, SA_ERROR_INVALID); + sa_return_val_if_fail(channel < dev->nchannels, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->ni_enabled, SA_ERROR_STATE); + sa_return_val_if_fail(dev->mode & SA_MODE_WRONLY, SA_ERROR_STATE); + sa_return_val_if_fail(dev->state == SA_STATE_RUNNING || dev->state == SA_STATE_STOPPED, SA_ERROR_STATE); + + return device_pwrite_ni(dev, channel, data, nbytes, offset, whence); +} + +int sa_device_get_read_size(sa_device_t *dev, size_t *size) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(size, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->mode & SA_MODE_RDONLY, SA_ERROR_STATE); + sa_return_val_if_fail(dev->state == SA_STATE_RUNNING || dev->state == SA_STATE_STOPPED, SA_ERROR_STATE); + + return device_get_read_size(dev, size); +} + +int sa_device_get_write_size(sa_device_t *dev, size_t *size) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(size, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->mode & SA_MODE_WRONLY, SA_ERROR_STATE); + sa_return_val_if_fail(dev->state == SA_STATE_RUNNING || dev->state == SA_STATE_STOPPED, SA_ERROR_STATE); + + return device_get_write_size(dev, size); +} + +int sa_device_resume(sa_device_t *dev) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->state == SA_STATE_RUNNING || dev->state == SA_STATE_STOPPED, SA_ERROR_STATE); + + return device_resume(dev); +} + +int sa_device_pause(sa_device_t *dev) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->state == SA_STATE_RUNNING || dev->state == SA_STATE_STOPPED, SA_ERROR_STATE); + + return device_pause(dev); +} + +int sa_device_drain(sa_device_t *dev) { + sa_return_val_if_fail(dev, SA_ERROR_INVALID); + sa_return_val_if_fail(dev->state == SA_STATE_RUNNING || dev->state == SA_STATE_STOPPED, SA_ERROR_STATE); + + return device_drain(dev); +} + +sa_device_t *device_alloc(size_t total) { + sa_device_t *d; + + sa_assert(total >= sizeof(sa_device_t)); + + if (!(d = sa_malloc0(total))) + return NULL; + + /* All fields a carefully chosen in a way that initializing them + * NUL bytes is sufficient */ + + return d; +} + +void device_free(sa_device_t *d) { + sa_free(d->codec); + sa_free(d->driver); + sa_free(d->device); + sa_free(d->channel_map); + sa_free(d->client_name); + sa_free(d->stream_name); + sa_free(d); +} + +int device_alloc_opaque(sa_device_t **dev, size_t total, const char *client_name, sa_mode_t mode, const char *codec) { + int error; + + if (!(*dev = device_alloc(total))) + return SA_ERROR_OOM; + + (*dev)->mode = mode; + + if (!((*dev)->codec = sa_strdup(codec))) { + device_free(*dev); + return SA_ERROR_OOM; + } + + if ((error = sa_device_change_client_name(*dev, client_name))) { + device_free(*dev); + return error; + } + + return SA_SUCCESS; +} + +int device_alloc_pcm(sa_device_t **dev, size_t total, const char *client_name, sa_mode_t mode, sa_pcm_format_t format, unsigned rate, unsigned nchannels) { + int error; + + if (!(*dev = device_alloc(total))) + return SA_ERROR_OOM; + + (*dev)->mode = mode; + (*dev)->pcm_format = format; + (*dev)->nchannels = nchannels; + + if ((error = sa_device_change_sampling_rate(*dev, rate))) { + device_free(*dev); + return error; + } + + if ((error = sa_device_change_client_name(*dev, client_name))) { + device_free(*dev); + return error; + } + + return SA_SUCCESS; +} -- cgit