Add sndio backend. It should allow guest operating systems with no
sndio support to use sndio audio interfaces of the host system. With help from brad@, ok sthen@.
This commit is contained in:
parent
3964fd72b2
commit
1d80b4a515
@ -1,4 +1,4 @@
|
||||
# $OpenBSD: Makefile,v 1.183 2018/12/19 17:57:06 sthen Exp $
|
||||
# $OpenBSD: Makefile,v 1.184 2019/05/09 05:12:53 ratchov Exp $
|
||||
|
||||
USE_WXNEEDED= Yes
|
||||
|
||||
@ -7,6 +7,7 @@ ONLY_FOR_ARCHS= aarch64 amd64 arm i386 powerpc sparc64
|
||||
COMMENT= multi system emulator
|
||||
|
||||
DISTNAME= qemu-3.1.0
|
||||
REVISION= 0
|
||||
CATEGORIES= emulators
|
||||
MASTER_SITES= https://download.qemu.org/
|
||||
EXTRACT_SUFX= .tar.xz
|
||||
@ -22,8 +23,8 @@ WANTLIB= SDL2 X11 atk-1.0 bz2 c cairo cairo-gobject capstone curl \
|
||||
epoxy fdt gbm gdk-3 gdk_pixbuf-2.0 gio-2.0 glib-2.0 gnutls \
|
||||
gobject-2.0 gthread-2.0 gtk-3 intl iscsi jpeg lzo2 m \
|
||||
curses nettle nfs pango-1.0 pangocairo-1.0 pcre2-8 \
|
||||
pixman-1 png ssh2 usb-1.0 util vte-2.91 xkbcommon xml2 z \
|
||||
${COMPILER_LIBCXX}
|
||||
pixman-1 png sndio ssh2 usb-1.0 util vte-2.91 xkbcommon \
|
||||
xml2 z ${COMPILER_LIBCXX}
|
||||
|
||||
# Using TLS emulation layer
|
||||
COMPILER = base-clang ports-gcc
|
||||
|
16
emulators/qemu/patches/patch-audio_Makefile_objs
Normal file
16
emulators/qemu/patches/patch-audio_Makefile_objs
Normal file
@ -0,0 +1,16 @@
|
||||
$OpenBSD: patch-audio_Makefile_objs,v 1.1 2019/05/09 05:12:53 ratchov Exp $
|
||||
|
||||
sndio module
|
||||
|
||||
Index: audio/Makefile.objs
|
||||
--- audio/Makefile.objs.orig
|
||||
+++ audio/Makefile.objs
|
||||
@@ -29,3 +29,8 @@ common-obj-$(CONFIG_AUDIO_SDL) += sdl.mo
|
||||
sdl.mo-objs = sdlaudio.o
|
||||
sdl.mo-cflags := $(SDL_CFLAGS)
|
||||
sdl.mo-libs := $(SDL_LIBS)
|
||||
+
|
||||
+# sndio module
|
||||
+common-obj-$(CONFIG_AUDIO_SNDIO) += sndio.mo
|
||||
+sndio.mo-objs = sndioaudio.o
|
||||
+sndio.mo-libs := $(SNDIO_LIBS)
|
552
emulators/qemu/patches/patch-audio_sndioaudio_c
Normal file
552
emulators/qemu/patches/patch-audio_sndioaudio_c
Normal file
@ -0,0 +1,552 @@
|
||||
$OpenBSD: patch-audio_sndioaudio_c,v 1.1 2019/05/09 05:12:53 ratchov Exp $
|
||||
|
||||
sndio module
|
||||
|
||||
Index: audio/sndioaudio.c
|
||||
--- audio/sndioaudio.c.orig
|
||||
+++ audio/sndioaudio.c
|
||||
@@ -0,0 +1,544 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2019 Alexandre Ratchov <alex@caoua.org>
|
||||
+ *
|
||||
+ * Permission to use, copy, modify, and distribute this software for any
|
||||
+ * purpose with or without fee is hereby granted, provided that the above
|
||||
+ * copyright notice and this permission notice appear in all copies.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * TODO :
|
||||
+ *
|
||||
+ * - Store device handle in a global variable and open it in full-duplex
|
||||
+ * rather than opening it twice. This is the only way to ensure
|
||||
+ * playback doesn't drift with respect to recording, which
|
||||
+ * is what guest systems expect.
|
||||
+ *
|
||||
+ * - Clarify whether hw->wpos can wrap, see sndio_run_in(). As we only
|
||||
+ * transfer one block at a time, hw->hwpos can't wrap, unless upper
|
||||
+ * layer skip samples.
|
||||
+ */
|
||||
+
|
||||
+#include <poll.h>
|
||||
+#include <sndio.h>
|
||||
+#include "qemu/osdep.h"
|
||||
+#include "qemu-common.h"
|
||||
+#include "qemu/main-loop.h"
|
||||
+#include "audio.h"
|
||||
+#include "trace.h"
|
||||
+
|
||||
+#define AUDIO_CAP "sndio"
|
||||
+#include "audio_int.h"
|
||||
+
|
||||
+typedef struct SndioVoice {
|
||||
+ union {
|
||||
+ HWVoiceOut out;
|
||||
+ HWVoiceIn in;
|
||||
+ } hw;
|
||||
+ struct sio_par par;
|
||||
+ struct sio_hdl *hdl;
|
||||
+ struct pollfd *pfds;
|
||||
+ struct pollindex {
|
||||
+ struct SndioVoice *self;
|
||||
+ int index;
|
||||
+ } *pindexes;
|
||||
+ unsigned char *buf;
|
||||
+ unsigned int bpf;
|
||||
+ unsigned int sndio_pos;
|
||||
+ unsigned int qemu_pos;
|
||||
+ unsigned int mode;
|
||||
+ unsigned int nfds;
|
||||
+} SndioVoice;
|
||||
+
|
||||
+typedef struct SndioConf {
|
||||
+ const char *devname;
|
||||
+ unsigned int latency;
|
||||
+} SndioConf;
|
||||
+
|
||||
+/* needed for forward reference */
|
||||
+static void sndio_poll_in(void *arg);
|
||||
+static void sndio_poll_out(void *arg);
|
||||
+
|
||||
+static SndioConf glob_conf = {
|
||||
+ .devname = SIO_DEVANY,
|
||||
+ .latency = 50
|
||||
+};
|
||||
+
|
||||
+static void sndio_poll_clear (SndioVoice *self)
|
||||
+{
|
||||
+ struct pollfd *pfd;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < self->nfds; i++) {
|
||||
+ pfd = &self->pfds[i];
|
||||
+ qemu_set_fd_handler (pfd->fd, NULL, NULL, NULL);
|
||||
+ }
|
||||
+
|
||||
+ self->nfds = 0;
|
||||
+}
|
||||
+
|
||||
+static void sndio_poll_wait(SndioVoice *self, int events)
|
||||
+{
|
||||
+ struct pollfd *pfd;
|
||||
+ int i;
|
||||
+
|
||||
+ /*
|
||||
+ * fill the given array of descriptors with the events sndio
|
||||
+ * wants, they are different from our 'event' variable because
|
||||
+ * sndio may use descriptors internally.
|
||||
+ */
|
||||
+ self->nfds = sio_pollfd (self->hdl, self->pfds, events);
|
||||
+
|
||||
+ for (i = 0; i < self->nfds; i++) {
|
||||
+ pfd = &self->pfds[i];
|
||||
+ if (pfd->fd < 0)
|
||||
+ continue;
|
||||
+ qemu_set_fd_handler (pfd->fd,
|
||||
+ (pfd->events & POLLIN) ? sndio_poll_in : NULL,
|
||||
+ (pfd->events & POLLOUT) ? sndio_poll_out : NULL,
|
||||
+ &self->pindexes[i]);
|
||||
+ pfd->revents = 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void sndio_write_do(SndioVoice *self)
|
||||
+{
|
||||
+ int todo, n;
|
||||
+
|
||||
+ todo = (self->qemu_pos * self->bpf) - self->sndio_pos;
|
||||
+
|
||||
+ /*
|
||||
+ * transfer data to device, until it blocks
|
||||
+ */
|
||||
+ while (todo > 0) {
|
||||
+ n = sio_write (self->hdl, self->buf + self->sndio_pos, todo);
|
||||
+ if (n == 0)
|
||||
+ break;
|
||||
+ self->sndio_pos += n;
|
||||
+ todo -= n;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * did we complete the block ?
|
||||
+ */
|
||||
+ if (todo == 0 && self->qemu_pos == self->par.round) {
|
||||
+ self->sndio_pos = 0;
|
||||
+ self->qemu_pos = 0;
|
||||
+ }
|
||||
+
|
||||
+ audio_run ("sndio_out");
|
||||
+}
|
||||
+
|
||||
+static void sndio_read_do(SndioVoice *self)
|
||||
+{
|
||||
+ int todo, n;
|
||||
+
|
||||
+ todo = (self->par.round * self->bpf) - self->sndio_pos;
|
||||
+
|
||||
+ /*
|
||||
+ * transfer data from the device, until it blocks
|
||||
+ */
|
||||
+ while (todo > 0) {
|
||||
+ n = sio_read (self->hdl, self->buf + self->sndio_pos, todo);
|
||||
+ if (n == 0)
|
||||
+ break;
|
||||
+ self->sndio_pos += n;
|
||||
+ todo -= n;
|
||||
+ }
|
||||
+
|
||||
+ audio_run ("sndio_in");
|
||||
+}
|
||||
+
|
||||
+static void sndio_poll_event (SndioVoice *self, int index, int event)
|
||||
+{
|
||||
+ int revents, todo;
|
||||
+
|
||||
+ /*
|
||||
+ * ensure we're not called twice this cycle
|
||||
+ */
|
||||
+ sndio_poll_clear (self);
|
||||
+
|
||||
+ /*
|
||||
+ * make self->pfds[] look as we're returning from poll syscal,
|
||||
+ * this is how sio_revents expects events to be.
|
||||
+ */
|
||||
+ self->pfds[index].revents = event;
|
||||
+
|
||||
+ /*
|
||||
+ * tell sndio to handle events and return whether we can read or
|
||||
+ * write without blocking.
|
||||
+ */
|
||||
+ revents = sio_revents (self->hdl, self->pfds);
|
||||
+ if (self->mode == SIO_PLAY) {
|
||||
+ if (revents & POLLOUT)
|
||||
+ sndio_write_do (self);
|
||||
+
|
||||
+ todo = (self->qemu_pos * self->bpf) - self->sndio_pos;
|
||||
+ sndio_poll_wait (self, todo > 0 ? POLLOUT : 0);
|
||||
+
|
||||
+ } else {
|
||||
+ if (revents & POLLIN)
|
||||
+ sndio_read_do (self);
|
||||
+
|
||||
+ todo = (self->par.round * self->bpf) - self->sndio_pos;
|
||||
+ sndio_poll_wait (self, todo > 0 ? POLLIN : 0);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void sndio_poll_in(void *arg)
|
||||
+{
|
||||
+ struct pollindex *pindex = (struct pollindex *) arg;
|
||||
+
|
||||
+ sndio_poll_event (pindex->self, pindex->index, POLLIN);
|
||||
+}
|
||||
+
|
||||
+static void sndio_poll_out(void *arg)
|
||||
+{
|
||||
+ struct pollindex *pindex = (struct pollindex *) arg;
|
||||
+
|
||||
+ sndio_poll_event (pindex->self, pindex->index, POLLOUT);
|
||||
+}
|
||||
+
|
||||
+static void sndio_fini (SndioVoice *self)
|
||||
+{
|
||||
+ if (self->hdl) {
|
||||
+ sio_close (self->hdl);
|
||||
+ self->hdl = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (self->pfds) {
|
||||
+ g_free (self->pfds);
|
||||
+ self->pfds = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (self->pindexes) {
|
||||
+ g_free (self->pindexes);
|
||||
+ self->pindexes = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (self->buf) {
|
||||
+ g_free (self->buf);
|
||||
+ self->buf = NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int sndio_init (SndioVoice *self,
|
||||
+ struct audsettings *as, int mode, SndioConf *cf)
|
||||
+{
|
||||
+ struct sio_par req;
|
||||
+ unsigned int nch;
|
||||
+ int i, nfds;
|
||||
+
|
||||
+ self->hdl = sio_open (cf->devname, mode, 1);
|
||||
+ if (self->hdl == NULL) {
|
||||
+ dolog ("failed to open device\n");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ self->mode = mode;
|
||||
+
|
||||
+ sio_initpar(&req);
|
||||
+
|
||||
+ switch (as->fmt) {
|
||||
+ case AUD_FMT_S8:
|
||||
+ req.bits = 8;
|
||||
+ req.sig = 1;
|
||||
+ break;
|
||||
+ case AUD_FMT_U8:
|
||||
+ req.bits = 8;
|
||||
+ req.sig = 0;
|
||||
+ break;
|
||||
+ case AUD_FMT_S16:
|
||||
+ req.bits = 16;
|
||||
+ req.sig = 1;
|
||||
+ break;
|
||||
+ case AUD_FMT_U16:
|
||||
+ req.bits = 16;
|
||||
+ req.sig = 0;
|
||||
+ break;
|
||||
+ case AUD_FMT_S32:
|
||||
+ req.bits = 32;
|
||||
+ req.sig = 1;
|
||||
+ break;
|
||||
+ case AUD_FMT_U32:
|
||||
+ req.bits = 32;
|
||||
+ req.sig = 0;
|
||||
+ }
|
||||
+
|
||||
+ if (req.bits > 8)
|
||||
+ req.le = as->endianness ? 0 : 1;
|
||||
+
|
||||
+ req.rate = as->freq;
|
||||
+ if (mode == SIO_PLAY)
|
||||
+ req.pchan = as->nchannels;
|
||||
+ else
|
||||
+ req.rchan = as->nchannels;
|
||||
+
|
||||
+ /* set on-device buffer size */
|
||||
+ req.appbufsz = req.rate * cf->latency / 1000;
|
||||
+
|
||||
+ if (!sio_setpar (self->hdl, &req)) {
|
||||
+ dolog ("failed set audio params\n");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ if (!sio_getpar (self->hdl, &self->par)) {
|
||||
+ dolog ("failed get audio params\n");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ nch = (mode == SIO_PLAY) ? self->par.pchan : self->par.rchan;
|
||||
+
|
||||
+ if (self->par.bits != req.bits || self->par.bps != req.bits / 8 ||
|
||||
+ self->par.sig != req.sig || (req.bits > 8 && self->par.le != req.le) ||
|
||||
+ self->par.rate != as->freq || nch != as->nchannels) {
|
||||
+ dolog ("unsupported audio params\n");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ self->bpf = self->par.bps * nch;
|
||||
+
|
||||
+ self->buf = audio_calloc (__func__, self->par.round, self->bpf);
|
||||
+ if (self->buf == NULL) {
|
||||
+ dolog ("failed to allocate audio buffer\n");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ nfds = sio_nfds (self->hdl);
|
||||
+
|
||||
+ self->pfds = g_malloc_n (nfds, sizeof(struct pollfd));
|
||||
+ if (self->pfds == NULL) {
|
||||
+ dolog ("failed to allocate pollfd structures\n");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ self->pindexes = g_malloc_n (nfds, sizeof(struct pollindex));
|
||||
+ if (self->pindexes == NULL) {
|
||||
+ dolog ("failed to allocate pollindex structures\n");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < nfds; i++) {
|
||||
+ self->pindexes[i].self = self;
|
||||
+ self->pindexes[i].index = i;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+fail:
|
||||
+ sndio_fini (self);
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+static int sndio_run_out (HWVoiceOut *hw, int live)
|
||||
+{
|
||||
+ SndioVoice *self = (SndioVoice *) hw;
|
||||
+ int decr, todo;
|
||||
+
|
||||
+ decr = hw->samples - self->qemu_pos;
|
||||
+ if (decr > live)
|
||||
+ decr = live;
|
||||
+
|
||||
+ decr = audio_pcm_hw_clip_out (hw, self->buf, decr, self->qemu_pos);
|
||||
+
|
||||
+ self->qemu_pos += decr;
|
||||
+
|
||||
+ todo = (self->qemu_pos * self->bpf) - self->sndio_pos;
|
||||
+ sndio_poll_wait (self, todo > 0 ? POLLOUT : 0);
|
||||
+
|
||||
+ return decr;
|
||||
+}
|
||||
+
|
||||
+static int sndio_run_in (HWVoiceIn *hw)
|
||||
+{
|
||||
+ SndioVoice *self = (SndioVoice *) hw;
|
||||
+ int decr, todo, avail;
|
||||
+
|
||||
+ avail = (self->sndio_pos / self->bpf) - self->qemu_pos;
|
||||
+
|
||||
+ decr = hw->samples - audio_pcm_hw_get_live_in (hw);
|
||||
+ if (decr > avail)
|
||||
+ decr = avail;
|
||||
+
|
||||
+ if (hw->wpos + decr > hw->samples) {
|
||||
+ dolog ("%s: overrun: wpos = %d, decr = %d\n", __func__, hw->wpos, decr);
|
||||
+ abort();
|
||||
+ }
|
||||
+
|
||||
+ hw->conv (hw->conv_buf + hw->wpos,
|
||||
+ self->buf + (hw->wpos * self->bpf),
|
||||
+ decr);
|
||||
+
|
||||
+ self->qemu_pos += decr;
|
||||
+
|
||||
+ /* did we complete the block ? */
|
||||
+ if (self->qemu_pos == self->par.round) {
|
||||
+ self->qemu_pos = 0;
|
||||
+ self->sndio_pos = 0;
|
||||
+ }
|
||||
+
|
||||
+ todo = (self->par.round * self->bpf) - self->sndio_pos;
|
||||
+ sndio_poll_wait (self, todo > 0 ? POLLIN : 0);
|
||||
+
|
||||
+ hw->wpos += decr;
|
||||
+ if (hw->wpos == hw->samples)
|
||||
+ hw->wpos = 0;
|
||||
+
|
||||
+ return decr;
|
||||
+}
|
||||
+
|
||||
+static int sndio_ctl (SndioVoice *self, int cmd)
|
||||
+{
|
||||
+ switch (cmd) {
|
||||
+ case VOICE_ENABLE:
|
||||
+ sio_start (self->hdl);
|
||||
+ sndio_poll_wait (self, 0);
|
||||
+ return 0;
|
||||
+
|
||||
+ case VOICE_DISABLE:
|
||||
+ sndio_poll_clear (self);
|
||||
+ sio_stop (self->hdl);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+static int sndio_write (SWVoiceOut *sw, void *buf, int len)
|
||||
+{
|
||||
+ return audio_pcm_sw_write (sw, buf, len);
|
||||
+}
|
||||
+
|
||||
+static int sndio_read (SWVoiceIn *sw, void *buf, int len)
|
||||
+{
|
||||
+ return audio_pcm_sw_read (sw, buf, len);
|
||||
+}
|
||||
+
|
||||
+static int sndio_ctl_out (HWVoiceOut *hw, int cmd, ...)
|
||||
+{
|
||||
+ SndioVoice *self = (SndioVoice *) hw;
|
||||
+
|
||||
+ return sndio_ctl (self, cmd);
|
||||
+}
|
||||
+
|
||||
+static int sndio_ctl_in (HWVoiceIn *hw, int cmd, ...)
|
||||
+{
|
||||
+ SndioVoice *self = (SndioVoice *) hw;
|
||||
+
|
||||
+ return sndio_ctl (self, cmd);
|
||||
+}
|
||||
+
|
||||
+static int sndio_init_out (HWVoiceOut *hw, struct audsettings *as, void *opaque)
|
||||
+{
|
||||
+ SndioVoice *self = (SndioVoice *) hw;
|
||||
+
|
||||
+ if (sndio_init (self, as, SIO_PLAY, opaque) == -1)
|
||||
+ return -1;
|
||||
+
|
||||
+ audio_pcm_init_info (&hw->info, as);
|
||||
+ hw->samples = self->par.round;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int sndio_init_in (HWVoiceIn *hw, struct audsettings *as, void *opaque)
|
||||
+{
|
||||
+ SndioVoice *self = (SndioVoice *) hw;
|
||||
+
|
||||
+ if (sndio_init (self, as, SIO_REC, opaque) == -1)
|
||||
+ return -1;
|
||||
+
|
||||
+ audio_pcm_init_info (&hw->info, as);
|
||||
+ hw->samples = self->par.round;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void sndio_fini_out (HWVoiceOut *hw)
|
||||
+{
|
||||
+ SndioVoice *self = (SndioVoice *) hw;
|
||||
+
|
||||
+ return sndio_fini(self);
|
||||
+}
|
||||
+
|
||||
+static void sndio_fini_in (HWVoiceIn *hw)
|
||||
+{
|
||||
+ SndioVoice *self = (SndioVoice *) hw;
|
||||
+
|
||||
+ return sndio_fini(self);
|
||||
+}
|
||||
+
|
||||
+static void *sndio_audio_init (void)
|
||||
+{
|
||||
+ SndioConf *conf;
|
||||
+
|
||||
+ conf = g_malloc(sizeof(SndioConf));
|
||||
+ if (conf == NULL)
|
||||
+ return NULL;
|
||||
+
|
||||
+ *conf = glob_conf;
|
||||
+
|
||||
+ return conf;
|
||||
+}
|
||||
+
|
||||
+static void sndio_audio_fini (void *opaque)
|
||||
+{
|
||||
+ g_free(opaque);
|
||||
+}
|
||||
+
|
||||
+static struct audio_option sndio_options[] = {
|
||||
+ {
|
||||
+ .name = "LATENCY",
|
||||
+ .tag = AUD_OPT_INT,
|
||||
+ .valp = &glob_conf.latency,
|
||||
+ .descr = "Desired latency in milliseconds"
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "DEVICE",
|
||||
+ .tag = AUD_OPT_STR,
|
||||
+ .valp = &glob_conf.devname,
|
||||
+ .descr = "Device name"
|
||||
+ },
|
||||
+ { /* End of list */ }
|
||||
+};
|
||||
+
|
||||
+static struct audio_pcm_ops sndio_pcm_ops = {
|
||||
+ .init_out = sndio_init_out,
|
||||
+ .fini_out = sndio_fini_out,
|
||||
+ .run_out = sndio_run_out,
|
||||
+ .write = sndio_write,
|
||||
+ .ctl_out = sndio_ctl_out,
|
||||
+ .init_in = sndio_init_in,
|
||||
+ .fini_in = sndio_fini_in,
|
||||
+ .run_in = sndio_run_in,
|
||||
+ .read = sndio_read,
|
||||
+ .ctl_in = sndio_ctl_in,
|
||||
+};
|
||||
+
|
||||
+static struct audio_driver sndio_audio_driver = {
|
||||
+ .name = "sndio",
|
||||
+ .descr = "https://man.openbsd.org/sndio",
|
||||
+ .options = sndio_options,
|
||||
+ .init = sndio_audio_init,
|
||||
+ .fini = sndio_audio_fini,
|
||||
+ .pcm_ops = &sndio_pcm_ops,
|
||||
+ .can_be_default = 1,
|
||||
+ .max_voices_out = INT_MAX,
|
||||
+ .max_voices_in = INT_MAX,
|
||||
+ .voice_size_out = sizeof (SndioVoice),
|
||||
+ .voice_size_in = sizeof (SndioVoice)
|
||||
+};
|
||||
+
|
||||
+static void register_audio_sndio(void)
|
||||
+{
|
||||
+ audio_driver_register(&sndio_audio_driver);
|
||||
+}
|
||||
+
|
||||
+type_init(register_audio_sndio);
|
@ -1,11 +1,36 @@
|
||||
$OpenBSD: patch-configure,v 1.59 2018/12/19 17:57:06 sthen Exp $
|
||||
$OpenBSD: patch-configure,v 1.60 2019/05/09 05:12:53 ratchov Exp $
|
||||
|
||||
Fix curses test to work on OpenBSD
|
||||
- sndio module
|
||||
- Fix curses test to work on OpenBSD
|
||||
|
||||
Index: configure
|
||||
--- configure.orig
|
||||
+++ configure
|
||||
@@ -3370,6 +3370,7 @@ if test "$curses" != "no" ; then
|
||||
@@ -819,8 +819,8 @@ NetBSD)
|
||||
OpenBSD)
|
||||
bsd="yes"
|
||||
make="${MAKE-gmake}"
|
||||
- audio_drv_list="sdl"
|
||||
- audio_possible_drivers="sdl"
|
||||
+ audio_drv_list="sndio"
|
||||
+ audio_possible_drivers="sndio"
|
||||
HOST_VARIANT_DIR="openbsd"
|
||||
supported_os="yes"
|
||||
;;
|
||||
@@ -3312,6 +3312,12 @@ for drv in $audio_drv_list; do
|
||||
fi
|
||||
;;
|
||||
|
||||
+ sndio)
|
||||
+ audio_drv_probe $drv sndio.h "-lsndio" \
|
||||
+ "sio_open(0, SIO_PLAY, 0); return 0;"
|
||||
+ sndio_libs="-lsndio"
|
||||
+ ;;
|
||||
+
|
||||
coreaudio)
|
||||
coreaudio_libs="-framework CoreAudio"
|
||||
;;
|
||||
@@ -3370,6 +3376,7 @@ if test "$curses" != "no" ; then
|
||||
fi
|
||||
curses_found=no
|
||||
cat > $TMPC << EOF
|
||||
@ -13,7 +38,7 @@ Index: configure
|
||||
#include <locale.h>
|
||||
#include <curses.h>
|
||||
#include <wchar.h>
|
||||
@@ -5631,10 +5632,6 @@ write_c_skeleton
|
||||
@@ -5631,10 +5638,6 @@ write_c_skeleton
|
||||
if test "$gcov" = "yes" ; then
|
||||
CFLAGS="-fprofile-arcs -ftest-coverage -g $CFLAGS"
|
||||
LDFLAGS="-fprofile-arcs -ftest-coverage $LDFLAGS"
|
||||
@ -24,3 +49,20 @@ Index: configure
|
||||
fi
|
||||
|
||||
if test "$have_asan" = "yes"; then
|
||||
@@ -6261,7 +6264,7 @@ echo "CONFIG_AUDIO_DRIVERS=$audio_drv_list" >> $config
|
||||
for drv in $audio_drv_list; do
|
||||
def=CONFIG_AUDIO_$(echo $drv | LC_ALL=C tr '[a-z]' '[A-Z]')
|
||||
case "$drv" in
|
||||
- alsa | oss | pa | sdl)
|
||||
+ alsa | oss | pa | sdl | sndio)
|
||||
echo "$def=m" >> $config_host_mak ;;
|
||||
*)
|
||||
echo "$def=y" >> $config_host_mak ;;
|
||||
@@ -6275,6 +6278,7 @@ echo "OSS_LIBS=$oss_libs" >> $config_host_mak
|
||||
if test "$audio_pt_int" = "yes" ; then
|
||||
echo "CONFIG_AUDIO_PT_INT=y" >> $config_host_mak
|
||||
fi
|
||||
+echo "SNDIO_LIBS=$sndio_libs" >> $config_host_mak
|
||||
if test "$audio_win_int" = "yes" ; then
|
||||
echo "CONFIG_AUDIO_WIN_INT=y" >> $config_host_mak
|
||||
fi
|
||||
|
Loading…
Reference in New Issue
Block a user