#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; }