diff options
-rw-r--r-- | GIDs | 1 | ||||
-rw-r--r-- | UIDs | 1 | ||||
-rw-r--r-- | audio/Makefile | 1 | ||||
-rw-r--r-- | audio/sndio/Makefile | 41 | ||||
-rw-r--r-- | audio/sndio/distinfo | 3 | ||||
-rw-r--r-- | audio/sndio/files/patch-configure | 60 | ||||
-rw-r--r-- | audio/sndio/files/patch-libsndio_Makefile.in | 17 | ||||
-rw-r--r-- | audio/sndio/files/patch-libsndio_sio.c | 20 | ||||
-rw-r--r-- | audio/sndio/files/patch-libsndio_sio__oss.c | 893 | ||||
-rw-r--r-- | audio/sndio/files/patch-libsndio_sio__priv.h | 12 | ||||
-rw-r--r-- | audio/sndio/files/sndiod.in | 32 | ||||
-rw-r--r-- | audio/sndio/pkg-descr | 10 | ||||
-rw-r--r-- | audio/sndio/pkg-message | 29 | ||||
-rw-r--r-- | audio/sndio/pkg-plist | 35 |
14 files changed, 1155 insertions, 0 deletions
@@ -234,6 +234,7 @@ aox:*:666: riak:*:667: bnetd:*:700: fastnetmon:*:701: +_sndio:*:702: bopm:*:717: openxpki:*:777: zetacoin:*:780: @@ -242,6 +242,7 @@ riakcs:*:668:667::0:0:Riak CS user:/usr/local/lib/riak-cs:/bin/sh stanchion:*:669:667::0:0:Stanchion user:/usr/local/lib/stanchion:/bin/sh bnetd:*:700:700::0:0:Bnetd user:/nonexistent:/usr/sbin/nologin fastnetmon:*:701:701::0:0:FastNetMon user:/nonexistent:/usr/sbin/nologin +_sndio:*:702:702::0:0:sndio privsep:/var/empty:/usr/sbin/nologin bopm:*:717:717::0:0:Blitzed Open Proxy Monitor:/nonexistent:/bin/sh _dnscrypt-wrapper:*:718:65534::0:0:dnscrypt-wrapper user:/var/empty:/usr/sbin/nologin openxpki:*:777:777::0:0:OpenXPKI Owner:/nonexistent:/usr/sbin/nologin diff --git a/audio/Makefile b/audio/Makefile index 822d8d57c57b..00b5e7a61a24 100644 --- a/audio/Makefile +++ b/audio/Makefile @@ -697,6 +697,7 @@ SUBDIR += smasher SUBDIR += snack SUBDIR += snd + SUBDIR += sndio SUBDIR += solfege SUBDIR += sonata SUBDIR += sooperlooper diff --git a/audio/sndio/Makefile b/audio/sndio/Makefile new file mode 100644 index 000000000000..f11b150dc23c --- /dev/null +++ b/audio/sndio/Makefile @@ -0,0 +1,41 @@ +# Created by: Tobias Kortkamp <t@tobik.me> +# $FreeBSD$ + +PORTNAME= sndio +PORTVERSION= 1.1.0 +CATEGORIES= audio +MASTER_SITES= http://www.sndio.org/ + +MAINTAINER= t@tobik.me +COMMENT= Small audio and MIDI framework from the OpenBSD project + +LICENSE= ISCL + +HAS_CONFIGURE= yes +CONFIGURE_ARGS= --prefix=${PREFIX} --mandir=${PREFIX}/man + +USE_LDCONFIG= yes +USE_RC_SUBR= sndiod + +.include <bsd.port.pre.mk> + +# FreeBSD 9.x does not have SOCK_CLOEXEC +.if ${OSVERSION} < 1000000 +CFLAGS+= -DSOCK_CLOEXEC=0 +.endif + +USERS= _sndio +GROUPS= _sndio + +# Parallel build leads to problems, but sndio is very quick to compile +# as is so not worth fixing +MAKE_JOBS_UNSAFE= yes + +post-install: + @${STRIP_CMD} \ + ${STAGEDIR}${PREFIX}/lib/libsndio.so.6.1 \ + ${STAGEDIR}${PREFIX}/bin/sndiod \ + ${STAGEDIR}${PREFIX}/bin/aucat \ + ${STAGEDIR}${PREFIX}/bin/midicat + +.include <bsd.port.post.mk> diff --git a/audio/sndio/distinfo b/audio/sndio/distinfo new file mode 100644 index 000000000000..4293504038ac --- /dev/null +++ b/audio/sndio/distinfo @@ -0,0 +1,3 @@ +TIMESTAMP = 1465315037 +SHA256 (sndio-1.1.0.tar.gz) = fcd7f845ff70f38c2898d737450b8aa3e1bb0afb9d147e8429ef22c0b2c2db57 +SIZE (sndio-1.1.0.tar.gz) = 121018 diff --git a/audio/sndio/files/patch-configure b/audio/sndio/files/patch-configure new file mode 100644 index 000000000000..9b967a11bf0b --- /dev/null +++ b/audio/sndio/files/patch-configure @@ -0,0 +1,60 @@ +--- configure.orig 2015-12-15 05:28:04 UTC ++++ configure +@@ -32,6 +32,7 @@ prefix=/usr/local # where to install s + so="libsndio.so.\${MAJ}.\${MIN}" # shared libs to build + alsa=no # do we want alsa support ? + sun=no # do we want sun support ? ++oss=no # do we want oss support ? + 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 + defs='-DHAVE_ARC4RANDOM -DHAVE_ISSETUGID \\\ + -DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRTONUM' + ;; ++ FreeBSD) ++ user=_sndio ++ so="$so libsndio.so" ++ defs='-DHAVE_ARC4RANDOM -DHAVE_ISSETUGID \\\ ++ -DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRTONUM' ++ oss=yes ++ mandir=${prefix}/man ++ ;; + esac + + # shell word separator (none) +@@ -106,6 +115,12 @@ for i; do + --disable-alsa) + alsa=no + shift;; ++ --enable-oss) ++ oss=yes ++ shift;; ++ --disable-oss) ++ oss=no ++ shift;; + --enable-sun) + sun=yes + shift;; +@@ -162,6 +177,13 @@ if [ $alsa = yes ]; then + fi + + # ++# if using OSS, add corresponding parameters ++# ++if [ $oss = yes ]; then ++ defs="$defs -DUSE_OSS" ++fi ++ ++# + # if using Sun API, add corresponding parameters + # + if [ $sun = yes ]; then +@@ -215,6 +237,7 @@ user..................... $user + libbsd................... $libbsd + precision................ $precision + alsa..................... $alsa ++oss...................... $oss + sun...................... $sun + rmidi.................... $rmidi + diff --git a/audio/sndio/files/patch-libsndio_Makefile.in b/audio/sndio/files/patch-libsndio_Makefile.in new file mode 100644 index 000000000000..e199ca7596b6 --- /dev/null +++ b/audio/sndio/files/patch-libsndio_Makefile.in @@ -0,0 +1,17 @@ +--- libsndio/Makefile.in.orig 2015-12-30 11:54:40 UTC ++++ libsndio/Makefile.in +@@ -99,7 +99,7 @@ clean: + # + OBJS = debug.o aucat.o \ + mio.o mio_rmidi.o mio_alsa.o mio_aucat.o \ +-sio.o sio_alsa.o sio_aucat.o sio_sun.o \ ++sio.o sio_alsa.o sio_aucat.o sio_oss.o sio_sun.o \ + issetugid.o strlcat.o strlcpy.o strtonum.o + + .c.o: +@@ -140,3 +140,5 @@ sio_aucat.o: sio_aucat.c aucat.h amsg.h + ../bsd-compat/bsd-compat.h + sio_sun.o: sio_sun.c debug.h sio_priv.h sndio.h \ + ../bsd-compat/bsd-compat.h ++sio_oss.o: sio_oss.c debug.h sio_priv.h sndio.h \ ++ ../bsd-compat/bsd-compat.h diff --git a/audio/sndio/files/patch-libsndio_sio.c b/audio/sndio/files/patch-libsndio_sio.c new file mode 100644 index 000000000000..44de62ae4ae5 --- /dev/null +++ b/audio/sndio/files/patch-libsndio_sio.c @@ -0,0 +1,20 @@ +--- 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 + 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); + #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 + if (_sndio_parsetype(str, "rsnd")) + #if defined(USE_SUN) + return _sio_sun_open(str, mode, nbio); ++#elif defined(USE_OSS) ++ return _sio_oss_open(str, mode, nbio); + #elif defined(USE_ALSA) + return _sio_alsa_open(str, mode, nbio); + #else diff --git a/audio/sndio/files/patch-libsndio_sio__oss.c b/audio/sndio/files/patch-libsndio_sio__oss.c new file mode 100644 index 000000000000..24b9f0481980 --- /dev/null +++ b/audio/sndio/files/patch-libsndio_sio__oss.c @@ -0,0 +1,893 @@ +--- libsndio/sio_oss.c.orig 2016-07-29 14:09:21 UTC ++++ libsndio/sio_oss.c +@@ -0,0 +1,890 @@ ++/* $OpenBSD$ */ ++/* ++ * Copyright (c) 2008 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. ++ */ ++ ++#ifdef USE_OSS ++#include <sys/types.h> ++#include <sys/ioctl.h> ++#include <sys/soundcard.h> ++#include <sys/stat.h> ++ ++#include <errno.h> ++#include <fcntl.h> ++#include <limits.h> ++#include <poll.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <unistd.h> ++ ++#include "debug.h" ++#include "sio_priv.h" ++#include "bsd-compat.h" ++ ++#define DEVPATH_PREFIX "/dev/dsp" ++#define DEVPATH_MAX (1 + \ ++ 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)) ++ ++/* ++ * argument to AUDIO_SETPAR and AUDIO_GETPAR ioctls ++ */ ++struct audio_swpar { ++ unsigned int sig; /* if 1, encoding is signed */ ++ unsigned int le; /* if 1, encoding is little-endian */ ++ unsigned int bits; /* bits per sample */ ++ unsigned int bps; /* bytes per sample */ ++ unsigned int msb; /* if 1, bits are msb-aligned */ ++ unsigned int rate; /* common play & rec sample rate */ ++ unsigned int pchan; /* play channels */ ++ unsigned int rchan; /* rec channels */ ++ unsigned int nblks; /* number of blocks in play buffer */ ++ unsigned int round; /* common frames per block */ ++ unsigned int _spare[6]; ++}; ++ ++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 */ ++ int idelta, odelta; /* position reported to client */ ++ ++ unsigned int play_pos; ++ struct audio_swpar swpar; ++}; ++ ++static void sio_oss_close(struct sio_hdl *); ++static int sio_oss_start(struct sio_hdl *); ++static int sio_oss_stop(struct sio_hdl *); ++static int sio_oss_setpar(struct sio_hdl *, struct sio_par *); ++static int sio_oss_getpar(struct sio_hdl *, struct sio_par *); ++static int sio_oss_getcap(struct sio_hdl *, struct sio_cap *); ++static size_t sio_oss_read(struct sio_hdl *, void *, size_t); ++static size_t sio_oss_write(struct sio_hdl *, const void *, size_t); ++static int sio_oss_nfds(struct sio_hdl *); ++static int sio_oss_pollfd(struct sio_hdl *, struct pollfd *, int); ++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 struct sio_ops sio_oss_ops = { ++ sio_oss_close, ++ sio_oss_setpar, ++ sio_oss_getpar, ++ sio_oss_getcap, ++ sio_oss_write, ++ sio_oss_read, ++ sio_oss_start, ++ sio_oss_stop, ++ sio_oss_nfds, ++ sio_oss_pollfd, ++ sio_oss_revents, ++ NULL, /* setvol */ ++ NULL, /* getvol */ ++}; ++ ++static int ++sio_oss_adjpar(struct sio_oss_hdl *hdl, struct audio_swpar *ap) ++{ ++ if (hdl->sio.eof) ++ return 0; ++ if (sio_oss_audio_setpar(hdl, ap)) { ++ DPERROR("AUDIO_SETPAR"); ++ hdl->sio.eof = 1; ++ return 0; ++ } ++ if (sio_oss_audio_getpar(hdl, ap)) { ++ DPERROR("AUDIO_GETPAR"); ++ hdl->sio.eof = 1; ++ return 0; ++ } ++ return 1; ++} ++ ++/* ++ * try to set the device to the given parameters and check that the ++ * device can use them; return 1 on success, 0 on failure or error ++ */ ++static int ++sio_oss_testpar(struct sio_oss_hdl *hdl, struct sio_enc *enc, ++ unsigned int pchan, unsigned int rchan, unsigned int rate) ++{ ++ struct audio_swpar ap; ++ ++ AUDIO_INITPAR(&ap); ++ if (enc != NULL) { ++ ap.sig = enc->sig; ++ ap.bits = enc->bits; ++ ap.bps = enc->bps; ++ if (ap.bps > 1) ++ ap.le = enc->le; ++ if (ap.bps * 8 > ap.bits) ++ ap.msb = enc->msb; ++ } ++ if (rate) ++ ap.rate = rate; ++ if (pchan && (hdl->sio.mode & SIO_PLAY)) ++ ap.pchan = pchan; ++ if (rchan && (hdl->sio.mode & SIO_REC)) ++ ap.rchan = rchan; ++ if (!sio_oss_adjpar(hdl, &ap)) ++ return 0; ++ if (pchan && ap.pchan != pchan) ++ return 0; ++ if (rchan && ap.rchan != rchan) ++ return 0; ++ if (rate && ap.rate != rate) ++ return 0; ++ if (enc) { ++ if (ap.sig != enc->sig) ++ return 0; ++ if (ap.bits != enc->bits) ++ return 0; ++ if (ap.bps != enc->bps) ++ return 0; ++ if (ap.bps > 1 && ap.le != enc->le) ++ return 0; ++ if (ap.bits < ap.bps * 8 && ap.msb != enc->msb) ++ return 0; ++ } ++ return 1; ++} ++ ++/* ++ * guess device capabilities ++ */ ++static int ++sio_oss_getcap(struct sio_hdl *sh, struct sio_cap *cap) ++{ ++ static unsigned int chans[] = { ++ 1, 2, 4, 6, 8, 10, 12 ++ }; ++ static unsigned int rates[] = { ++ 8000, 11025, 12000, 16000, 22050, 24000, ++ 32000, 44100, 48000, 64000, 88200, 96000 ++ }; ++ static unsigned int encs[] = { ++ 8, 16, 24, 32 ++ }; ++ struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; ++ struct audio_swpar savepar, ap; ++ unsigned int nconf = 0; ++ unsigned int enc_map = 0, rchan_map = 0, pchan_map = 0, rate_map; ++ unsigned int i, j, conf; ++ ++ if (sio_oss_audio_getpar(hdl, &savepar)) { ++ DPERROR("AUDIO_GETPAR"); ++ hdl->sio.eof = 1; ++ return 0; ++ } ++ ++ /* ++ * get a subset of supported encodings ++ */ ++ for (i = 0; i < sizeof(encs) / sizeof(encs[0]); i++) { ++ AUDIO_INITPAR(&ap); ++ ap.bits = encs[i]; ++ ap.sig = (ap.bits > 8) ? 1 : 0; ++ if (!sio_oss_adjpar(hdl, &ap)) ++ return 0; ++ if (ap.bits == encs[i]) { ++ cap->enc[i].sig = ap.sig; ++ cap->enc[i].bits = ap.bits; ++ cap->enc[i].le = ap.le; ++ cap->enc[i].bps = ap.bps; ++ cap->enc[i].msb = ap.msb; ++ enc_map |= 1 << i; ++ } ++ } ++ ++ /* ++ * fill channels ++ * ++ * for now we're lucky: all kernel devices assume that the ++ * number of channels and the encoding are independent so we can ++ * use the current encoding and try various channels. ++ */ ++ if (hdl->sio.mode & SIO_PLAY) { ++ for (i = 0; i < sizeof(chans) / sizeof(chans[0]); i++) { ++ AUDIO_INITPAR(&ap); ++ ap.pchan = chans[i]; ++ if (!sio_oss_adjpar(hdl, &ap)) ++ return 0; ++ if (ap.pchan == chans[i]) { ++ cap->pchan[i] = chans[i]; ++ pchan_map |= (1 << i); ++ } ++ } ++ } ++ if (hdl->sio.mode & SIO_REC) { ++ for (i = 0; i < sizeof(chans) / sizeof(chans[0]); i++) { ++ AUDIO_INITPAR(&ap); ++ ap.pchan = chans[i]; ++ if (!sio_oss_adjpar(hdl, &ap)) ++ return 0; ++ if (ap.rchan == chans[i]) { ++ cap->rchan[i] = chans[i]; ++ rchan_map |= (1 << i); ++ } ++ } ++ } ++ ++ /* ++ * fill rates ++ * ++ * rates are not independent from other parameters (eg. on ++ * uaudio devices), so certain rates may not be allowed with ++ * certain encodings. We have to check rates for all encodings ++ */ ++ for (j = 0; j < sizeof(encs) / sizeof(encs[0]); j++) { ++ rate_map = 0; ++ if ((enc_map & (1 << j)) == 0) ++ continue; ++ for (i = 0; i < sizeof(rates) / sizeof(rates[0]); i++) { ++ if (sio_oss_testpar(hdl, ++ &cap->enc[j], 0, 0, rates[i])) { ++ cap->rate[i] = rates[i]; ++ rate_map |= (1 << i); ++ } ++ } ++ for (conf = 0; conf < nconf; conf++) { ++ if (cap->confs[conf].rate == rate_map) { ++ cap->confs[conf].enc |= (1 << j); ++ break; ++ } ++ } ++ if (conf == nconf) { ++ if (nconf == SIO_NCONF) ++ break; ++ cap->confs[nconf].enc = (1 << j); ++ cap->confs[nconf].pchan = pchan_map; ++ cap->confs[nconf].rchan = rchan_map; ++ cap->confs[nconf].rate = rate_map; ++ nconf++; ++ } ++ } ++ cap->nconf = nconf; ++ ++ if (sio_oss_audio_setpar(hdl, &savepar)) { ++ DPERROR("AUDIO_SETPAR"); ++ hdl->sio.eof = 1; ++ return 0; ++ } ++ return 1; ++} ++ ++static int ++sio_oss_getfd(const char *str, unsigned int mode, int nbio) ++{ ++ const char *p; ++ char path[DEVPATH_MAX]; ++ 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; ++ } ++ 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 ++ flags = (mode & SIO_PLAY) ? O_WRONLY : O_RDONLY; ++ while ((fd = open(path, flags | O_NONBLOCK | O_CLOEXEC)) < 0) { ++ if (errno == EINTR) ++ continue; ++ DPERROR(path); ++ return -1; ++ } ++ return fd; ++} ++ ++static struct sio_hdl * ++sio_oss_fdopen(int fd, unsigned int mode, int nbio) ++{ ++ struct sio_oss_hdl *hdl; ++ ++ hdl = malloc(sizeof(struct sio_oss_hdl)); ++ if (hdl == NULL) ++ return NULL; ++ _sio_create(&hdl->sio, &sio_oss_ops, mode, nbio); ++ ++ /* Set default device parameters */ ++ sio_oss_fmt_to_swpar(AFMT_S16_LE, &hdl->swpar); ++ hdl->swpar.msb = 1; ++ hdl->swpar.rate = 44100; ++ 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; ++} ++ ++struct sio_hdl * ++_sio_oss_open(const char *str, unsigned int mode, int nbio) ++{ ++ struct sio_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; ++ while (close(fd) < 0 && errno == EINTR) ++ ; /* retry */ ++ ++ return NULL; ++} ++ ++static void ++sio_oss_close(struct sio_hdl *sh) ++{ ++ struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; ++ ++ while (close(hdl->fd) < 0 && errno == EINTR) ++ ; /* retry */ ++ free(hdl); ++} ++ ++static int ++sio_oss_start(struct sio_hdl *sh) ++{ ++ struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; ++ ++ 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->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); ++ } ++ 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; ++ return 0; ++ } ++ return 1; ++} ++ ++static int ++sio_oss_setpar(struct sio_hdl *sh, struct sio_par *par) ++{ ++ struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; ++ struct audio_swpar ap; ++ ++ AUDIO_INITPAR(&ap); ++ ap.sig = par->sig; ++ ap.le = par->le; ++ ap.bits = par->bits; ++ ap.bps = par->bps; ++ ap.msb = par->msb; ++ ap.rate = par->rate; ++ if (hdl->sio.mode & SIO_PLAY) ++ ap.pchan = par->pchan; ++ if (hdl->sio.mode & SIO_REC) ++ ap.rchan = par->rchan; ++ if (par->round != ~0U && par->appbufsz != ~0U) { ++ ap.round = par->round; ++ ap.nblks = par->appbufsz / par->round; ++ } else if (par->round != ~0U) { ++ ap.round = par->round; ++ ap.nblks = 2; ++ } else if (par->appbufsz != ~0U) { ++ ap.round = par->appbufsz / 2; ++ ap.nblks = 2; ++ } ++ if (sio_oss_audio_setpar(hdl, &ap) < 0) { ++ DPERROR("AUDIO_SETPAR"); ++ hdl->sio.eof = 1; ++ return 0; ++ } ++ return 1; ++} ++ ++static int ++sio_oss_getpar(struct sio_hdl *sh, struct sio_par *par) ++{ ++ struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; ++ struct audio_swpar ap; ++ ++ if (sio_oss_audio_getpar(hdl, &ap) < 0) { ++ DPERROR("AUDIO_GETPAR"); ++ hdl->sio.eof = 1; ++ return 0; ++ } ++ par->sig = ap.sig; ++ par->le = ap.le; ++ par->bits = ap.bits; ++ par->bps = ap.bps; ++ par->msb = ap.msb; ++ par->rate = ap.rate; ++ par->pchan = ap.pchan; ++ par->rchan = ap.rchan; ++ par->round = ap.round; ++ par->appbufsz = par->bufsz = ap.nblks * ap.round; ++ par->xrun = SIO_IGNORE; ++ return 1; ++} ++ ++static size_t ++sio_oss_read(struct sio_hdl *sh, void *buf, size_t len) ++{ ++ struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; ++ ssize_t n; ++ ++ while ((n = read(hdl->fd, buf, len)) < 0) { ++ if (errno == EINTR) ++ continue; ++ if (errno != EAGAIN) { ++ DPERROR("sio_oss_read: read"); ++ hdl->sio.eof = 1; ++ } ++ return 0; ++ } ++ if (n == 0) { ++ DPRINTF("sio_oss_read: eof\n"); ++ hdl->sio.eof = 1; ++ return 0; ++ } ++ return n; ++} ++ ++static size_t ++sio_oss_write(struct sio_hdl *sh, const void *buf, size_t len) ++{ ++ struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; ++ const unsigned char *data = buf; ++ ssize_t n, todo; ++ ++ todo = len; ++ while ((n = write(hdl->fd, data, todo)) < 0) { ++ if (errno == EINTR) ++ continue; ++ if (errno != EAGAIN) { ++ DPERROR("sio_oss_write: write"); ++ hdl->sio.eof = 1; ++ } ++ return 0; ++ } ++ ++ hdl->play_pos += n; ++ ++ return n; ++} ++ ++static int ++sio_oss_nfds(struct sio_hdl *hdl) ++{ ++ return 1; ++} ++ ++static int ++sio_oss_pollfd(struct sio_hdl *sh, struct pollfd *pfd, int events) ++{ ++ struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; ++ ++ 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; ++} ++ ++int ++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 revents = pfd->revents; ++ ++ 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; ++ 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; ++ 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; ++ if (delta > 0) { ++ _sio_onmove_cb(&hdl->sio, delta); ++ hdl->idelta -= delta; ++ hdl->odelta -= delta; ++ } ++ 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) { ++ case AFMT_S8: ++ ap->le = 1; ++ ap->sig = 1; ++ ap->bits = 8; ++ break; ++ case AFMT_U8: ++ ap->le = 1; ++ ap->sig = 0; ++ ap->bits = 8; ++ break; ++ case AFMT_S16_LE: ++ ap->le = 1; ++ ap->sig = 1; ++ ap->bits = 16; ++ break; ++ case AFMT_S16_BE: ++ ap->le = 0; ++ ap->sig = 1; ++ ap->bits = 16; ++ break; ++ case AFMT_U16_LE: ++ ap->le = 1; ++ ap->sig = 0; ++ ap->bits = 16; ++ break; ++ case AFMT_U16_BE: ++ ap->le = 0; ++ ap->sig = 0; ++ ap->bits = 16; ++ break; ++ case AFMT_S24_LE: ++ ap->le = 1; ++ ap->sig = 1; ++ ap->bits = 24; ++ break; ++ case AFMT_S24_BE: ++ ap->le = 0; ++ ap->sig = 1; ++ ap->bits = 24; ++ break; ++ case AFMT_U24_LE: ++ ap->le = 1; ++ ap->sig = 0; ++ ap->bits = 24; ++ break; ++ case AFMT_U24_BE: ++ ap->le = 0; ++ ap->sig = 0; ++ ap->bits = 24; ++ break; ++ case AFMT_S32_LE: ++ ap->le = 1; ++ ap->sig = 1; ++ ap->bits = 32; ++ break; ++ case AFMT_S32_BE: ++ ap->le = 0; ++ ap->sig = 1; ++ ap->bits = 32; ++ break; ++ case AFMT_U32_LE: ++ ap->le = 1; ++ ap->sig = 0; ++ ap->bits = 32; ++ break; ++ case AFMT_U32_BE: ++ ap->le = 0; ++ ap->sig = 0; ++ ap->bits = 32; ++ break; ++ } ++} ++ ++static int ++sio_oss_swpar_to_fmt(struct audio_swpar *ap) ++{ ++ unsigned int bits = ap->bits; ++ unsigned int sig = ap->sig; ++ unsigned int le = ap->le; ++ ++ switch(bits) { ++ case 8: ++ if (sig) ++ return AFMT_S8; ++ else ++ return AFMT_U8; ++ break; ++ case 16: ++ if (sig) ++ if (le) ++ return AFMT_S16_LE; ++ else ++ return AFMT_S16_BE; ++ else ++ if (le) ++ return AFMT_U16_LE; ++ else ++ return AFMT_U16_BE; ++ break; ++ break; ++ case 24: ++ if (sig) ++ if (le) ++ return AFMT_S24_LE; ++ else ++ return AFMT_S24_BE; ++ else ++ if (le) ++ return AFMT_U24_LE; ++ else ++ return AFMT_U24_BE; ++ break; ++ break; ++ case 32: ++ if (sig) ++ if (le) ++ return AFMT_S32_LE; ++ else ++ return AFMT_S32_BE; ++ else ++ if (le) ++ return AFMT_U32_LE; ++ else ++ return AFMT_U32_BE; ++ break; ++ default: ++ if (sig) ++ if (SIO_LE_NATIVE) ++ return AFMT_S16_LE; ++ else ++ return AFMT_S16_BE; ++ else ++ if (SIO_LE_NATIVE) ++ return AFMT_U16_LE; ++ else ++ return AFMT_U16_BE; ++ } ++} ++ ++static int sio_oss_audio_getpar(struct sio_oss_hdl *hdl, struct audio_swpar *ap) ++{ ++ audio_buf_info bi; ++ ++ *ap = hdl->swpar; ++ ++ return 0; ++} ++ ++static int sio_oss_audio_setpar(struct sio_oss_hdl *hdl, struct audio_swpar *ap) ++{ ++ int fmt = sio_oss_swpar_to_fmt(ap); ++ if (fmt < 0) ++ return -1; ++ ++ if (ioctl(hdl->fd, SNDCTL_DSP_SETFMT, &fmt) < 0) ++ return -1; ++ ++ sio_oss_fmt_to_swpar(fmt, ap); ++ ++ if (ioctl(hdl->fd, SNDCTL_DSP_SPEED, &ap->rate) < 0) ++ 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) ++ return -1; ++ ++ ap->pchan = ap->rchan = chan; ++ ++ 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"); ++ 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; ++} ++ ++#endif /* defined USE_OSS */ diff --git a/audio/sndio/files/patch-libsndio_sio__priv.h b/audio/sndio/files/patch-libsndio_sio__priv.h new file mode 100644 index 000000000000..d8cb0fc3734e --- /dev/null +++ b/audio/sndio/files/patch-libsndio_sio__priv.h @@ -0,0 +1,12 @@ +--- libsndio/sio_priv.h.orig 2015-01-17 23:09:04 UTC ++++ libsndio/sio_priv.h +@@ -69,6 +69,9 @@ struct sio_hdl *_sio_aucat_open(const ch + #ifdef USE_SUN + struct sio_hdl *_sio_sun_open(const char *, unsigned, int); + #endif ++#ifdef USE_OSS ++struct sio_hdl *_sio_oss_open(const char *, unsigned, int); ++#endif + #ifdef USE_ALSA + struct sio_hdl *_sio_alsa_open(const char *, unsigned, int); + #endif diff --git a/audio/sndio/files/sndiod.in b/audio/sndio/files/sndiod.in new file mode 100644 index 000000000000..87814017d3a7 --- /dev/null +++ b/audio/sndio/files/sndiod.in @@ -0,0 +1,32 @@ +#!/bin/sh +# +# $FreeBSD$ +# +# PROVIDE: sndiod +# REQUIRE: NETWORKING sysctl +# BEFORE: DAEMON +# KEYWORD: shutdown + +# By default sndiod will use the audio device from +# hw.snd.default_unit. You can override this by setting sndiod_flags. +# +# To connect to a remote sndiod use e.g. +# sndiod_flags="-f snd@remotehost/0" +# +# To use /dev/dsp5 +# sndiod_flags="-f rsnd/5" + +. /etc/rc.subr + +name=sndiod +rcvar=sndiod_enable + +load_rc_config $name + +_sndiod_devnum=$($SYSCTL -n hw.snd.default_unit) +: ${sndiod_enable="NO"} +: ${sndiod_flags="-f rsnd/$_sndiod_devnum"} + +command="%%PREFIX%%/bin/sndiod" + +run_rc_command "$1" diff --git a/audio/sndio/pkg-descr b/audio/sndio/pkg-descr new file mode 100644 index 000000000000..075b321f0fcb --- /dev/null +++ b/audio/sndio/pkg-descr @@ -0,0 +1,10 @@ +Sndio is a small audio and MIDI framework part of the OpenBSD project. + +It provides an lightweight audio & MIDI server and a fully documented +user-space API to access either the server or directly the hardware in +a uniform way. Sndio is designed to work for desktop applications, +but pays special attention to synchronization mechanisms and +reliability required by music applications. Reliability through +simplicity are part of the project goals. + +WWW: http://www.sndio.org/ diff --git a/audio/sndio/pkg-message b/audio/sndio/pkg-message new file mode 100644 index 000000000000..9da5476417a0 --- /dev/null +++ b/audio/sndio/pkg-message @@ -0,0 +1,29 @@ +sndio's OSS support (i.e. local playback 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 + + sysrc sndiod_enable=YES + +Alternatively 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. + +audio/pulseaudio-module-sndio is a PulseAudio module that allows you +to play to your sndio server. This is useful for ports that have +PulseAudio support but no direct sndio support. diff --git a/audio/sndio/pkg-plist b/audio/sndio/pkg-plist new file mode 100644 index 000000000000..1425a6ddc6de --- /dev/null +++ b/audio/sndio/pkg-plist @@ -0,0 +1,35 @@ +bin/aucat +bin/midicat +bin/sndiod +include/sndio.h +lib/libsndio.so +lib/libsndio.so.6.1 +man/man1/aucat.1.gz +man/man1/midicat.1.gz +man/man3/mio_close.3.gz +man/man3/mio_eof.3.gz +man/man3/mio_nfds.3.gz +man/man3/mio_open.3.gz +man/man3/mio_pollfd.3.gz +man/man3/mio_read.3.gz +man/man3/mio_revents.3.gz +man/man3/mio_write.3.gz +man/man3/sio_close.3.gz +man/man3/sio_eof.3.gz +man/man3/sio_getcap.3.gz +man/man3/sio_getpar.3.gz +man/man3/sio_initpar.3.gz +man/man3/sio_nfds.3.gz +man/man3/sio_onmove.3.gz +man/man3/sio_onvol.3.gz +man/man3/sio_open.3.gz +man/man3/sio_pollfd.3.gz +man/man3/sio_read.3.gz +man/man3/sio_revents.3.gz +man/man3/sio_setpar.3.gz +man/man3/sio_setvol.3.gz +man/man3/sio_start.3.gz +man/man3/sio_stop.3.gz +man/man3/sio_write.3.gz +man/man7/sndio.7.gz +man/man8/sndiod.8.gz |