Changeset View
Changeset View
Standalone View
Standalone View
head/www/firefox-esr/files/patch-cubeb-oss
Show First 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | |||||
+#if defined (USE_OSS) | +#if defined (USE_OSS) | ||||
+ oss_init, | + oss_init, | ||||
+#endif | +#endif | ||||
#if defined(USE_AUDIOUNIT_RUST) | #if defined(USE_AUDIOUNIT_RUST) | ||||
audiounit_rust_init, | audiounit_rust_init, | ||||
#endif | #endif | ||||
--- /dev/null | --- /dev/null | ||||
+++ media/libcubeb/src/cubeb_oss.c | +++ media/libcubeb/src/cubeb_oss.c | ||||
@@ -0,0 +1,1210 @@ | @@ -0,0 +1,1245 @@ | ||||
+/* | +/* | ||||
+ * Copyright © 2019-2020 Nia Alarie <nia@NetBSD.org> | + * Copyright © 2019-2020 Nia Alarie <nia@NetBSD.org> | ||||
+ * Copyright © 2020 Ka Ho Ng <khng300@gmail.com> | + * Copyright © 2020 Ka Ho Ng <khng300@gmail.com> | ||||
+ * Copyright © 2020 The FreeBSD Foundation | |||||
+ * | + * | ||||
+ * Portions of this software were developed by Ka Ho Ng | |||||
+ * under sponsorship from the FreeBSD Foundation. | |||||
+ * | |||||
+ * This program is made available under an ISC-style license. See the | + * This program is made available under an ISC-style license. See the | ||||
+ * accompanying file LICENSE for details. | + * accompanying file LICENSE for details. | ||||
+ */ | + */ | ||||
+ | + | ||||
+#if defined(__FreeBSD__) && __FreeBSD__ < 12 | +#if defined(__FreeBSD__) && __FreeBSD__ < 12 | ||||
+#define _WITH_GETLINE | +#define _WITH_GETLINE | ||||
+#endif | +#endif | ||||
+#include <assert.h> | +#include <assert.h> | ||||
Show All 21 Lines | |||||
+#define OSS_PREFER_RATE (48000) | +#define OSS_PREFER_RATE (48000) | ||||
+#endif | +#endif | ||||
+ | + | ||||
+/* Standard acceptable minimum. */ | +/* Standard acceptable minimum. */ | ||||
+#ifndef OSS_LATENCY_MS | +#ifndef OSS_LATENCY_MS | ||||
+#define OSS_LATENCY_MS (8) | +#define OSS_LATENCY_MS (8) | ||||
+#endif | +#endif | ||||
+ | + | ||||
+#ifndef OSS_NFRAGS | |||||
+#define OSS_NFRAGS (4) | |||||
+#endif | |||||
+ | |||||
+#ifndef OSS_DEFAULT_DEVICE | +#ifndef OSS_DEFAULT_DEVICE | ||||
+#define OSS_DEFAULT_DEVICE "/dev/dsp" | +#define OSS_DEFAULT_DEVICE "/dev/dsp" | ||||
+#endif | +#endif | ||||
+ | + | ||||
+#ifndef OSS_DEFAULT_MIXER | +#ifndef OSS_DEFAULT_MIXER | ||||
+#define OSS_DEFAULT_MIXER "/dev/mixer" | +#define OSS_DEFAULT_MIXER "/dev/mixer" | ||||
+#endif | +#endif | ||||
+ | + | ||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | |||||
+ bool destroying; | + bool destroying; | ||||
+ float volume; | + float volume; | ||||
+ struct oss_stream play; | + struct oss_stream play; | ||||
+ struct oss_stream record; | + struct oss_stream record; | ||||
+ cubeb_data_callback data_cb; | + cubeb_data_callback data_cb; | ||||
+ cubeb_state_callback state_cb; | + cubeb_state_callback state_cb; | ||||
+ uint64_t frames_written; | + uint64_t frames_written; | ||||
+ unsigned int nfr; /* Number of frames allocated */ | + unsigned int nfr; /* Number of frames allocated */ | ||||
+ unsigned int nfrags; | |||||
+ unsigned int bufframes; | |||||
+}; | +}; | ||||
+ | + | ||||
+static char const * | +static char const * | ||||
+oss_cubeb_devid_intern(cubeb *context, char const * devid) | +oss_cubeb_devid_intern(cubeb *context, char const * devid) | ||||
+{ | +{ | ||||
+ char const *is; | + char const *is; | ||||
+ pthread_mutex_lock(&context->mutex); | + pthread_mutex_lock(&context->mutex); | ||||
+ is = cubeb_strings_intern(context->devid_strs, devid); | + is = cubeb_strings_intern(context->devid_strs, devid); | ||||
▲ Show 20 Lines • Show All 593 Lines • ▼ Show 20 Lines | |||||
+ buf[i] = (buf[i] * multiplier) >> 15; | + buf[i] = (buf[i] * multiplier) >> 15; | ||||
+ } | + } | ||||
+} | +} | ||||
+ | + | ||||
+static int | +static int | ||||
+oss_audio_loop(cubeb_stream * s) | +oss_audio_loop(cubeb_stream * s) | ||||
+{ | +{ | ||||
+ int state = CUBEB_STATE_STARTED; | + int state = CUBEB_STATE_STARTED; | ||||
+ long nfr = 0; | |||||
+ int trig = 0; | + int trig = 0; | ||||
+ int drain = 0; | + int drain = 0; | ||||
+ struct pollfd pfds[2]; | + struct pollfd pfds[2]; | ||||
+ bool cbready = true; | + unsigned int ppending, rpending; | ||||
+ | + | ||||
+ pfds[0].fd = s->play.fd; | + pfds[0].fd = s->play.fd; | ||||
+ pfds[0].events = POLLOUT; | + pfds[0].events = POLLOUT; | ||||
+ pfds[1].fd = s->record.fd; | + pfds[1].fd = s->record.fd; | ||||
+ pfds[1].events = POLLIN; | + pfds[1].events = POLLIN; | ||||
+ | + | ||||
+ ppending = 0; | |||||
+ rpending = s->bufframes; | |||||
+ | |||||
+ if (s->record.fd != -1) { | + if (s->record.fd != -1) { | ||||
+ if (ioctl(s->record.fd, SNDCTL_DSP_SETTRIGGER, &trig)) { | + if (ioctl(s->record.fd, SNDCTL_DSP_SETTRIGGER, &trig)) { | ||||
+ LOG("Error %d occured when setting trigger on record fd", errno); | + LOG("Error %d occured when setting trigger on record fd", errno); | ||||
+ state = CUBEB_STATE_ERROR; | + state = CUBEB_STATE_ERROR; | ||||
+ goto out; | + goto out; | ||||
+ } | + } | ||||
+ trig |= PCM_ENABLE_INPUT; | + trig |= PCM_ENABLE_INPUT; | ||||
+ if (ioctl(s->record.fd, SNDCTL_DSP_SETTRIGGER, &trig)) { | + if (ioctl(s->record.fd, SNDCTL_DSP_SETTRIGGER, &trig)) { | ||||
+ LOG("Error %d occured when setting trigger on record fd", errno); | + LOG("Error %d occured when setting trigger on record fd", errno); | ||||
+ state = CUBEB_STATE_ERROR; | + state = CUBEB_STATE_ERROR; | ||||
+ goto out; | + goto out; | ||||
+ } | + } | ||||
+ memset(s->record.buf, 0, s->bufframes * s->record.frame_size); | |||||
+ } | + } | ||||
+ | + | ||||
+ if (s->record.fd != -1) | |||||
+ memset(s->record.buf, 0, s->nfr); | |||||
+ | |||||
+ while (1) { | + while (1) { | ||||
+ long nfr = 0; | |||||
+ | |||||
+ pthread_mutex_lock(&s->mtx); | + pthread_mutex_lock(&s->mtx); | ||||
+ if (!s->running || s->destroying) { | + if (!s->running || s->destroying) { | ||||
+ pthread_mutex_unlock(&s->mtx); | + pthread_mutex_unlock(&s->mtx); | ||||
+ state = CUBEB_STATE_STOPPED; | + state = CUBEB_STATE_STOPPED; | ||||
+ break; | + break; | ||||
+ } | + } | ||||
+ pthread_mutex_unlock(&s->mtx); | + pthread_mutex_unlock(&s->mtx); | ||||
+ if (s->play.fd == -1 && s->record.fd == -1) { | + if (s->play.fd == -1 && s->record.fd == -1) { | ||||
+ /* | + /* | ||||
+ * Stop here if the stream is not play & record stream, | + * Stop here if the stream is not play & record stream, | ||||
+ * play-only stream or record-only stream | + * play-only stream or record-only stream | ||||
+ */ | + */ | ||||
+ | + | ||||
+ state = CUBEB_STATE_STOPPED; | + state = CUBEB_STATE_STOPPED; | ||||
+ break; | + break; | ||||
+ } | + } | ||||
+ | + | ||||
+ while ((s->bufframes - ppending) >= s->nfr && rpending >= s->nfr) { | |||||
+ long n = ((s->bufframes - ppending) < rpending) ? s->bufframes - ppending : rpending; | |||||
+ char *rptr = NULL, *pptr = NULL; | |||||
+ if (s->record.fd != -1) | |||||
+ rptr = (char *)s->record.buf; | |||||
+ if (s->play.fd != -1) | |||||
+ pptr = (char *)s->play.buf + ppending * s->play.frame_size; | |||||
+ if (s->record.fd != -1 && s->record.floating) { | + if (s->record.fd != -1 && s->record.floating) { | ||||
+ oss_linear32_to_float(s->record.buf, s->record.info.channels * s->nfr); | + oss_linear32_to_float(s->record.buf, s->record.info.channels * n); | ||||
+ } | + } | ||||
+ if (cbready) { | + nfr = s->data_cb(s, s->user_ptr, rptr, pptr, n); | ||||
+ nfr = s->data_cb(s, s->user_ptr, s->record.buf, s->play.buf, s->nfr); | |||||
+ if (nfr == CUBEB_ERROR) { | + if (nfr == CUBEB_ERROR) { | ||||
+ state = CUBEB_STATE_ERROR; | + state = CUBEB_STATE_ERROR; | ||||
+ goto out; | + goto out; | ||||
+ } | + } | ||||
+ cbready = false; | + if (pptr) { | ||||
+ } | |||||
+ if (s->play.fd != -1) { | |||||
+ float vol; | + float vol; | ||||
+ | + | ||||
+ pthread_mutex_lock(&s->mtx); | + pthread_mutex_lock(&s->mtx); | ||||
+ vol = s->volume; | + vol = s->volume; | ||||
+ pthread_mutex_unlock(&s->mtx); | + pthread_mutex_unlock(&s->mtx); | ||||
+ | + | ||||
+ if (s->play.floating) { | + if (s->play.floating) { | ||||
+ oss_float_to_linear32(s->play.buf, s->play.info.channels * nfr, vol); | + oss_float_to_linear32(pptr, s->play.info.channels * nfr, vol); | ||||
+ } else { | + } else { | ||||
+ oss_linear16_set_vol(s->play.buf, s->play.info.channels * nfr, vol); | + oss_linear16_set_vol((int16_t *)pptr, s->play.info.channels * nfr, vol); | ||||
+ } | + } | ||||
+ } | + } | ||||
+ if (nfr < (long)s->nfr) { | + if (pptr) { | ||||
+ ppending += nfr; | |||||
+ assert(ppending <= s->bufframes); | |||||
+ } | |||||
+ if (rptr) { | |||||
+ assert(rpending >= nfr); | |||||
+ rpending -= nfr; | |||||
+ memmove(rptr, rptr + nfr * s->record.frame_size, | |||||
+ (s->bufframes - nfr) * s->record.frame_size); | |||||
+ } | |||||
+ if (nfr < n) { | |||||
+ if (s->play.fd != -1) { | + if (s->play.fd != -1) { | ||||
+ drain = 1; | + drain = 1; | ||||
+ break; | |||||
+ } else { | + } else { | ||||
+ /* | + /* | ||||
+ * This is a record-only stream and number of frames | + * This is a record-only stream and number of frames | ||||
+ * returned from data_cb() is smaller than number | + * returned from data_cb() is smaller than number | ||||
+ * of frames required to read. Stop here. | + * of frames required to read. Stop here. | ||||
+ */ | + */ | ||||
+ | + | ||||
+ state = CUBEB_STATE_STOPPED; | + state = CUBEB_STATE_STOPPED; | ||||
+ break; | + goto out; | ||||
+ } | + } | ||||
+ } | + } | ||||
+ } | |||||
+ | + | ||||
+ size_t to_write = s->play.fd != -1 ? nfr : 0; | |||||
+ size_t to_read = s->record.fd != -1 ? s->nfr : 0; | |||||
+ size_t write_ofs = 0; | |||||
+ size_t read_ofs = 0; | |||||
+ while (to_write > 0 || to_read > 0) { | |||||
+ size_t bytes; | |||||
+ ssize_t n, frames; | + ssize_t n, frames; | ||||
+ int nfds; | + int nfds; | ||||
+ | + | ||||
+ pfds[0].revents = 0; | + pfds[0].revents = 0; | ||||
+ pfds[1].revents = 0; | + pfds[1].revents = 0; | ||||
+ | + | ||||
+ nfds = poll(pfds, 2, 1000); | + nfds = poll(pfds, 2, 1000); | ||||
+ if (nfds == -1) { | + if (nfds == -1) { | ||||
+ if (errno == EINTR) | + if (errno == EINTR) | ||||
+ continue; | + continue; | ||||
+ LOG("Error %d occured when polling playback and record fd", errno); | + LOG("Error %d occured when polling playback and record fd", errno); | ||||
+ state = CUBEB_STATE_ERROR; | + state = CUBEB_STATE_ERROR; | ||||
+ goto out; | + goto out; | ||||
+ } else if (nfds == 0) | + } else if (nfds == 0) | ||||
+ continue; | + continue; | ||||
+ | + | ||||
+ if ((pfds[0].revents & (POLLERR | POLLHUP)) || | + if ((pfds[0].revents & (POLLERR | POLLHUP)) || | ||||
+ (pfds[1].revents & (POLLERR | POLLHUP))) { | + (pfds[1].revents & (POLLERR | POLLHUP))) { | ||||
+ LOG("Error occured on playback, record fds"); | + LOG("Error occured on playback, record fds"); | ||||
+ state = CUBEB_STATE_ERROR; | + state = CUBEB_STATE_ERROR; | ||||
+ goto out; | + goto out; | ||||
+ } | + } | ||||
+ | + | ||||
+ if (to_write > 0 && pfds[0].revents) { | + if (pfds[0].revents) { | ||||
+ bytes = to_write * s->play.frame_size; | + while (ppending > 0) { | ||||
+ if ((n = write(s->play.fd, (uint8_t *)s->play.buf + write_ofs, bytes)) < 0) { | + size_t bytes = ppending * s->play.frame_size; | ||||
+ if ((n = write(s->play.fd, (uint8_t *)s->play.buf, bytes)) < 0) { | |||||
+ if (errno == EINTR) | |||||
+ continue; | |||||
+ if (errno == EAGAIN) { | |||||
+ if (drain) | |||||
+ continue; | |||||
+ break; | |||||
+ } | |||||
+ state = CUBEB_STATE_ERROR; | + state = CUBEB_STATE_ERROR; | ||||
+ goto out; | + goto out; | ||||
+ } | + } | ||||
+ frames = n / s->play.frame_size; | + frames = n / s->play.frame_size; | ||||
+ pthread_mutex_lock(&s->mtx); | + pthread_mutex_lock(&s->mtx); | ||||
+ s->frames_written += frames; | + s->frames_written += frames; | ||||
+ pthread_mutex_unlock(&s->mtx); | + pthread_mutex_unlock(&s->mtx); | ||||
+ to_write -= frames; | + ppending -= frames; | ||||
+ write_ofs += n; | + memmove(s->play.buf, (uint8_t *)s->play.buf + n, | ||||
+ (s->bufframes - frames) * s->play.frame_size); | |||||
+ } | + } | ||||
+ if (to_read > 0 && pfds[1].revents) { | + } | ||||
+ bytes = to_read * s->record.frame_size; | + if (pfds[1].revents) { | ||||
+ if ((n = read(s->record.fd, (uint8_t *)s->record.buf + read_ofs, | + while (s->bufframes - rpending > 0) { | ||||
+ bytes)) < 0) { | + size_t bytes = (s->bufframes - rpending) * s->record.frame_size; | ||||
+ size_t read_ofs = rpending * s->record.frame_size; | |||||
+ if ((n = read(s->record.fd, (uint8_t *)s->record.buf + read_ofs, bytes)) < 0) { | |||||
+ if (errno == EINTR) | |||||
+ continue; | |||||
+ if (errno == EAGAIN) | |||||
+ break; | |||||
+ state = CUBEB_STATE_ERROR; | + state = CUBEB_STATE_ERROR; | ||||
+ goto out; | + goto out; | ||||
+ } | + } | ||||
+ frames = n / s->record.frame_size; | + frames = n / s->record.frame_size; | ||||
+ to_read -= frames; | + rpending += frames; | ||||
+ read_ofs += n; | |||||
+ } | + } | ||||
+ } | + } | ||||
+ if (drain) { | + if (drain) { | ||||
+ state = CUBEB_STATE_DRAINED; | + state = CUBEB_STATE_DRAINED; | ||||
+ break; | + break; | ||||
+ } | + } | ||||
+ cbready = true; | |||||
+ } | + } | ||||
+ | + | ||||
+out: | +out: | ||||
+ return state; | + return state; | ||||
+} | +} | ||||
+ | + | ||||
+static void * | +static void * | ||||
+oss_io_routine(void *arg) | +oss_io_routine(void *arg) | ||||
+{ | +{ | ||||
+ cubeb_stream *s = arg; | + cubeb_stream *s = arg; | ||||
+ cubeb_state state = CUBEB_STATE_STARTED; | + cubeb_state state = CUBEB_STATE_STARTED; | ||||
+ | + | ||||
+ do { | + do { | ||||
+ pthread_mutex_lock(&s->mtx); | + pthread_mutex_lock(&s->mtx); | ||||
+ if (s->destroying) { | + if (s->destroying) { | ||||
+ pthread_mutex_unlock(&s->mtx); | + pthread_mutex_unlock(&s->mtx); | ||||
+ break; | + break; | ||||
+ } | + } | ||||
+ pthread_mutex_unlock(&s->mtx); | + pthread_mutex_unlock(&s->mtx); | ||||
+ | + | ||||
+ state = CUBEB_STATE_STARTED; | |||||
+ s->state_cb(s, s->user_ptr, state); | + s->state_cb(s, s->user_ptr, state); | ||||
+ | + | ||||
+ state = oss_audio_loop(s); | + state = oss_audio_loop(s); | ||||
+ assert(state != CUBEB_STATE_STARTED); | + assert(state != CUBEB_STATE_STARTED); | ||||
+ | + | ||||
+ if (s->record.fd != -1) | + if (s->record.fd != -1) | ||||
+ ioctl(s->record.fd, SNDCTL_DSP_HALT_INPUT, NULL); | + ioctl(s->record.fd, SNDCTL_DSP_HALT_INPUT, NULL); | ||||
+ s->state_cb(s, s->user_ptr, state); | + s->state_cb(s, s->user_ptr, state); | ||||
Show All 16 Lines | |||||
+ pthread_mutex_unlock(&s->mtx); | + pthread_mutex_unlock(&s->mtx); | ||||
+ return NULL; | + return NULL; | ||||
+} | +} | ||||
+ | + | ||||
+static inline int | +static inline int | ||||
+oss_calc_frag_shift(unsigned int frames, unsigned int frame_size) | +oss_calc_frag_shift(unsigned int frames, unsigned int frame_size) | ||||
+{ | +{ | ||||
+ int n = 4; | + int n = 4; | ||||
+ int blksize = (frames * frame_size + 4 - 1) / 4; | + int blksize = (frames * frame_size + OSS_NFRAGS - 1) / OSS_NFRAGS; | ||||
+ while ((1 << n) < blksize) | + while ((1 << n) < blksize) | ||||
+ n++; | + n++; | ||||
+ return n; | + return n; | ||||
+} | +} | ||||
+ | + | ||||
+static inline int | +static inline int | ||||
+oss_get_frag_params(unsigned int shift) | +oss_get_frag_params(unsigned int shift) | ||||
+{ | +{ | ||||
+ return (8 << 16) | shift; | + return (OSS_NFRAGS << 16) | shift; | ||||
+} | +} | ||||
+ | + | ||||
+static int | +static int | ||||
+oss_stream_init(cubeb * context, | +oss_stream_init(cubeb * context, | ||||
+ cubeb_stream ** stream, | + cubeb_stream ** stream, | ||||
+ char const * stream_name, | + char const * stream_name, | ||||
+ cubeb_devid input_device, | + cubeb_devid input_device, | ||||
+ cubeb_stream_params * input_stream_params, | + cubeb_stream_params * input_stream_params, | ||||
Show All 39 Lines | |||||
+ nb_channels = cubeb_channel_layout_nb_channels(input_stream_params->layout); | + nb_channels = cubeb_channel_layout_nb_channels(input_stream_params->layout); | ||||
+ if (input_stream_params->layout != CUBEB_LAYOUT_UNDEFINED && | + if (input_stream_params->layout != CUBEB_LAYOUT_UNDEFINED && | ||||
+ nb_channels != input_stream_params->channels) { | + nb_channels != input_stream_params->channels) { | ||||
+ LOG("input_stream_params->layout does not match input_stream_params->channels"); | + LOG("input_stream_params->layout does not match input_stream_params->channels"); | ||||
+ ret = CUBEB_ERROR_INVALID_PARAMETER; | + ret = CUBEB_ERROR_INVALID_PARAMETER; | ||||
+ goto error; | + goto error; | ||||
+ } | + } | ||||
+ if (s->record.fd == -1) { | + if (s->record.fd == -1) { | ||||
+ if ((s->record.fd = open(s->record.name, O_RDONLY)) == -1) { | + if ((s->record.fd = open(s->record.name, O_RDONLY | O_NONBLOCK)) == -1) { | ||||
+ LOG("Audio device \"%s\" could not be opened as read-only", | + LOG("Audio device \"%s\" could not be opened as read-only", | ||||
+ s->record.name); | + s->record.name); | ||||
+ ret = CUBEB_ERROR_DEVICE_UNAVAILABLE; | + ret = CUBEB_ERROR_DEVICE_UNAVAILABLE; | ||||
+ goto error; | + goto error; | ||||
+ } | + } | ||||
+ } | + } | ||||
+ if ((ret = oss_copy_params(s->record.fd, s, input_stream_params, | + if ((ret = oss_copy_params(s->record.fd, s, input_stream_params, | ||||
+ &s->record.info)) != CUBEB_OK) { | + &s->record.info)) != CUBEB_OK) { | ||||
Show All 14 Lines | |||||
+ nb_channels = cubeb_channel_layout_nb_channels(output_stream_params->layout); | + nb_channels = cubeb_channel_layout_nb_channels(output_stream_params->layout); | ||||
+ if (output_stream_params->layout != CUBEB_LAYOUT_UNDEFINED && | + if (output_stream_params->layout != CUBEB_LAYOUT_UNDEFINED && | ||||
+ nb_channels != output_stream_params->channels) { | + nb_channels != output_stream_params->channels) { | ||||
+ LOG("output_stream_params->layout does not match output_stream_params->channels"); | + LOG("output_stream_params->layout does not match output_stream_params->channels"); | ||||
+ ret = CUBEB_ERROR_INVALID_PARAMETER; | + ret = CUBEB_ERROR_INVALID_PARAMETER; | ||||
+ goto error; | + goto error; | ||||
+ } | + } | ||||
+ if (s->play.fd == -1) { | + if (s->play.fd == -1) { | ||||
+ if ((s->play.fd = open(s->play.name, O_WRONLY)) == -1) { | + if ((s->play.fd = open(s->play.name, O_WRONLY | O_NONBLOCK)) == -1) { | ||||
+ LOG("Audio device \"%s\" could not be opened as write-only", | + LOG("Audio device \"%s\" could not be opened as write-only", | ||||
+ s->play.name); | + s->play.name); | ||||
+ ret = CUBEB_ERROR_DEVICE_UNAVAILABLE; | + ret = CUBEB_ERROR_DEVICE_UNAVAILABLE; | ||||
+ goto error; | + goto error; | ||||
+ } | + } | ||||
+ } | + } | ||||
+ if ((ret = oss_copy_params(s->play.fd, s, output_stream_params, | + if ((ret = oss_copy_params(s->play.fd, s, output_stream_params, | ||||
+ &s->play.info)) != CUBEB_OK) { | + &s->play.info)) != CUBEB_OK) { | ||||
+ LOG("Setting play params failed"); | + LOG("Setting play params failed"); | ||||
+ goto error; | + goto error; | ||||
+ } | + } | ||||
+ s->play.floating = (output_stream_params->format == CUBEB_SAMPLE_FLOAT32NE); | + s->play.floating = (output_stream_params->format == CUBEB_SAMPLE_FLOAT32NE); | ||||
+ s->play.frame_size = s->play.info.channels * (s->play.info.precision / 8); | + s->play.frame_size = s->play.info.channels * (s->play.info.precision / 8); | ||||
+ playnfr = (1 << oss_calc_frag_shift(s->nfr, s->play.frame_size)) / s->play.frame_size; | + playnfr = (1 << oss_calc_frag_shift(s->nfr, s->play.frame_size)) / s->play.frame_size; | ||||
+ } | + } | ||||
+ /* Use the largest nframes among playing and recording streams */ | + /* Use the largest nframes among playing and recording streams */ | ||||
+ s->nfr = (playnfr > recnfr) ? playnfr : recnfr; | + s->nfr = (playnfr > recnfr) ? playnfr : recnfr; | ||||
+ s->nfrags = OSS_NFRAGS; | |||||
+ s->bufframes = s->nfr * s->nfrags; | |||||
+ if (s->play.fd != -1) { | + if (s->play.fd != -1) { | ||||
+ int frag = oss_get_frag_params(oss_calc_frag_shift(s->nfr, s->play.frame_size)); | + int frag = oss_get_frag_params(oss_calc_frag_shift(s->nfr, s->play.frame_size)); | ||||
+ if (ioctl(s->record.fd, SNDCTL_DSP_SETFRAGMENT, &frag)) | + if (ioctl(s->record.fd, SNDCTL_DSP_SETFRAGMENT, &frag)) | ||||
+ LOG("Failed to set record fd with SNDCTL_DSP_SETFRAGMENT. frag: 0x%x", | + LOG("Failed to set record fd with SNDCTL_DSP_SETFRAGMENT. frag: 0x%x", | ||||
+ frag); | + frag); | ||||
+ } | + } | ||||
+ if (s->record.fd != -1) { | + if (s->record.fd != -1) { | ||||
+ int frag = oss_get_frag_params(oss_calc_frag_shift(s->nfr, s->record.frame_size)); | + int frag = oss_get_frag_params(oss_calc_frag_shift(s->nfr, s->record.frame_size)); | ||||
Show All 16 Lines | |||||
+ goto error; | + goto error; | ||||
+ } | + } | ||||
+ if (pthread_cond_init(&s->stopped_cv, NULL) != 0) { | + if (pthread_cond_init(&s->stopped_cv, NULL) != 0) { | ||||
+ LOG("Failed to create cv"); | + LOG("Failed to create cv"); | ||||
+ goto error; | + goto error; | ||||
+ } | + } | ||||
+ | + | ||||
+ if (s->play.fd != -1) { | + if (s->play.fd != -1) { | ||||
+ if ((s->play.buf = calloc(s->nfr, s->play.frame_size)) == NULL) { | + if ((s->play.buf = calloc(s->bufframes, s->play.frame_size)) == NULL) { | ||||
+ ret = CUBEB_ERROR; | + ret = CUBEB_ERROR; | ||||
+ goto error; | + goto error; | ||||
+ } | + } | ||||
+ } | + } | ||||
+ if (s->record.fd != -1) { | + if (s->record.fd != -1) { | ||||
+ if ((s->record.buf = calloc(s->nfr, s->record.frame_size)) == NULL) { | + if ((s->record.buf = calloc(s->bufframes, s->record.frame_size)) == NULL) { | ||||
+ ret = CUBEB_ERROR; | + ret = CUBEB_ERROR; | ||||
+ goto error; | + goto error; | ||||
+ } | + } | ||||
+ } | + } | ||||
+ | + | ||||
+ *stream = s; | + *stream = s; | ||||
+ return CUBEB_OK; | + return CUBEB_OK; | ||||
+error: | +error: | ||||
+ if (s != NULL) { | + if (s != NULL) { | ||||
+ oss_stream_destroy(s); | + oss_stream_destroy(s); | ||||
+ } | + } | ||||
+ return ret; | + return ret; | ||||
+} | +} | ||||
+ | + | ||||
+static int | +static int | ||||
+oss_stream_thr_create(cubeb_stream * s) | +oss_stream_thr_create(cubeb_stream * s) | ||||
+{ | +{ | ||||
+ if (s->thread_created) { | + if (s->thread_created) { | ||||
+ pthread_mutex_lock(&s->mtx); | |||||
+ pthread_cond_signal(&s->doorbell_cv); | + pthread_cond_signal(&s->doorbell_cv); | ||||
+ pthread_mutex_unlock(&s->mtx); | |||||
+ | |||||
+ return CUBEB_OK; | + return CUBEB_OK; | ||||
+ } | + } | ||||
+ | + | ||||
+ if (pthread_create(&s->thread, NULL, oss_io_routine, s) != 0) { | + if (pthread_create(&s->thread, NULL, oss_io_routine, s) != 0) { | ||||
+ LOG("Couldn't create thread"); | + LOG("Couldn't create thread"); | ||||
+ return CUBEB_ERROR; | + return CUBEB_ERROR; | ||||
+ } | + } | ||||
+ | + | ||||
▲ Show 20 Lines • Show All 99 Lines • Show Last 20 Lines |