- Fix high CPU usage while recording and playing at the same time,
report better sio_onmove deltas [1] - Fix issues with underruns when the system is under high load - Fix sio_getcap [1] - Fallback to /dev/dsp (hw.snd.default_unit) in sndiod and libsndio when no other device is specified [1] - rc.d script now configures a monitoring sub-device (a fake recording stream with a mix of all playback streams) by default [1] - Use OPSYS for better portability PR: 212007 [1] Submitted by: Tobias Kortkamp (maintainer) [1]
This commit is contained in:
parent
90fb779629
commit
2eef738073
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=420515
6 changed files with 185 additions and 219 deletions
|
@ -3,6 +3,7 @@
|
|||
|
||||
PORTNAME= sndio
|
||||
PORTVERSION= 1.1.0
|
||||
PORTREVISION= 1
|
||||
CATEGORIES= audio
|
||||
MASTER_SITES= http://www.sndio.org/
|
||||
|
||||
|
@ -20,7 +21,7 @@ USE_RC_SUBR= sndiod
|
|||
.include <bsd.port.pre.mk>
|
||||
|
||||
# FreeBSD 9.x does not have SOCK_CLOEXEC
|
||||
.if ${OSVERSION} < 1000000
|
||||
.if ${OPSYS} == FreeBSD && ${OSVERSION} < 1000000
|
||||
CFLAGS+= -DSOCK_CLOEXEC=0
|
||||
.endif
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
rmidi=no # do we want support for raw char dev ?
|
||||
precision=16 # aucat/sndiod arithmetic precision
|
||||
user=_sndio # non-privileged user for sndio daemon
|
||||
@@ -71,6 +72,14 @@ case `uname` in
|
||||
@@ -71,6 +72,15 @@ case `uname` in
|
||||
defs='-DHAVE_ARC4RANDOM -DHAVE_ISSETUGID \\\
|
||||
-DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRTONUM'
|
||||
;;
|
||||
|
@ -16,14 +16,15 @@
|
|||
+ user=_sndio
|
||||
+ so="$so libsndio.so"
|
||||
+ defs='-DHAVE_ARC4RANDOM -DHAVE_ISSETUGID \\\
|
||||
+ -DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRTONUM'
|
||||
+ -DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRTONUM \\\
|
||||
+ -DDEFAULT_DEV=\\"fallback\\"'
|
||||
+ oss=yes
|
||||
+ mandir=${prefix}/man
|
||||
+ ;;
|
||||
esac
|
||||
|
||||
# shell word separator (none)
|
||||
@@ -106,6 +115,12 @@ for i; do
|
||||
@@ -106,6 +116,12 @@ for i; do
|
||||
--disable-alsa)
|
||||
alsa=no
|
||||
shift;;
|
||||
|
@ -36,7 +37,7 @@
|
|||
--enable-sun)
|
||||
sun=yes
|
||||
shift;;
|
||||
@@ -162,6 +177,13 @@ if [ $alsa = yes ]; then
|
||||
@@ -162,6 +178,13 @@ if [ $alsa = yes ]; then
|
||||
fi
|
||||
|
||||
#
|
||||
|
@ -50,7 +51,7 @@
|
|||
# if using Sun API, add corresponding parameters
|
||||
#
|
||||
if [ $sun = yes ]; then
|
||||
@@ -215,6 +237,7 @@ user..................... $user
|
||||
@@ -215,6 +238,7 @@ user..................... $user
|
||||
libbsd................... $libbsd
|
||||
precision................ $precision
|
||||
alsa..................... $alsa
|
||||
|
|
|
@ -1,15 +1,23 @@
|
|||
--- libsndio/sio.c.orig 2016-01-08 20:51:12 UTC
|
||||
+++ libsndio/sio.c
|
||||
@@ -64,6 +64,8 @@ sio_open(const char *str, unsigned int m
|
||||
@@ -64,17 +64,25 @@ sio_open(const char *str, unsigned int m
|
||||
return hdl;
|
||||
#if defined(USE_SUN)
|
||||
return _sio_sun_open("rsnd/0", mode, nbio);
|
||||
+#elif defined(USE_OSS)
|
||||
+ return _sio_oss_open("rsnd/0", mode, nbio);
|
||||
+ return _sio_oss_open("fallback", mode, nbio);
|
||||
#elif defined(USE_ALSA)
|
||||
return _sio_alsa_open("rsnd/0", mode, nbio);
|
||||
#else
|
||||
@@ -75,6 +77,8 @@ sio_open(const char *str, unsigned int m
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
+#if defined(USE_OSS)
|
||||
+ if (strcmp(str, "fallback") == 0)
|
||||
+ return _sio_oss_open(str, mode, nbio);
|
||||
+#endif
|
||||
if (_sndio_parsetype(str, "snd"))
|
||||
return _sio_aucat_open(str, mode, nbio);
|
||||
if (_sndio_parsetype(str, "rsnd"))
|
||||
#if defined(USE_SUN)
|
||||
return _sio_sun_open(str, mode, nbio);
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
--- libsndio/sio_oss.c.orig 2016-07-29 14:09:21 UTC
|
||||
--- libsndio/sio_oss.c.orig 2016-08-20 02:30:22 UTC
|
||||
+++ libsndio/sio_oss.c
|
||||
@@ -0,0 +1,890 @@
|
||||
@@ -0,0 +1,838 @@
|
||||
+/* $OpenBSD$ */
|
||||
+/*
|
||||
+ * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
|
||||
+ * Copyright (c) 2016 Tobias Kortkamp <t@tobik.me>
|
||||
+ *
|
||||
+ * Permission to use, copy, modify, and distribute this software for any
|
||||
+ * purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -21,6 +22,7 @@
|
|||
+#ifdef USE_OSS
|
||||
+#include <sys/types.h>
|
||||
+#include <sys/ioctl.h>
|
||||
+#include <sys/param.h>
|
||||
+#include <sys/soundcard.h>
|
||||
+#include <sys/stat.h>
|
||||
+
|
||||
|
@ -42,13 +44,6 @@
|
|||
+ sizeof(DEVPATH_PREFIX) - 1 + \
|
||||
+ sizeof(int) * 3)
|
||||
+
|
||||
+struct audio_pos {
|
||||
+ unsigned int play_pos; /* total bytes played */
|
||||
+ unsigned int play_xrun; /* bytes of silence inserted */
|
||||
+ unsigned int rec_pos; /* total bytes recorded */
|
||||
+ unsigned int rec_xrun; /* bytes dropped */
|
||||
+};
|
||||
+
|
||||
+#define AUDIO_INITPAR(p) \
|
||||
+ (void)memset((void *)(p), 0xff, sizeof(struct audio_swpar))
|
||||
+
|
||||
|
@ -72,13 +67,16 @@
|
|||
+struct sio_oss_hdl {
|
||||
+ struct sio_hdl sio;
|
||||
+ int fd;
|
||||
+ int filling;
|
||||
+ unsigned int ibpf, obpf; /* bytes per frame */
|
||||
+ unsigned int ibytes, obytes; /* bytes the hw transferred */
|
||||
+ unsigned int ierr, oerr; /* frames the hw dropped */
|
||||
+ unsigned int isamples;
|
||||
+ unsigned int osamples;
|
||||
+ int idelta, odelta; /* position reported to client */
|
||||
+
|
||||
+ unsigned int play_pos;
|
||||
+ char *devstr;
|
||||
+
|
||||
+ /* OSS doesn't have an API to ask for device parameters
|
||||
+ * without setting them, so we keep track of them ourselves.
|
||||
+ */
|
||||
+ struct audio_swpar swpar;
|
||||
+};
|
||||
+
|
||||
|
@ -95,11 +93,9 @@
|
|||
+static int sio_oss_revents(struct sio_hdl *, struct pollfd *);
|
||||
+
|
||||
+static void sio_oss_fmt_to_swpar(int, struct audio_swpar *);
|
||||
+static int sio_oss_audio_getpos(struct sio_oss_hdl *, struct audio_pos *);
|
||||
+static int sio_oss_audio_getpar(struct sio_oss_hdl *, struct audio_swpar *);
|
||||
+static int sio_oss_audio_setpar(struct sio_oss_hdl *, struct audio_swpar *);
|
||||
+static int sio_oss_audio_start(struct sio_oss_hdl *);
|
||||
+static int sio_oss_audio_stop(struct sio_oss_hdl *, int);
|
||||
+static int sio_oss_reopen(struct sio_oss_hdl *);
|
||||
+
|
||||
+static struct sio_ops sio_oss_ops = {
|
||||
+ sio_oss_close,
|
||||
|
@ -315,25 +311,33 @@
|
|||
+ unsigned int devnum;
|
||||
+ int fd, flags;
|
||||
+
|
||||
+ p = _sndio_parsetype(str, "rsnd");
|
||||
+ if (p == NULL) {
|
||||
+ DPRINTF("sio_oss_getfd: %s: \"rsnd\" expected\n", str);
|
||||
+ return -1;
|
||||
+ if (strcmp(str, "fallback") == 0) {
|
||||
+ /* On FreeBSD /dev/dsp points to the default unit
|
||||
+ * selectable with the hw.snd.default_unit sysctl.
|
||||
+ * Use it as fallback device.
|
||||
+ */
|
||||
+ snprintf(path, sizeof(path), DEVPATH_PREFIX);
|
||||
+ } else {
|
||||
+ p = _sndio_parsetype(str, "rsnd");
|
||||
+ if (p == NULL) {
|
||||
+ DPRINTF("sio_oss_getfd: %s: \"rsnd\" expected\n", str);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ switch (*p) {
|
||||
+ case '/':
|
||||
+ p++;
|
||||
+ break;
|
||||
+ default:
|
||||
+ DPRINTF("sio_oss_getfd: %s: '/' expected\n", str);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ p = _sndio_parsenum(p, &devnum, 255);
|
||||
+ if (p == NULL || *p != '\0') {
|
||||
+ DPRINTF("sio_oss_getfd: %s: number expected after '/'\n", str);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ snprintf(path, sizeof(path), DEVPATH_PREFIX "%u", devnum);
|
||||
+ }
|
||||
+ switch (*p) {
|
||||
+ case '/':
|
||||
+ p++;
|
||||
+ break;
|
||||
+ default:
|
||||
+ DPRINTF("sio_oss_getfd: %s: '/' expected\n", str);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ p = _sndio_parsenum(p, &devnum, 255);
|
||||
+ if (p == NULL || *p != '\0') {
|
||||
+ DPRINTF("sio_oss_getfd: %s: number expected after '/'\n", str);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ snprintf(path, sizeof(path), DEVPATH_PREFIX "%u", devnum);
|
||||
+ if (mode == (SIO_PLAY | SIO_REC))
|
||||
+ flags = O_RDWR;
|
||||
+ else
|
||||
|
@ -347,7 +351,7 @@
|
|||
+ return fd;
|
||||
+}
|
||||
+
|
||||
+static struct sio_hdl *
|
||||
+static struct sio_oss_hdl *
|
||||
+sio_oss_fdopen(int fd, unsigned int mode, int nbio)
|
||||
+{
|
||||
+ struct sio_oss_hdl *hdl;
|
||||
|
@ -360,29 +364,30 @@
|
|||
+ /* Set default device parameters */
|
||||
+ sio_oss_fmt_to_swpar(AFMT_S16_LE, &hdl->swpar);
|
||||
+ hdl->swpar.msb = 1;
|
||||
+ hdl->swpar.rate = 44100;
|
||||
+ hdl->swpar.rate = 48000;
|
||||
+ hdl->swpar.bps = SIO_BPS(hdl->swpar.bits);
|
||||
+ hdl->swpar.pchan = hdl->swpar.rchan = 2;
|
||||
+ hdl->swpar.round = 960; // TODO:
|
||||
+ hdl->swpar.nblks = 8; // TODO:
|
||||
+
|
||||
+ hdl->fd = fd;
|
||||
+ hdl->filling = 0;
|
||||
+ return (struct sio_hdl *)hdl;
|
||||
+
|
||||
+ return hdl;
|
||||
+}
|
||||
+
|
||||
+struct sio_hdl *
|
||||
+_sio_oss_open(const char *str, unsigned int mode, int nbio)
|
||||
+{
|
||||
+ struct sio_hdl *hdl;
|
||||
+ struct sio_oss_hdl *hdl;
|
||||
+ int fd;
|
||||
+
|
||||
+ fd = sio_oss_getfd(str, mode, nbio);
|
||||
+ if (fd < 0)
|
||||
+ return NULL;
|
||||
+
|
||||
+ hdl = sio_oss_fdopen(fd, mode, nbio);
|
||||
+ if (hdl != NULL)
|
||||
+ return hdl;
|
||||
+ if (hdl != NULL) {
|
||||
+ hdl->devstr = strdup(str);
|
||||
+ return (struct sio_hdl*)hdl;
|
||||
+ }
|
||||
+ while (close(fd) < 0 && errno == EINTR)
|
||||
+ ; /* retry */
|
||||
+
|
||||
|
@ -396,6 +401,7 @@
|
|||
+
|
||||
+ while (close(hdl->fd) < 0 && errno == EINTR)
|
||||
+ ; /* retry */
|
||||
+ free(hdl->devstr);
|
||||
+ free(hdl);
|
||||
+}
|
||||
+
|
||||
|
@ -403,51 +409,32 @@
|
|||
+sio_oss_start(struct sio_hdl *sh)
|
||||
+{
|
||||
+ struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh;
|
||||
+ int low;
|
||||
+
|
||||
+ hdl->obpf = hdl->sio.par.pchan * hdl->sio.par.bps;
|
||||
+ hdl->ibpf = hdl->sio.par.rchan * hdl->sio.par.bps;
|
||||
+ hdl->ibytes = 0;
|
||||
+ hdl->obytes = 0;
|
||||
+ hdl->ierr = 0;
|
||||
+ hdl->oerr = 0;
|
||||
+ hdl->isamples = 0;
|
||||
+ hdl->osamples = 0;
|
||||
+ hdl->idelta = 0;
|
||||
+ hdl->odelta = 0;
|
||||
+ hdl->play_pos = 0;
|
||||
+
|
||||
+ if (hdl->sio.mode & SIO_PLAY) {
|
||||
+ /*
|
||||
+ * keep the device paused and let sio_oss_pollfd() trigger the
|
||||
+ * start later, to avoid buffer underruns
|
||||
+ */
|
||||
+ hdl->filling = 1;
|
||||
+ } else {
|
||||
+ /*
|
||||
+ * no play buffers to fill, start now!
|
||||
+ */
|
||||
+ if (sio_oss_audio_start(hdl) < 0) {
|
||||
+ DPERROR("AUDIO_START");
|
||||
+ hdl->sio.eof = 1;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ _sio_onmove_cb(&hdl->sio, 0);
|
||||
+ }
|
||||
+ /* Nothing else to do here, device was just (re-)opened in
|
||||
+ * sio_setpar and OSS starts playing/recording on first
|
||||
+ * write/read.
|
||||
+ */
|
||||
+ _sio_onmove_cb(&hdl->sio, 0);
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+sio_oss_stop(struct sio_hdl *sh)
|
||||
+{
|
||||
+ struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh;
|
||||
+
|
||||
+ if (hdl->filling) {
|
||||
+ hdl->filling = 0;
|
||||
+ return 1;
|
||||
+ }
|
||||
+ if (sio_oss_audio_stop(hdl, hdl->fd) < 0) {
|
||||
+ DPERROR("AUDIO_STOP");
|
||||
+ hdl->sio.eof = 1;
|
||||
+ struct sio_oss_hdl *hdl = (struct sio_oss_hdl*)sh;
|
||||
+ /* Close and reopen device. This resets CURRENT_IPTR which
|
||||
+ * allows us to get a semi-accurate recording position */
|
||||
+ if (sio_oss_audio_setpar(hdl, &hdl->swpar) < 0)
|
||||
+ return 0;
|
||||
+ }
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
|
@ -506,7 +493,7 @@
|
|||
+ par->pchan = ap.pchan;
|
||||
+ par->rchan = ap.rchan;
|
||||
+ par->round = ap.round;
|
||||
+ par->appbufsz = par->bufsz = ap.nblks * ap.round;
|
||||
+ par->appbufsz = par->bufsz = ap.round * ap.nblks;
|
||||
+ par->xrun = SIO_IGNORE;
|
||||
+ return 1;
|
||||
+}
|
||||
|
@ -531,6 +518,7 @@
|
|||
+ hdl->sio.eof = 1;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return n;
|
||||
+}
|
||||
+
|
||||
|
@ -552,8 +540,6 @@
|
|||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ hdl->play_pos += n;
|
||||
+
|
||||
+ return n;
|
||||
+}
|
||||
+
|
||||
|
@ -570,16 +556,7 @@
|
|||
+
|
||||
+ pfd->fd = hdl->fd;
|
||||
+ pfd->events = events;
|
||||
+ if (hdl->filling && hdl->sio.wused == hdl->sio.par.bufsz *
|
||||
+ hdl->sio.par.pchan * hdl->sio.par.bps) {
|
||||
+ hdl->filling = 0;
|
||||
+ if (sio_oss_audio_start(hdl) < 0) {
|
||||
+ DPERROR("AUDIO_START");
|
||||
+ hdl->sio.eof = 1;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ _sio_onmove_cb(&hdl->sio, 0);
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
|
@ -587,61 +564,42 @@
|
|||
+sio_oss_revents(struct sio_hdl *sh, struct pollfd *pfd)
|
||||
+{
|
||||
+ struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh;
|
||||
+ struct audio_pos ap;
|
||||
+ int dierr = 0, doerr = 0, offset, delta;
|
||||
+ int delta;
|
||||
+ int revents = pfd->revents;
|
||||
+ long long play_pos, rec_pos;
|
||||
+ oss_count_t optr, iptr;
|
||||
+
|
||||
+ if ((pfd->revents & POLLHUP) ||
|
||||
+ (pfd->revents & (POLLIN | POLLOUT)) == 0)
|
||||
+ return pfd->revents;
|
||||
+ if (sio_oss_audio_getpos(hdl, &ap) < 0) {
|
||||
+ DPERROR("sio_oss_revents: GETPOS");
|
||||
+ hdl->sio.eof = 1;
|
||||
+ return POLLHUP;
|
||||
+ }
|
||||
+
|
||||
+ if (hdl->sio.mode & SIO_PLAY) {
|
||||
+ delta = (ap.play_pos - hdl->obytes) / hdl->obpf;
|
||||
+ doerr = (ap.play_xrun - hdl->oerr) / hdl->obpf;
|
||||
+ hdl->obytes = ap.play_pos;
|
||||
+ hdl->oerr = ap.play_xrun;
|
||||
+ if (ioctl(hdl->fd, SNDCTL_DSP_CURRENT_OPTR, &optr) < 0) {
|
||||
+ DPERROR("sio_oss_revents: ");
|
||||
+ hdl->sio.eof = 1;
|
||||
+ return POLLHUP;
|
||||
+ }
|
||||
+ play_pos = optr.samples - optr.fifo_samples;
|
||||
+ delta = play_pos - hdl->osamples;
|
||||
+ hdl->osamples = play_pos;
|
||||
+ hdl->odelta += delta;
|
||||
+ if (!(hdl->sio.mode & SIO_REC)) {
|
||||
+ hdl->idelta += delta;
|
||||
+ dierr = doerr;
|
||||
+ }
|
||||
+ if (doerr > 0)
|
||||
+ DPRINTFN(2, "play xrun %d\n", doerr);
|
||||
+ }
|
||||
+ if (hdl->sio.mode & SIO_REC) {
|
||||
+ delta = (ap.rec_pos - hdl->ibytes) / hdl->ibpf;
|
||||
+ dierr = (ap.rec_xrun - hdl->ierr) / hdl->ibpf;
|
||||
+ hdl->ibytes = ap.rec_pos;
|
||||
+ hdl->ierr = ap.rec_xrun;
|
||||
+ if (ioctl(hdl->fd, SNDCTL_DSP_CURRENT_IPTR, &iptr) < 0) {
|
||||
+ DPERROR("sio_oss_revents: ");
|
||||
+ hdl->sio.eof = 1;
|
||||
+ return POLLHUP;
|
||||
+ }
|
||||
+ rec_pos = iptr.samples - iptr.fifo_samples;
|
||||
+ delta = rec_pos - hdl->isamples;
|
||||
+ hdl->isamples = rec_pos;
|
||||
+ hdl->idelta += delta;
|
||||
+ if (!(hdl->sio.mode & SIO_PLAY)) {
|
||||
+ hdl->odelta += delta;
|
||||
+ doerr = dierr;
|
||||
+ }
|
||||
+ if (dierr > 0)
|
||||
+ DPRINTFN(2, "rec xrun %d\n", dierr);
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * GETPOS reports positions including xruns,
|
||||
+ * so we have to substract to get the real position
|
||||
+ */
|
||||
+ hdl->idelta -= dierr;
|
||||
+ hdl->odelta -= doerr;
|
||||
+
|
||||
+ offset = doerr - dierr;
|
||||
+ if (offset > 0) {
|
||||
+ hdl->sio.rdrop += offset * hdl->ibpf;
|
||||
+ hdl->idelta -= offset;
|
||||
+ DPRINTFN(2, "will drop %d and pause %d\n", offset, doerr);
|
||||
+ } else if (offset < 0) {
|
||||
+ hdl->sio.wsil += -offset * hdl->obpf;
|
||||
+ hdl->odelta -= -offset;
|
||||
+ DPRINTFN(2, "will insert %d and pause %d\n", -offset, dierr);
|
||||
+ }
|
||||
+
|
||||
+ delta = (hdl->idelta > hdl->odelta) ? hdl->idelta : hdl->odelta;
|
||||
|
@ -653,26 +611,6 @@
|
|||
+ return revents;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+sio_oss_audio_getpos(struct sio_oss_hdl *hdl, struct audio_pos *ap)
|
||||
+{
|
||||
+ count_info cio, cii;
|
||||
+ oss_count_t optr;
|
||||
+
|
||||
+ ap->play_pos = hdl->play_pos / hdl->sio.par.bps;
|
||||
+ ap->play_xrun = 0;
|
||||
+
|
||||
+ if (ioctl(hdl->fd, SNDCTL_DSP_GETIPTR, &cii) < 0) {
|
||||
+ DPERROR("sio_oss_getpos: GETIPTR");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ ap->rec_pos = cii.bytes;
|
||||
+ ap->rec_xrun = 0;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+sio_oss_fmt_to_swpar(int fmt, struct audio_swpar *ap) {
|
||||
+ switch(fmt) {
|
||||
|
@ -826,67 +764,77 @@
|
|||
+
|
||||
+static int sio_oss_audio_setpar(struct sio_oss_hdl *hdl, struct audio_swpar *ap)
|
||||
+{
|
||||
+ int fmt = sio_oss_swpar_to_fmt(ap);
|
||||
+ audio_buf_info bi;
|
||||
+ int bufsz;
|
||||
+ int chan;
|
||||
+ int fmt;
|
||||
+ int rate;
|
||||
+
|
||||
+ if (sio_oss_reopen(hdl) < 0) {
|
||||
+ DPERROR("sio_oss_audio_setpar: reopen");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ ap->msb = ap->msb == -1 ? 0 : ap->msb;
|
||||
+ ap->sig = ap->sig == -1 ? 1 : ap->sig;
|
||||
+ ap->bits = ap->bits == -1 ? ap->bps == -1 ? 16 : ap->bps*8 : ap->bits;
|
||||
+ ap->le = ap->le == -1 ? SIO_LE_NATIVE : ap->le;
|
||||
+ ap->bps = ap->bps == -1 ? SIO_BPS(ap->bits) : ap->bps;
|
||||
+ ap->msb = 0;
|
||||
+ ap->rate = ap->rate == -1 ? 48000 : ap->rate;
|
||||
+
|
||||
+ if (ap->bits < 8)
|
||||
+ ap->bits = 8;
|
||||
+ if (ap->bits > 32)
|
||||
+ ap->bits = 32;
|
||||
+ if (ap->bps < 1)
|
||||
+ ap->bps = 1;
|
||||
+ if (ap->bps > 4)
|
||||
+ ap->bps = 4;
|
||||
+ if (ap->rate < 4000)
|
||||
+ ap->rate = 4000;
|
||||
+ if (ap->rate > 192000)
|
||||
+ ap->rate = 192000;
|
||||
+
|
||||
+ fmt = sio_oss_swpar_to_fmt(ap);
|
||||
+ if (fmt < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ if (ioctl(hdl->fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
|
||||
+ if (ioctl(hdl->fd, SNDCTL_DSP_SETFMT, &fmt) < 0) {
|
||||
+ DPERROR("sio_oss_audio_setpar: SETFMT");
|
||||
+ return -1;
|
||||
+
|
||||
+ }
|
||||
+ sio_oss_fmt_to_swpar(fmt, ap);
|
||||
+
|
||||
+ if (ioctl(hdl->fd, SNDCTL_DSP_SPEED, &ap->rate) < 0)
|
||||
+ if (ioctl(hdl->fd, SNDCTL_DSP_SPEED, &ap->rate) < 0) {
|
||||
+ DPERROR("sio_oss_audio_setpar: SPEED");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ ap->bps = SIO_BPS(ap->bits);
|
||||
+ ap->msb = 0;
|
||||
+
|
||||
+ int chan = (hdl->sio.mode & SIO_PLAY) ? ap->pchan : ap->rchan;
|
||||
+ if (ioctl(hdl->fd, SNDCTL_DSP_CHANNELS, &chan) < 0)
|
||||
+ chan = ap->pchan == ~0U ? ap->pchan : ap->rchan;
|
||||
+ chan = chan == -1 ? 2 : chan;
|
||||
+ if (ioctl(hdl->fd, SNDCTL_DSP_CHANNELS, &chan) < 0) {
|
||||
+ DPERROR("sio_oss_audio_setpar: CHANNELS");
|
||||
+ return -1;
|
||||
+
|
||||
+ }
|
||||
+ ap->pchan = ap->rchan = chan;
|
||||
+
|
||||
+ ap->nblks = ap->nblks <= 0 ? 8 : ap->nblks;
|
||||
+ ap->round = ap->round <= 0 ? 960 : ap->round;
|
||||
+
|
||||
+ hdl->swpar = *ap;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int sio_oss_audio_start(struct sio_oss_hdl *hdl) {
|
||||
+ // Empty playback buffer
|
||||
+ if (ioctl(hdl->fd, SNDCTL_DSP_SKIP, NULL) < 0) {
|
||||
+ DPERROR("SNDCTL_DSP_SKIP");
|
||||
+static int sio_oss_reopen(struct sio_oss_hdl *hdl) {
|
||||
+ /* Reopen device */
|
||||
+ while (close(hdl->fd) < 0 && errno == EINTR)
|
||||
+ ; /* retry */
|
||||
+ hdl->fd = sio_oss_getfd(hdl->devstr, hdl->sio.mode, 1);
|
||||
+ if (hdl->fd < 0) {
|
||||
+ DPERROR("sio_oss_audio_setpar: reopen");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ int trigger;
|
||||
+
|
||||
+ if (hdl->sio.mode & SIO_PLAY) {
|
||||
+ trigger = PCM_ENABLE_OUTPUT;
|
||||
+ }
|
||||
+ if (hdl->sio.mode & SIO_REC) {
|
||||
+ trigger = PCM_ENABLE_INPUT;
|
||||
+ } // TODO:
|
||||
+
|
||||
+ if (ioctl(hdl->fd, SNDCTL_DSP_SETTRIGGER, &trigger)) {
|
||||
+ DPERROR("sio_oss_start: SETTRIGGER");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int sio_oss_audio_stop(struct sio_oss_hdl *hdl, int fd) {
|
||||
+ /* Block until buffer is played */
|
||||
+ if (ioctl(hdl->fd, SNDCTL_DSP_SYNC, NULL) < 0) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ // TODO: Check mode and use HALT_{IN,OUT}PUT
|
||||
+ if (ioctl(hdl->fd, SNDCTL_DSP_HALT, NULL) < 0) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# $FreeBSD$
|
||||
#
|
||||
# PROVIDE: sndiod
|
||||
# REQUIRE: NETWORKING sysctl
|
||||
# REQUIRE: NETWORKING
|
||||
# BEFORE: DAEMON
|
||||
# KEYWORD: shutdown
|
||||
|
||||
|
@ -23,9 +23,8 @@ rcvar=sndiod_enable
|
|||
|
||||
load_rc_config $name
|
||||
|
||||
_sndiod_devnum=$($SYSCTL -n hw.snd.default_unit)
|
||||
: ${sndiod_enable="NO"}
|
||||
: ${sndiod_flags="-f rsnd/$_sndiod_devnum"}
|
||||
: ${sndiod_flags="-s default -m mon -s monitor"}
|
||||
|
||||
command="%%PREFIX%%/bin/sndiod"
|
||||
|
||||
|
|
|
@ -1,28 +1,37 @@
|
|||
sndio's OSS support (i.e. local playback support) is highly
|
||||
Sndio's OSS support (i.e. local playback/recording support) is highly
|
||||
experimental. If you run into problems please file a bug at
|
||||
https://github.com/t6/sndio or send an email to t+sndio@tobik.me.
|
||||
|
||||
The recommended way to use this port is to have a remote sndio server
|
||||
running on a Linux or OpenBSD host.
|
||||
|
||||
If you want clients to auto-play to your remote sndio server, enable
|
||||
sndiod with:
|
||||
|
||||
sysrc sndiod_enable=YES sndiod_flags="-f snd@remotehost/0"
|
||||
service sndiod start
|
||||
|
||||
For local playback simply enabling the sndiod server will suffice
|
||||
Enable the sndiod server with:
|
||||
|
||||
sysrc sndiod_enable=YES
|
||||
service sndiod start
|
||||
|
||||
Alternatively set the AUDIODEVICE environment variable so clients know
|
||||
where to stream to
|
||||
Please note that by default sndiod is configured with a monitoring
|
||||
sub-device i.e. a device through which you can record everything that
|
||||
plays through sndiod:
|
||||
|
||||
aucat -f snd/0.monitor -o recording.wav
|
||||
|
||||
Make sure you override sndiod_flags if this is not wanted:
|
||||
|
||||
sysrc sndiod_flags=""
|
||||
|
||||
If you want clients to auto-play to your remote sndio server set
|
||||
sndiod_flags accordingly:
|
||||
|
||||
sysrc sndiod_flags="-f snd@remotehost/0"
|
||||
|
||||
Alternatively you can always set the AUDIODEVICE environment variable
|
||||
so clients know where to stream to:
|
||||
|
||||
export AUDIODEVICE=snd@remotehost/0
|
||||
|
||||
There is no sndio support in the official FreeBSD ports tree yet. The
|
||||
fork at https://github.com/t6/freebsd-port-sndio contains patches that
|
||||
enable sndio support in important ports.
|
||||
There is little sndio support in the FreeBSD ports tree right now. If
|
||||
your favourite port is missing support please take a look at the fork
|
||||
at https://github.com/t6/freebsd-ports-sndio and
|
||||
https://github.com/t6/freebsd-ports-sndio/wiki/Status which contains
|
||||
patches that enable sndio support in various ports.
|
||||
|
||||
audio/pulseaudio-module-sndio is a PulseAudio module that allows you
|
||||
to play to your sndio server. This is useful for ports that have
|
||||
|
|
Loading…
Reference in a new issue