summaryrefslogtreecommitdiffstats
path: root/audio/libcanberra/files/patch-src_oss.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/libcanberra/files/patch-src_oss.c')
-rw-r--r--audio/libcanberra/files/patch-src_oss.c502
1 files changed, 10 insertions, 492 deletions
diff --git a/audio/libcanberra/files/patch-src_oss.c b/audio/libcanberra/files/patch-src_oss.c
index c8eef31b9..5b478d22c 100644
--- a/audio/libcanberra/files/patch-src_oss.c
+++ b/audio/libcanberra/files/patch-src_oss.c
@@ -1,493 +1,11 @@
---- src/oss.c.orig 2008-08-20 16:49:01.916312000 -0400
-+++ src/oss.c 2008-08-20 16:49:58.000000000 -0400
-@@ -0,0 +1,490 @@
-+/***
-+ This file is part of libcanberra.
-+
-+ Copyright 2008 Lennart Poettering
-+ Joe Marcus Clarke
-+
-+ libcanberra is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU Lesser General Public License as
-+ published by the Free Software Foundation, either version 2.1 of the
-+ License, or (at your option) any later version.
-+
-+ libcanberra is distributed in the hope that it will be useful, but
-+ WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with libcanberra. If not, If not, see
-+ <http://www.gnu.org/licenses/>.
-+***/
-+
-+#ifdef HAVE_CONFIG_H
-+#include <config.h>
-+#endif
-+
-+#include <sys/types.h>
-+#include <sys/ioctl.h>
-+#include <sys/uio.h>
-+#include <math.h>
-+#include <unistd.h>
-+
-+#ifdef HAVE_MACHINE_SOUNDCARD_H
-+# include <machine/soundcard.h>
-+#else
-+# ifdef HAVE_SOUNDCARD_H
-+# include <soundcard.h>
-+# else
-+# include <sys/soundcard.h>
-+# endif
-+#endif
-+
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <stdlib.h>
-+#include <poll.h>
-+#include <pthread.h>
-+#include <semaphore.h>
-+
-+#include "canberra.h"
-+#include "common.h"
-+#include "driver.h"
-+#include "llist.h"
-+#include "read-sound-file.h"
-+#include "sound-theme-spec.h"
-+#include "malloc.h"
-+
-+struct private;
-+
-+struct outstanding {
-+ CA_LLIST_FIELDS(struct outstanding);
-+ ca_bool_t dead;
-+ uint32_t id;
-+ ca_finish_callback_t callback;
-+ void *userdata;
-+ ca_sound_file *file;
-+ int pcm;
-+ int pipe_fd[2];
-+ ca_context *context;
-+};
-+
-+struct private {
-+ ca_theme_data *theme;
-+ ca_mutex *outstanding_mutex;
-+ ca_bool_t signal_semaphore;
-+ sem_t semaphore;
-+ ca_bool_t semaphore_allocated;
-+ CA_LLIST_HEAD(struct outstanding, outstanding);
-+};
-+
-+#define PRIVATE(c) ((struct private *) ((c)->private))
-+
-+static void outstanding_free(struct outstanding *o) {
-+ ca_assert(o);
-+
-+ if (o->pipe_fd[1] >= 0)
-+ close(o->pipe_fd[1]);
-+
-+ if (o->pipe_fd[0] >= 0)
-+ close(o->pipe_fd[0]);
-+
-+ if (o->file)
-+ ca_sound_file_close(o->file);
-+
-+ if (o->pcm > -1) {
-+ close(o->pcm);
-+ o->pcm = -1;
-+ }
-+
-+ ca_free(o);
-+}
-+
-+int driver_open(ca_context *c) {
-+ struct private *p;
-+
-+ ca_return_val_if_fail(c, CA_ERROR_INVALID);
-+ ca_return_val_if_fail(!c->driver || ca_streq(c->driver, "oss"), CA_ERROR_NODRIVER);
-+ ca_return_val_if_fail(!PRIVATE(c), CA_ERROR_STATE);
-+
-+ if (!(c->private = p = ca_new0(struct private, 1)))
-+ return CA_ERROR_OOM;
-+
-+ if (!(p->outstanding_mutex = ca_mutex_new())) {
-+ driver_destroy(c);
-+ return CA_ERROR_OOM;
-+ }
-+
-+ if (sem_init(&p->semaphore, 0, 0) < 0) {
-+ driver_destroy(c);
-+ return CA_ERROR_OOM;
-+ }
-+
-+ p->semaphore_allocated = TRUE;
-+
-+ return CA_SUCCESS;
-+}
-+
-+int driver_destroy(ca_context *c) {
-+ struct private *p;
-+ struct outstanding *out;
-+
-+ ca_return_val_if_fail(c, CA_ERROR_INVALID);
-+ ca_return_val_if_fail(c->private, CA_ERROR_STATE);
-+
-+ p = PRIVATE(c);
-+
-+ if (p->outstanding_mutex) {
-+ ca_mutex_lock(p->outstanding_mutex);
-+
-+ /* Tell all player threads to terminate */
-+ for (out = p->outstanding; out; out = out->next) {
-+
-+ if (out->dead)
-+ continue;
-+
-+ out->dead = TRUE;
-+
-+ if (out->callback)
-+ out->callback(c, out->id, CA_ERROR_DESTROYED, out->userdata);
-+
-+ /* This will cause the thread to wakeup and terminate */
-+ if (out->pipe_fd[1] >= 0) {
-+ close(out->pipe_fd[1]);
-+ out->pipe_fd[1] = -1;
-+ }
-+ }
-+
-+ if (p->semaphore_allocated) {
-+ /* Now wait until all players are destroyed */
-+ p->signal_semaphore = TRUE;
-+ while (p->outstanding) {
-+ ca_mutex_unlock(p->outstanding_mutex);
-+ sem_wait(&p->semaphore);
-+ ca_mutex_lock(p->outstanding_mutex);
-+ }
-+ }
-+
-+ ca_mutex_unlock(p->outstanding_mutex);
-+ ca_mutex_free(p->outstanding_mutex);
-+ }
-+
-+ if (p->theme)
-+ ca_theme_data_free(p->theme);
-+
-+ if (p->semaphore_allocated)
-+ sem_destroy(&p->semaphore);
-+
-+ ca_free(p);
-+
-+ c->private = NULL;
-+
-+ return CA_SUCCESS;
-+}
-+
-+int driver_change_device(ca_context *c, char *device) {
-+ ca_return_val_if_fail(c, CA_ERROR_INVALID);
-+ ca_return_val_if_fail(c->private, CA_ERROR_STATE);
-+
-+ return CA_SUCCESS;
-+}
-+
-+int driver_change_props(ca_context *c, ca_proplist *changed, ca_proplist *merged) {
-+ ca_return_val_if_fail(c, CA_ERROR_INVALID);
-+ ca_return_val_if_fail(changed, CA_ERROR_INVALID);
-+ ca_return_val_if_fail(merged, CA_ERROR_INVALID);
-+
-+ return CA_SUCCESS;
-+}
-+
-+int driver_cache(ca_context *c, ca_proplist *proplist) {
-+ ca_return_val_if_fail(c, CA_ERROR_INVALID);
-+ ca_return_val_if_fail(proplist, CA_ERROR_INVALID);
-+
-+ return CA_ERROR_NOTSUPPORTED;
-+}
-+
-+static int translate_error(int error) {
-+
-+ switch (error) {
-+ case ENODEV:
-+ case ENOENT:
-+ return CA_ERROR_NOTFOUND;
-+ case EACCES:
-+ case EPERM:
-+ return CA_ERROR_ACCESS;
-+ case ENOMEM:
-+ return CA_ERROR_OOM;
-+ case EBUSY:
-+ return CA_ERROR_NOTAVAILABLE;
-+ case EINVAL:
-+ return CA_ERROR_INVALID;
-+ default:
-+ if (ca_debug())
-+ fprintf(stderr, "Got unhandled error from OSS: %s\n", strerror(error));
-+ return CA_ERROR_IO;
-+ }
-+}
-+
-+static int open_oss(ca_context *c, struct outstanding *out) {
-+ struct private *p;
-+ int mode;
-+ int val;
-+ int test;
-+ int ret;
-+
-+ ca_return_val_if_fail(c, CA_ERROR_INVALID);
-+ ca_return_val_if_fail(c->private, CA_ERROR_STATE);
-+ ca_return_val_if_fail(out, CA_ERROR_INVALID);
-+
-+ p = PRIVATE(c);
-+
-+ if ((out->pcm = open(c->device ? c->device : "/dev/dsp", O_WRONLY | O_NONBLOCK, 0)) < 0)
-+ goto finish;
-+
-+ if ((mode = fcntl(out->pcm, F_GETFL)) < 0) {
-+ goto finish;
-+ }
-+ mode &= ~O_NONBLOCK;
-+ if (fcntl(out->pcm, F_SETFL, mode) < 0) {
-+ goto finish;
-+ }
-+
-+ switch (ca_sound_file_get_sample_type(out->file)) {
-+ case CA_SAMPLE_U8:
-+ val = AFMT_U8;
-+ break;
-+ case CA_SAMPLE_S16NE:
-+ val = AFMT_S16_NE;
-+ break;
-+ case CA_SAMPLE_S16RE:
+--- src/oss.c.orig 2008-09-07 12:54:12.000000000 -0400
++++ src/oss.c 2008-09-07 12:54:18.000000000 -0400
+@@ -258,7 +258,7 @@ static int open_oss(ca_context *c, struc
+ val = AFMT_S16_NE;
+ break;
+ case CA_SAMPLE_S16RE:
+-#if __BYTE_ORDER == __LITTLE_ENDIAN
+#if _BYTE_ORDER == _LITTLE_ENDIAN
-+ val = AFMT_S16_BE;
-+#else
-+ val = AFMT_S16_LE;
-+#endif
-+ break;
-+ }
-+
-+ test = val;
-+ if (ioctl(out->pcm, SNDCTL_DSP_SETFMT, &val) < 0)
-+ goto finish;
-+
-+ if (val != test) {
-+ errno = EINVAL;
-+ goto finish;
-+ }
-+
-+ val = ca_sound_file_get_nchannels(out->file);
-+ if (ioctl(out->pcm, SNDCTL_DSP_CHANNELS, &val) < 0)
-+ goto finish;
-+
-+ val = test = ca_sound_file_get_rate(out->file);
-+ if (ioctl(out->pcm, SNDCTL_DSP_SPEED, &val) < 0)
-+ goto finish;
-+
-+ /* Taken from esound. Check to make sure the configured rate is close
-+ * enough to the requested rate.
-+ */
-+ if (fabs((double) (val - test)) > test * 0.05) {
-+ errno = EINVAL;
-+ goto finish;
-+ }
-+
-+ return CA_SUCCESS;
-+
-+finish:
-+
-+ ret = errno;
-+ close(out->pcm);
-+ out->pcm = -1;
-+ return translate_error(ret);
-+}
-+
-+#define BUFSIZE (4*1024)
-+
-+static void* thread_func(void *userdata) {
-+ struct outstanding *out = userdata;
-+ int ret;
-+ void *data, *d = NULL;
-+ ssize_t bytes_written;
-+ size_t fs, data_size;
-+ size_t nbytes = 0;
-+ struct pollfd pfd[2];
-+ nfds_t n_pfd = 2;
-+ struct private *p;
-+
-+ p = PRIVATE(out->context);
-+
-+ pthread_detach(pthread_self());
-+
-+ fs = ca_sound_file_frame_size(out->file);
-+ data_size = (BUFSIZE/fs)*fs;
-+
-+ if (!(data = ca_malloc(data_size))) {
-+ ret = CA_ERROR_OOM;
-+ goto finish;
-+ }
-+
-+ pfd[0].fd = out->pipe_fd[0];
-+ pfd[0].events = POLLIN;
-+ pfd[0].revents = 0;
-+ pfd[1].fd = out->pcm;
-+ pfd[1].events = POLLOUT;
-+ pfd[1].revents = 0;
-+
-+ for (;;) {
-+ if (out->dead)
-+ break;
-+
-+ if (poll(pfd, n_pfd, -1) < 0) {
-+ ret = CA_ERROR_SYSTEM;
-+ goto finish;
-+ }
-+
-+ /* We have been asked to shut down */
-+ if (pfd[0].revents)
-+ break;
-+
-+ if (nbytes <= 0) {
-+
-+ nbytes = data_size;
-+
-+ if ((ret = ca_sound_file_read_arbitrary(out->file, data, &nbytes)) < 0)
-+ goto finish;
-+
-+ d = data;
-+ }
-+
-+ if (nbytes <= 0) {
-+ break;
-+ }
-+
-+ if ((bytes_written = write(out->pcm, d, nbytes)) <= 0) {
-+ ret = errno;
-+ goto finish;
-+ }
-+
-+ nbytes -= bytes_written;
-+ d = (uint8_t*) d + bytes_written;
-+ }
-+
-+ ret = CA_SUCCESS;
-+
-+finish:
-+
-+ ca_free(data);
-+
-+ if (!out->dead)
-+ if (out->callback)
-+ out->callback(out->context, out->id, ret, out->userdata);
-+
-+ ca_mutex_lock(p->outstanding_mutex);
-+
-+ CA_LLIST_REMOVE(struct outstanding, p->outstanding, out);
-+
-+ if (!p->outstanding && p->signal_semaphore)
-+ sem_post(&p->semaphore);
-+
-+ outstanding_free(out);
-+
-+ ca_mutex_unlock(p->outstanding_mutex);
-+
-+ return NULL;
-+}
-+
-+int driver_play(ca_context *c, uint32_t id, ca_proplist *proplist, ca_finish_callback_t cb, void *userdata) {
-+ struct private *p;
-+ struct outstanding *out = NULL;
-+ int ret;
-+ pthread_t thread;
-+
-+ ca_return_val_if_fail(c, CA_ERROR_INVALID);
-+ ca_return_val_if_fail(proplist, CA_ERROR_INVALID);
-+ ca_return_val_if_fail(!userdata || cb, CA_ERROR_INVALID);
-+ ca_return_val_if_fail(c->private, CA_ERROR_STATE);
-+
-+ p = PRIVATE(c);
-+
-+ if (!(out = ca_new0(struct outstanding, 1))) {
-+ ret = CA_ERROR_OOM;
-+ goto finish;
-+ }
-+
-+ out->context = c;
-+ out->id = id;
-+ out->callback = cb;
-+ out->userdata = userdata;
-+ out->pipe_fd[0] = out->pipe_fd[1] = -1;
-+
-+ if (pipe(out->pipe_fd) < 0) {
-+ ret = CA_ERROR_SYSTEM;
-+ goto finish;
-+ }
-+
-+ if ((ret = ca_lookup_sound(&out->file, &p->theme, c->props, proplist)) < 0)
-+ goto finish;
-+
-+ if ((ret = open_oss(c, out)) < 0)
-+ goto finish;
-+
-+ /* OK, we're ready to go, so let's add this to our list */
-+ ca_mutex_lock(p->outstanding_mutex);
-+ CA_LLIST_PREPEND(struct outstanding, p->outstanding, out);
-+ ca_mutex_unlock(p->outstanding_mutex);
-+
-+ if (pthread_create(&thread, NULL, thread_func, out) < 0) {
-+ ret = CA_ERROR_OOM;
-+
-+ ca_mutex_lock(p->outstanding_mutex);
-+ CA_LLIST_REMOVE(struct outstanding, p->outstanding, out);
-+ ca_mutex_unlock(p->outstanding_mutex);
-+
-+ goto finish;
-+ }
-+
-+ ret = CA_SUCCESS;
-+
-+finish:
-+
-+ /* We keep the outstanding struct around if we need clean up later to */
-+ if (ret != CA_SUCCESS)
-+ outstanding_free(out);
-+
-+ return ret;
-+}
-+
-+int driver_cancel(ca_context *c, uint32_t id) {
-+ struct private *p;
-+ struct outstanding *out;
-+
-+ ca_return_val_if_fail(c, CA_ERROR_INVALID);
-+ ca_return_val_if_fail(c->private, CA_ERROR_STATE);
-+
-+ p = PRIVATE(c);
-+
-+ ca_mutex_lock(p->outstanding_mutex);
-+
-+ for (out = p->outstanding; out; out = out->next) {
-+
-+ if (out->id != id)
-+ continue;
-+
-+ if (out->dead)
-+ continue;
-+
-+ out->dead = TRUE;
-+
-+ if (out->callback)
-+ out->callback(c, out->id, CA_ERROR_CANCELED, out->userdata);
-+
-+ /* This will cause the thread to wakeup and terminate */
-+ if (out->pipe_fd[1] >= 0) {
-+ close(out->pipe_fd[1]);
-+ out->pipe_fd[1] = -1;
-+ }
-+ }
-+
-+ ca_mutex_unlock(p->outstanding_mutex);
-+
-+ return CA_SUCCESS;
-+}
+ val = AFMT_S16_BE;
+ #else
+ val = AFMT_S16_LE;