From 7d83e5c7816b5e343695a75ba58b32dbe1be969a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 1 Oct 2007 20:16:28 +0000 Subject: move all sources down to a seperate src/ tree git-svn-id: file:///home/lennart/svn/public/libsydney/trunk@34 9ba3c220-e4d3-45a2-8aa3-73fcc9aff6ce --- oss.c | 858 ------------------------------------------------------------------ 1 file changed, 858 deletions(-) delete mode 100644 oss.c (limited to 'oss.c') diff --git a/oss.c b/oss.c deleted file mode 100644 index d09f8aa..0000000 --- a/oss.c +++ /dev/null @@ -1,858 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sydney.h" -#include "common.h" -#include "macro.h" -#include "malloc.h" -#include "converter.h" -#include "driver.h" -#include "thread.h" -#include "bufferq.h" - -#define DEFAULT_DEVICE "/dev/dsp" -#define DRIVER_NAME "oss" - -typedef struct oss_stream oss_stream_t; -#define OSS_STREAM(x) ((oss_stream_t*) (x->private)) - -struct oss_stream { - sa_stream_t *parent; - int fd; - pcm_attrs_t real_pcm_attrs; - sa_converter_t converter_read, converter_write; - size_t read_fragment_size, write_fragment_size; - unsigned read_nfragments, write_nfragments; - sa_thread_t *thread; - int socket_fds[2]; - sa_bufferq_t bufferq; -}; - -static int simple_log2(int v) { - int k = 0; - - for (;;) { - v >>= 1; - if (!v) break; - k++; - } - - return k; -} - -static size_t fixup_bps(size_t s, size_t bps1, size_t bps2) { - return (s*bps2)/bps1; -} - -int driver_open(sa_stream_t *s) { - oss_stream_t *oss; - char *n; - int f, arg, bs, r, phase, i, found, suggested, fs, l, m; - unsigned c; - size_t real_bps = 0, bps; - int loops = 0; - - static const int format_map[_SA_PCM_FORMAT_MAX] = { - [SA_PCM_FORMAT_U8] = AFMT_U8, - [SA_PCM_FORMAT_ULAW] = AFMT_MU_LAW, - [SA_PCM_FORMAT_ALAW] = AFMT_A_LAW, - [SA_PCM_FORMAT_S16_LE] = AFMT_S16_LE, - [SA_PCM_FORMAT_S16_BE] = AFMT_S16_BE, - [SA_PCM_FORMAT_S24_LE] = AFMT_S16_NE, /* OSS doesn't know this format, hence we pick the best we can */ - [SA_PCM_FORMAT_S24_BE] = AFMT_S16_NE, - [SA_PCM_FORMAT_S32_LE] = AFMT_S16_NE, - [SA_PCM_FORMAT_S32_BE] = AFMT_S16_NE, - [SA_PCM_FORMAT_FLOAT32_LE] = AFMT_S16_NE, - [SA_PCM_FORMAT_FLOAT32_BE] = AFMT_S16_NE - }; - static const int try_rates[] = { 8000, 16000, 32000, 44100, 48000, 96000, 192000 }; - - if (s->driver && strcmp(s->driver, DRIVER_NAME)) - return SA_ERROR_NO_DRIVER; - - if (!(s->private = oss = sa_new0(oss_stream_t, 1))) - return SA_ERROR_OOM; - - oss->parent = s; - oss->socket_fds[0] = oss->socket_fds[1] = -1; - - n = s->device ? s->device : DEFAULT_DEVICE; - if (!s->codec) - bps = s->pcm_frame_size * s->pcm_attrs.rate; - - for (;;) { - /* We need to loop here, because we have to call SETFRAGMENT - * as first ioctl after the open, at a point where we - * don't now yet the sample type, freq and the number of - * channels we actually settled on. Hence we have to loop - * here: if the sampling format is too far off we have to call - * SETFRAGMENT again which can do only after reopening the - * device again. */ - - if ((oss->fd = open(n, s->mode == SA_MODE_RDONLY ? O_RDONLY : (s->mode == SA_MODE_WRONLY ? O_WRONLY : O_RDWR) | O_NOCTTY | O_NONBLOCK)) < 0) { - - if (errno == ENODEV || errno == ENOENT) - r = SA_ERROR_NO_DEVICE; - else - r = SA_ERROR_SYSTEM; - - goto fail; - } - - fcntl(oss->fd, F_SETFL, fcntl(oss->fd, F_GETFL) & ~O_NONBLOCK); /* FIXME*/ - - if (!s->device) { - if (!(n = sa_strdup(n))) { - r = SA_ERROR_OOM; - goto fail; - } - - s->device = n; - } - - /* Set fragment settings */ - if (s->mode & SA_MODE_WRONLY) { - bs = s->write_lower_watermark; - } - - if (s->mode & SA_MODE_RDONLY) { - int rbs; - - rbs = s->read_upper_watermark; - - if (s->mode & SA_MODE_WRONLY) - bs = bs > rbs ? bs : rbs; - else - bs = rbs; - } - - if (!s->codec && real_bps) - bs = fixup_bps(bs, bps, real_bps); - - fs = bs/4; - l = simple_log2(fs); - if (l < 1) l = 1; - m = (bs+(1< 0x7FFF) m = 0x7FFF; - - printf("Asking OSS for: %u fragments, %u fragsize\n", m, 1 << l); - - arg = (m << 16) | l; - - ioctl(oss->fd, SNDCTL_DSP_SETFRAGMENT, &arg); - /* We ignore errors on this call, since it's merely a hint anyway */ - - if (s->codec) { - - if (strcmp(s->codec, SA_CODEC_AC3) == 0) - f = AFMT_AC3; - else if (strcmp(s->codec, SA_CODEC_MPEG) == 0) - f = AFMT_MPEG; - else { - r = SA_ERROR_NO_CODEC; - goto fail; - } - - } else - f = format_map[s->pcm_attrs.format]; - - bs = 0; - - for (;;) { - arg = f; - - if (ioctl(oss->fd, SNDCTL_DSP_SETFMT, &arg) < 0) { - r = SA_ERROR_SYSTEM; - goto fail; - } - - if (arg == f) - break; - - /* Hmm, the device doesn't support what we're looking for, - * let's try our luck */ - - if (f == AFMT_S16_LE && !bs) { - f = AFMT_S16_BE; - bs = 1; - } else if (f == AFMT_S16_BE && !bs) { - f = AFMT_S16_LE; - bs = 1; - } else if (f == AFMT_S16_LE || f == AFMT_S16_BE) { - f = AFMT_MU_LAW; - bs = 0; - } else if (f == AFMT_MU_LAW && !bs) { - f = AFMT_A_LAW; - bs = 1; - } else if (f == AFMT_A_LAW && !bs) { - f = AFMT_MU_LAW; - bs = 1; - } else if (f == AFMT_A_LAW || f == AFMT_MU_LAW) { - f = AFMT_U8; - } else if (f == AFMT_AC3 || f == AFMT_MPEG) { - r = SA_ERROR_NO_CODEC; - goto fail; - } else { - r = SA_ERROR_NO_PCM_FORMAT; - goto fail; - } - } - - if (!s->codec) { - - switch (f) { - case AFMT_MU_LAW: - oss->real_pcm_attrs.format = SA_PCM_FORMAT_ULAW; - break; - - case AFMT_A_LAW: - oss->real_pcm_attrs.format = SA_PCM_FORMAT_ALAW; - break; - - case AFMT_U8: - oss->real_pcm_attrs.format = SA_PCM_FORMAT_U8; - break; - - case AFMT_S16_LE: - oss->real_pcm_attrs.format = SA_PCM_FORMAT_S16_LE; - break; - - case AFMT_S16_BE: - oss->real_pcm_attrs.format = SA_PCM_FORMAT_S16_BE; - break; - - default: - sa_assert_not_reached(); - } - - - found = 0; - - if (s->adjust_nchannels >= 0) { - - /* First try more channels ... */ - for (c = s->pcm_attrs.nchannels; c < 8 || c == s->pcm_attrs.nchannels; c ++) { - arg = c; - if (ioctl(oss->fd, SNDCTL_DSP_CHANNELS, &arg) < 0) { - r = SA_ERROR_SYSTEM; - goto fail; - } - - if (arg == (int) c) { - found = 1; - break; - } - } - - /* ... then try less channels */ - if (!found) { - for (c = s->pcm_attrs.nchannels - 1; c > 0; c --) { - arg = c; - if (ioctl(oss->fd, SNDCTL_DSP_CHANNELS, &arg) < 0) { - r = SA_ERROR_SYSTEM; - goto fail; - } - - if (arg == (int) c) { - found = 1; - break; - } - } - } - } else { - - /* First try less channels ... */ - for (c = s->pcm_attrs.nchannels; c > 0; c --) { - arg = c; - if (ioctl(oss->fd, SNDCTL_DSP_CHANNELS, &arg) < 0) { - r = SA_ERROR_SYSTEM; - goto fail; - } - - if (arg == (int) c) { - found = 1; - break; - } - } - - /* ... then try more channels */ - if (!found) { - for (c = s->pcm_attrs.nchannels + 1; c < 8; c ++) { - arg = c; - if (ioctl(oss->fd, SNDCTL_DSP_CHANNELS, &arg) < 0) { - r = SA_ERROR_SYSTEM; - goto fail; - } - - if (arg == (int) c) { - found = 1; - break; - } - } - } - } - - if (!found) { - errno = EIO; - r = SA_ERROR_SYSTEM; - goto fail; - } - - oss->real_pcm_attrs.nchannels = c; - - if (!(oss->real_pcm_attrs.channel_map = sa_new(sa_channel_t, c))) { - r = SA_ERROR_OOM; - goto fail; - } - - switch (c) { - case 8: - oss->real_pcm_attrs.channel_map[7] = SA_CHANNEL_REAR_RIGHT; - case 7: - oss->real_pcm_attrs.channel_map[6] = SA_CHANNEL_REAR_LEFT; - case 6: - oss->real_pcm_attrs.channel_map[5] = SA_CHANNEL_FRONT_LEFT; - case 5: - oss->real_pcm_attrs.channel_map[4] = SA_CHANNEL_FRONT_RIGHT; - case 4: - oss->real_pcm_attrs.channel_map[3] = SA_CHANNEL_LFE; - case 3: - oss->real_pcm_attrs.channel_map[2] = SA_CHANNEL_CENTER; - case 2: - oss->real_pcm_attrs.channel_map[1] = SA_CHANNEL_RIGHT; - oss->real_pcm_attrs.channel_map[0] = SA_CHANNEL_LEFT; - break; - case 1: - oss->real_pcm_attrs.channel_map[0] = SA_CHANNEL_MONO; - break; - } - - r = s->pcm_attrs.rate; - - if (r < 8000) - r = 8000; - - suggested = 0; - phase = 0; - - for (;;) { - arg = r; - - if (ioctl(oss->fd, SNDCTL_DSP_SPEED, &arg) < 0) { - r = SA_ERROR_SYSTEM; - goto fail; - } - - sa_assert(arg > 0); - - if (arg >= r*0.95 || arg <= r *1.05) - break; - - if (arg > suggested) - suggested = arg; - - if (s->adjust_rate >= 0) { - - if (phase == 0) { - /* Find the next higher sample rate to try */ - - for (i = 0; i < (int) SA_ELEMENTSOF(try_rates); i++) { - /* Yes, we could optimize a little here */ - - if (try_rates[i] > r) { - r = try_rates[i]; - break; - } - } - - - if (i == SA_ELEMENTSOF(try_rates)) { - phase = 1; - r = s->pcm_attrs.rate; - } - } - - if (phase == 1) { - /* Find the next lower sample rate to try */ - - for (i = SA_ELEMENTSOF(try_rates); i > 0; i--) { - if (suggested > try_rates[i-1] && suggested < r) { - r = suggested; - break; - } else if (try_rates[i-1] < r) { - r = try_rates[i-1]; - break; - } - } - - sa_assert(i > 0); - } - - } else { - - if (phase == 0) { - /* Find the next lower sample rate to try */ - - for (i = SA_ELEMENTSOF(try_rates); i > 0; i--) { - - if (try_rates[i-1] < r) { - r = try_rates[i-1]; - break; - } - } - - if (i == 0) { - phase = 1; - r = s->pcm_attrs.rate; - } - } - - if (phase == 1) { - /* Find the next higher sample rate to try */ - - for (i = 0; i < (int) SA_ELEMENTSOF(try_rates); i++) { - if (suggested > r && suggested < try_rates[i]) { - r = suggested; - break; - } else if (try_rates[i] < r) { - r = try_rates[i]; - break; - } - } - - sa_assert(i < (int) SA_ELEMENTSOF(try_rates)); - } - } - - } - - oss->real_pcm_attrs.rate = r; - - printf("Chosen: %u channels, %uHz, format=%u\n", oss->real_pcm_attrs.nchannels, oss->real_pcm_attrs.rate, oss->real_pcm_attrs.format); - - real_bps = oss->real_pcm_attrs.nchannels * oss->real_pcm_attrs.rate * sa_get_pcm_sample_size(oss->real_pcm_attrs.format); - - if (real_bps != bps && loops < 1) { - loops++; - - sa_free(oss->real_pcm_attrs.channel_map); - oss->real_pcm_attrs.channel_map = NULL; - - close(oss->fd); - - printf("bps changed, retrying...\n"); - continue; - } - } - - break; - } - - /* First, let's try GETBLKSIZE */ - if (ioctl(oss->fd, SNDCTL_DSP_GETBLKSIZE, &arg) >= 0) { - if (s->mode & SA_MODE_RDONLY) { - oss->read_fragment_size = arg; - oss->read_nfragments = 2; - } - - if (s->mode & SA_MODE_WRONLY) { - oss->write_fragment_size = arg; - oss->write_nfragments = 2; - } - } - - /* Now, let's use GETxSPACE */ - if (s->mode & SA_MODE_RDONLY) { - audio_buf_info info; - - if (ioctl(oss->fd, SNDCTL_DSP_GETISPACE, &info) >= 0) { - oss->read_fragment_size = info.fragsize; - oss->read_nfragments = info.fragstotal; - } - } - - if (s->mode & SA_MODE_WRONLY) { - audio_buf_info info; - - if (ioctl(oss->fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) { - oss->write_fragment_size = info.fragsize; - oss->write_nfragments = info.fragstotal; - } - } - - if (s->mode & SA_MODE_WRONLY && (oss->write_fragment_size <= 0 || oss->write_nfragments <= 1)) { - errno = EIO; - r = SA_ERROR_SYSTEM; - goto fail; - } - - if (s->mode & SA_MODE_RDONLY && (oss->read_fragment_size <= 0 || oss->read_nfragments <= 1)) { - errno = EIO; - r = SA_ERROR_SYSTEM; - goto fail; - } - - if (!s->codec) { - - if (s->adjust_nchannels != 0) { - sa_channel_t *cm; - - if (!(cm = sa_newdup(sa_channel_t, oss->real_pcm_attrs.channel_map, oss->real_pcm_attrs.nchannels))) { - r = SA_ERROR_OOM; - goto fail; - } - - sa_free(s->pcm_attrs.channel_map); - s->pcm_attrs.channel_map = cm; - - s->pcm_attrs.nchannels = oss->real_pcm_attrs.nchannels; - } - if (s->adjust_rate != 0) - s->pcm_attrs.rate = oss->real_pcm_attrs.rate; - if (s->adjust_pcm_format != 0) - s->pcm_attrs.format = oss->real_pcm_attrs.format; - - if (s->mode & SA_MODE_RDONLY) - if ((r = sa_converter_init(&oss->converter_read, &oss->real_pcm_attrs, &s->pcm_attrs, s->dynamic_rate_enabled)) < 0) - goto fail; - - if (s->mode & SA_MODE_WRONLY) - if ((r = sa_converter_init(&oss->converter_write, &s->pcm_attrs, &oss->real_pcm_attrs, s->dynamic_rate_enabled)) < 0) - goto fail; - } - - if (s->adjust_watermarks) { - - if (s->mode & SA_MODE_RDONLY) { - s->read_lower_watermark = oss->read_fragment_size; - s->read_upper_watermark = oss->read_fragment_size * oss->read_nfragments; - } - - if (s->mode & SA_MODE_WRONLY) { - s->write_lower_watermark = oss->write_fragment_size; - s->write_upper_watermark = oss->write_fragment_size * oss->write_nfragments; - } - } - - if (s->mode & SA_MODE_RDONLY) - printf("Chosen for read: %u fragments, %u fragsize\n", oss->read_nfragments, oss->read_fragment_size); - - if (s->mode & SA_MODE_WRONLY) - printf("Chosen for write: %u fragments, %u fragsize\n", oss->write_nfragments, oss->write_fragment_size); - - if (sa_bufferq_init(&oss->bufferq, s->pcm_attrs.nchannels, s->pcm_sample_size) < 0) - goto fail; - - return SA_SUCCESS; - -fail: - driver_destroy(s); - return r; -} - -int driver_destroy(sa_stream_t *s) { - oss_stream_t *oss = OSS_STREAM(s); - - if (oss) { - - if (oss->thread) - driver_stop_thread(s); - - if (oss->fd >= 0) - close(oss->fd); - - sa_bufferq_done(&oss->bufferq); - - sa_free(oss->real_pcm_attrs.channel_map); - sa_converter_done(&oss->converter_read); - sa_converter_done(&oss->converter_write); - - sa_free(oss); - } - - return SA_SUCCESS; -} - -static int feed(sa_stream_t *s) { - oss_stream_t *oss = OSS_STREAM(s); - size_t w; - int ret; - - sa_assert(s); - - for (;;) { - if ((ret = driver_get_write_size(s, &w)) < 0) - return ret; - - while (w > 0) { - void* i[1]; - size_t nbytes; - uint8_t *d; - int drop; - - sa_bufferq_get(&oss->bufferq, i, &nbytes); - - if (nbytes) { - void **dst; - size_t *stride; - - if ((ret = sa_converter_go_interleaved(&oss->converter_write, i[0], &dst, &stride, 1, &nbytes))) - return ret; - - d = dst[0]; - drop = 1; - - s->state = SA_STATE_RUNNING; - - } else { - nbytes = w > oss->write_fragment_size ? oss->write_fragment_size : w; - - if (!(d = sa_converter_get_zero_buffer(&oss->converter_write, nbytes))) - return SA_ERROR_OOM; - - drop = s->xrun_mode == SA_XRUN_MODE_SPIN; - - if (s->xrun_mode == SA_XRUN_MODE_STOP) - s->state = SA_STATE_STOPPED; - } - - while (nbytes > 0) { - ssize_t l; - - if ((l = write(oss->fd, d, nbytes)) < 0) - return SA_ERROR_SYSTEM; - - sa_assert(l > 0); - - nbytes -= l; - d += l; - - w -= 1; - - if (drop) - sa_bufferq_drop(&oss->bufferq, l); - } - } - } - - return SA_SUCCESS; -} - -enum { - POLLFD_OSS_FD, - POLLFD_SOCKET_FD, - POLLFD_MAX -}; - -static void thread_func(void *data) { - struct pollfd pollfds[POLLFD_MAX]; - sa_stream_t *s = data; - oss_stream_t *oss = OSS_STREAM(s); - sigset_t mask; - - sigfillset(&mask); - pthread_sigmask(SIG_BLOCK, &mask, NULL); - - if (s->callback) { - s->event = SA_EVENT_INIT_THREAD; - if (s->callback(s, SA_EVENT_INIT_THREAD) < 0) - return; - } - - memset(pollfds, 0, sizeof(pollfds)); - - pollfds[POLLFD_SOCKET_FD].fd = oss->socket_fds[0]; - pollfds[POLLFD_SOCKET_FD].events = POLLIN; - - pollfds[POLLFD_OSS_FD].fd = oss->fd; - pollfds[POLLFD_OSS_FD].events = ((s->mode & SA_MODE_RDONLY) ? POLLIN : 0) | ((s->mode & SA_MODE_WRONLY) ? POLLOUT : 0); - - for (;;) { - int ret; - if (poll(pollfds, POLLFD_MAX, -1) < 0) { - if (errno == EINTR) - continue; - - if (s->callback) { - s->event = SA_EVENT_ERROR; - s->error = SA_ERROR_SYSTEM; - s->callback(s, SA_EVENT_ERROR); - } - break; - } - - if (pollfds[POLLFD_SOCKET_FD].revents) - break; - - if (pollfds[POLLFD_OSS_FD].revents & (POLLERR|POLLHUP|POLLNVAL)) { - - if (s->callback) { - s->event = SA_EVENT_ERROR; - s->error = SA_ERROR_SYSTEM; - errno = EIO; - s->callback(s, SA_EVENT_ERROR); - } - break; - } - - if (s->callback) { - s->event = SA_EVENT_REQUEST_IO; - if (s->callback(s, SA_EVENT_REQUEST_IO) < 0) - break; - } - - if ((ret = feed(s)) < 0) { - if (s->callback) { - s->event = SA_EVENT_ERROR; - s->error = ret; - s->callback(s, SA_EVENT_ERROR); - } - break; - } - } -} - -int driver_start_thread(sa_stream_t *s, sa_event_callback_t callback) { - oss_stream_t *oss = OSS_STREAM(s); - sa_return_val_if_fail(!oss->thread, SA_ERROR_STATE); - - s->callback = callback; - - if ((socketpair(AF_UNIX, SOCK_DGRAM, 0, oss->socket_fds)) < 0) - return SA_ERROR_SYSTEM; - - if (!(oss->thread = sa_thread_new(thread_func, s))) - return SA_ERROR_OOM; - - return SA_SUCCESS; -} - -int driver_stop_thread(sa_stream_t *s) { - oss_stream_t *oss = OSS_STREAM(s); - sa_return_val_if_fail(oss->thread, SA_ERROR_STATE); - sa_return_val_if_fail(oss->thread != sa_thread_self(), SA_ERROR_STATE); - - if (oss->socket_fds[0] >= 0) - close(oss->socket_fds[0]); - - if (oss->socket_fds[1] >= 0) - close(oss->socket_fds[1]); - - if (oss->thread) - sa_thread_free(oss->thread); - - oss->thread = NULL; - oss->socket_fds[0] = oss->socket_fds[1] = -1; - - return SA_SUCCESS; -} - -int driver_change_read_volume(sa_stream_t *s, const int32_t vol[]) { - oss_stream_t *oss = OSS_STREAM(s); - - sa_return_val_if_fail(!s->codec, SA_ERROR_NOT_SUPPORTED); - - sa_converter_set_volume(&oss->converter_read, vol); - - return SA_SUCCESS; -} - -int driver_change_write_volume(sa_stream_t *s, const int32_t vol[]) { - oss_stream_t *oss = OSS_STREAM(s); - - sa_return_val_if_fail(!s->codec, SA_ERROR_NOT_SUPPORTED); - - sa_converter_set_volume(&oss->converter_write, vol); - - return SA_SUCCESS; -} - -int driver_change_rate(sa_stream_t *s, unsigned rate) { - oss_stream_t *oss = OSS_STREAM(s); - - if (s->mode & SA_MODE_RDONLY) - sa_converter_set_ratio(&oss->converter_read, oss->real_pcm_attrs.rate, s->pcm_attrs.rate); - if (s->mode & SA_MODE_WRONLY) - sa_converter_set_ratio(&oss->converter_write, s->pcm_attrs.rate, oss->real_pcm_attrs.rate); - - return SA_SUCCESS; -} - -int driver_get_state(sa_stream_t *s, sa_state_t *state) { - *state = s->state; - return SA_SUCCESS; -} - -int driver_get_position(sa_stream_t *s, sa_position_t position, int64_t *pos) { - return SA_ERROR_NOT_SUPPORTED; -} - -int driver_read(sa_stream_t *s, void *data, size_t nbytes) { - return SA_ERROR_NOT_SUPPORTED; -} - -int driver_pwrite(sa_stream_t *s, const void *data, size_t nbytes, int64_t offset, sa_seek_t whence) { - oss_stream_t *oss = OSS_STREAM(s); - int ret, ret2; - - if ((ret = sa_bufferq_push(&oss->bufferq, 0, data, nbytes, offset, whence, SA_BUFFERQ_ITEM_STATIC))) - return ret; - - ret = feed(s); - ret2 = sa_bufferq_realloc(&oss->bufferq); - - return ret ? ret : ret2; -} - -int driver_read_ni(sa_stream_t *s, unsigned channel, void *data, size_t nbytes) { - return SA_ERROR_NOT_SUPPORTED; -} - -int driver_pwrite_ni(sa_stream_t *s, unsigned channel, const void *data, size_t nbytes, int64_t offset, sa_seek_t whence) { - return SA_ERROR_NOT_SUPPORTED; -} - -int driver_get_read_size(sa_stream_t *s, size_t *size) { - return SA_ERROR_NOT_SUPPORTED; -} - -int driver_get_write_size(sa_stream_t *s, size_t *size) { - return SA_ERROR_NOT_SUPPORTED; -} - -int driver_resume(sa_stream_t *s) { - return SA_ERROR_NOT_SUPPORTED; -} - -int driver_pause(sa_stream_t *s) { - return SA_ERROR_NOT_SUPPORTED; -} - -int driver_drain(sa_stream_t *s) { - oss_stream_t *oss = OSS_STREAM(s); - sa_return_val_if_fail(!oss->thread, SA_ERROR_STATE); - - if (ioctl(oss->fd, SNDCTL_DSP_SYNC, NULL) < 0) - return SA_ERROR_SYSTEM; - - return SA_SUCCESS; -} - -/* Unsupported operations */ - -int driver_change_device(sa_stream_t *s, const char *device) { - return SA_ERROR_NOT_SUPPORTED; -} - -int driver_change_meta_data(sa_stream_t *s, const char *name, const void *data, size_t size) { - return SA_ERROR_NOT_SUPPORTED; -} -- cgit