Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 3 Aug 2016 06:15:41 +0000 (UTC)
From:      Kurt Jaeger <pi@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r419497 - in head: . audio audio/sndio audio/sndio/files
Message-ID:  <201608030615.u736FfWD025344@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: pi
Date: Wed Aug  3 06:15:41 2016
New Revision: 419497
URL: https://svnweb.freebsd.org/changeset/ports/419497

Log:
  New port: audio/sndio
  
  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/
  
  PR:		210124
  Submitted by:	Tobias Kortkamp <t@tobik.me>

Added:
  head/audio/sndio/
  head/audio/sndio/Makefile   (contents, props changed)
  head/audio/sndio/distinfo   (contents, props changed)
  head/audio/sndio/files/
  head/audio/sndio/files/patch-configure   (contents, props changed)
  head/audio/sndio/files/patch-libsndio_Makefile.in   (contents, props changed)
  head/audio/sndio/files/patch-libsndio_sio.c   (contents, props changed)
  head/audio/sndio/files/patch-libsndio_sio__oss.c   (contents, props changed)
  head/audio/sndio/files/patch-libsndio_sio__priv.h   (contents, props changed)
  head/audio/sndio/files/sndiod.in   (contents, props changed)
  head/audio/sndio/pkg-descr   (contents, props changed)
  head/audio/sndio/pkg-message   (contents, props changed)
  head/audio/sndio/pkg-plist   (contents, props changed)
Modified:
  head/GIDs
  head/UIDs
  head/audio/Makefile

Modified: head/GIDs
==============================================================================
--- head/GIDs	Wed Aug  3 02:08:46 2016	(r419496)
+++ head/GIDs	Wed Aug  3 06:15:41 2016	(r419497)
@@ -234,6 +234,7 @@ aox:*:666:
 riak:*:667:
 bnetd:*:700:
 fastnetmon:*:701:
+_sndio:*:702:
 bopm:*:717:
 openxpki:*:777:
 zetacoin:*:780:

Modified: head/UIDs
==============================================================================
--- head/UIDs	Wed Aug  3 02:08:46 2016	(r419496)
+++ head/UIDs	Wed Aug  3 06:15:41 2016	(r419497)
@@ -242,6 +242,7 @@ riakcs:*:668:667::0:0:Riak CS user:/usr/
 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

Modified: head/audio/Makefile
==============================================================================
--- head/audio/Makefile	Wed Aug  3 02:08:46 2016	(r419496)
+++ head/audio/Makefile	Wed Aug  3 06:15:41 2016	(r419497)
@@ -697,6 +697,7 @@
     SUBDIR += smasher
     SUBDIR += snack
     SUBDIR += snd
+    SUBDIR += sndio
     SUBDIR += solfege
     SUBDIR += sonata
     SUBDIR += sooperlooper

Added: head/audio/sndio/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/audio/sndio/Makefile	Wed Aug  3 06:15:41 2016	(r419497)
@@ -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>

Added: head/audio/sndio/distinfo
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/audio/sndio/distinfo	Wed Aug  3 06:15:41 2016	(r419497)
@@ -0,0 +1,3 @@
+TIMESTAMP = 1465315037
+SHA256 (sndio-1.1.0.tar.gz) = fcd7f845ff70f38c2898d737450b8aa3e1bb0afb9d147e8429ef22c0b2c2db57
+SIZE (sndio-1.1.0.tar.gz) = 121018

Added: head/audio/sndio/files/patch-configure
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/audio/sndio/files/patch-configure	Wed Aug  3 06:15:41 2016	(r419497)
@@ -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
+ 

Added: head/audio/sndio/files/patch-libsndio_Makefile.in
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/audio/sndio/files/patch-libsndio_Makefile.in	Wed Aug  3 06:15:41 2016	(r419497)
@@ -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

Added: head/audio/sndio/files/patch-libsndio_sio.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/audio/sndio/files/patch-libsndio_sio.c	Wed Aug  3 06:15:41 2016	(r419497)
@@ -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

Added: head/audio/sndio/files/patch-libsndio_sio__oss.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/audio/sndio/files/patch-libsndio_sio__oss.c	Wed Aug  3 06:15:41 2016	(r419497)
@@ -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)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201608030615.u736FfWD025344>