svn commit: r436589 - in head/audio/portaudio: . files

Tobias Kortkamp tobik at FreeBSD.org
Tue Mar 21 12:05:57 UTC 2017


Author: tobik
Date: Tue Mar 21 12:05:55 2017
New Revision: 436589
URL: https://svnweb.freebsd.org/changeset/ports/436589

Log:
  - Add SNDIO option
  - Reset maintainer after 4 consecutive maintainer timeouts
  - Use *_CONFIGURE_WITH options helper
  - Do not install tests by default
  
  PR:		217385
  Obtained from:	OpenBSD
  Approved by:	lme (mentor), maintainer timeout (3 weeks)
  Differential Revision:	https://reviews.freebsd.org/D10072

Added:
  head/audio/portaudio/files/pa_sndio.c   (contents, props changed)
  head/audio/portaudio/files/patch-Makefile.in   (contents, props changed)
  head/audio/portaudio/files/patch-configure.in   (contents, props changed)
  head/audio/portaudio/files/patch-include_portaudio.h   (contents, props changed)
  head/audio/portaudio/files/patch-src_os_unix_pa__unix__hostapis.c   (contents, props changed)
Modified:
  head/audio/portaudio/Makefile

Modified: head/audio/portaudio/Makefile
==============================================================================
--- head/audio/portaudio/Makefile	Tue Mar 21 11:59:21 2017	(r436588)
+++ head/audio/portaudio/Makefile	Tue Mar 21 12:05:55 2017	(r436589)
@@ -3,26 +3,24 @@
 
 PORTNAME=	portaudio
 DISTVERSION=	19_20140130
-PORTREVISION=	5
+PORTREVISION=	6
 CATEGORIES=	audio
 MASTER_SITES=	http://www.portaudio.com/archives/
 DISTNAME=	pa_stable_v${DISTVERSION}
 
-MAINTAINER=	koalative at gmail.com
+MAINTAINER=	ports at FreeBSD.org
 COMMENT=	Portable cross-platform Audio API
 
 LICENSE=	MIT
 LICENSE_FILE=	${WRKSRC}/LICENSE.txt
 
-USES=		dos2unix gmake libtool pathfix pkgconfig tar:tgz
+USES=	autoreconf dos2unix gmake localbase:ldflags libtool pathfix \
+	pkgconfig tar:tgz
 GNU_CONFIGURE=	yes
 CONFIGURE_ARGS=	PKG_CONFIG_LIBDIR=${PREFIX}/libdata/pkgconfig \
 		--without-alsa
 USE_LDCONFIG=	yes
 
-CPPFLAGS+=	-I${LOCALBASE}/include
-LDFLAGS+=	-lpthread -L${LOCALBASE}/lib
-
 WRKSRC=		${WRKDIR}/${PORTNAME}
 
 PORTDOCS=	*
@@ -31,8 +29,7 @@ PORTEXAMPLES=	*
 DOCSRCDIR1=	${WRKSRC}
 DOC_FILES1=	README.txt index.html
 
-OPTIONS_DEFINE=	DOCS DOXYGEN EXAMPLES JACK PATEST
-OPTIONS_DEFAULT=PATEST
+OPTIONS_DEFINE=	DOCS DOXYGEN EXAMPLES JACK PATEST SNDIO
 
 PATEST_DESC=	PortAudio Test Programs
 DOXYGEN_DESC=	Install API documentation (requires DOCS)
@@ -40,14 +37,20 @@ DOXYGEN_DESC=	Install API documentation 
 OPTIONS_SUB=	yes
 
 JACK_LIB_DEPENDS=	libjack.so:audio/jack
-JACK_CONFIGURE_ON=	--with-jack
-JACK_CONFIGURE_OFF=	--without-jack
+JACK_CONFIGURE_WITH=	jack
 
 PATEST_BIN=	pa_m* paqa_* patest*
 
+SNDIO_LIB_DEPENDS=	libsndio.so:audio/sndio
+SNDIO_CONFIGURE_WITH=	sndio
+
 DOXYGEN_IMPLIES=	DOCS
 DOXYGEN_BUILD_DEPENDS=	doxygen:devel/doxygen
 
+post-extract:
+	@${MKDIR} ${WRKSRC}/src/hostapi/sndio
+	@${CP} ${FILESDIR}/pa_sndio.c ${WRKSRC}/src/hostapi/sndio
+
 post-patch:
 	@${REINPLACE_CMD} -e 's|machine/soundcard.h|sys/soundcard.h|' ${WRKSRC}/configure.in \
 		${WRKSRC}/src/hostapi/oss/pa_unix_oss.c ${WRKSRC}/src/SConscript

Added: head/audio/portaudio/files/pa_sndio.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/audio/portaudio/files/pa_sndio.c	Tue Mar 21 12:05:55 2017	(r436589)
@@ -0,0 +1,713 @@
+/*
+ * Copyright (c) 2009 Alexandre Ratchov <alex at 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.
+ */
+#include <sys/types.h>
+#include <pthread.h>
+#include <poll.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sndio.h>
+
+#include "pa_util.h"
+#include "pa_hostapi.h"
+#include "pa_stream.h"
+#include "pa_process.h"
+#include "pa_allocation.h"
+
+#if 0
+#define DPR(...) do { fprintf(stderr, __VA_ARGS__); } while (0)
+#else
+#define DPR(...) do {} while (0)
+#endif
+
+/*
+ * per-stream data
+ */
+typedef struct PaSndioStream
+{
+	PaUtilStreamRepresentation base;
+	PaUtilBufferProcessor bufproc;	/* format conversion */
+	struct sio_hdl *hdl;		/* handle for device i/o */
+	struct sio_par par;		/* current device parameters */	
+	unsigned mode;			/* SIO_PLAY, SIO_REC or both */
+	int stopped;			/* stop requested or not started */
+	int active;			/* thread is running */
+	unsigned long long realpos;	/* frame number h/w is processing */
+	char *rbuf, *wbuf;		/* bounce buffers for conversions */
+	unsigned long long rpos, wpos;	/* bytes read/written */
+	pthread_t thread;		/* thread of the callback interface */
+} PaSndioStream;
+
+/*
+ * api "class" data, common to all streams
+ */
+typedef struct PaSndioHostApiRepresentation
+{
+	PaUtilHostApiRepresentation base;
+	PaUtilStreamInterface callback;
+	PaUtilStreamInterface blocking;
+	/*
+	 * sndio has no device discovery mechanism, so expose only
+	 * the default device, the user will have a chance to change it
+	 * using the environment variable
+	 */
+	PaDeviceInfo *infos[1], default_info;
+} PaSndioHostApiRepresentation;
+
+/*
+ * callback invoked when blocks are processed by the hardware
+ */
+static void
+sndioOnMove(void *addr, int delta)
+{
+	PaSndioStream *s = (PaSndioStream *)addr;
+
+	s->realpos += delta;
+}
+
+/*
+ * convert PA encoding to sndio encoding, return true on success
+ */
+static int
+sndioSetFmt(struct sio_par *sio, PaSampleFormat fmt)
+{
+	switch (fmt & ~paNonInterleaved) {
+	case paInt32:
+		sio->sig = 1;
+		sio->bits = 32;
+		break;
+	case paInt24:
+		sio->sig = 1;
+		sio->bits = 24;
+		sio->bps = 3;	/* paInt24 is packed format */
+		break;
+	case paInt16:
+	case paFloat32:
+		sio->sig = 1;
+		sio->bits = 16;
+		break;
+	case paInt8:
+		sio->sig = 1;
+		sio->bits = 8;
+		break;
+	case paUInt8:
+		sio->sig = 0;
+		sio->bits = 8;
+		break;
+	default:
+		DPR("sndioSetFmt: %x: unsupported\n", fmt);
+		return 0;
+	}
+	sio->le = SIO_LE_NATIVE;
+	return 1;
+}
+
+/*
+ * convert sndio encoding to PA encoding, return true on success
+ */
+static int
+sndioGetFmt(struct sio_par *sio, PaSampleFormat *fmt)
+{
+	if ((sio->bps * 8 != sio->bits && !sio->msb) ||
+	    (sio->bps > 1 && sio->le != SIO_LE_NATIVE)) {
+		DPR("sndioGetFmt: bits = %u, le = %u, msb = %u, bps = %u\n",
+		    sio->bits, sio->le, sio->msb, sio->bps);
+		return 0;
+	}
+
+	switch (sio->bits) {
+	case 32:
+		if (!sio->sig)
+			return 0;
+		*fmt = paInt32;
+		break;
+	case 24:
+		if (!sio->sig)
+			return 0;
+		*fmt = (sio->bps == 3) ? paInt24 : paInt32;
+		break;
+	case 16:
+		if (!sio->sig)
+			return 0;
+		*fmt = paInt16;
+		break;
+	case 8:
+		*fmt = sio->sig ? paInt8 : paUInt8;
+		break;
+	default:
+		DPR("sndioGetFmt: %u: unsupported\n", sio->bits);
+		return 0;
+	}
+	return 1;
+}
+
+/*
+ * I/O loop for callback interface
+ */
+static void *
+sndioThread(void *arg)
+{
+	PaSndioStream *s = (PaSndioStream *)arg;
+	PaStreamCallbackTimeInfo ti;
+	unsigned char *data;
+	unsigned todo, rblksz, wblksz;
+	int n, result;
+	
+	rblksz = s->par.round * s->par.rchan * s->par.bps;
+	wblksz = s->par.round * s->par.pchan * s->par.bps;
+	
+	DPR("sndioThread: mode = %x, round = %u, rblksz = %u, wblksz = %u\n",
+	    s->mode, s->par.round, rblksz, wblksz);
+	
+	while (!s->stopped) {
+		if (s->mode & SIO_REC) {
+			todo = rblksz;
+			data = s->rbuf;
+			while (todo > 0) {
+				n = sio_read(s->hdl, data, todo);
+				if (n == 0) {
+					DPR("sndioThread: sio_read failed\n");
+					goto failed;
+				}
+				todo -= n;
+				data += n;
+			}
+			s->rpos += s->par.round;
+			ti.inputBufferAdcTime = 
+			    (double)s->realpos / s->par.rate;
+		}
+		if (s->mode & SIO_PLAY) {
+			ti.outputBufferDacTime =
+			    (double)(s->realpos + s->par.bufsz) / s->par.rate;
+		}
+		ti.currentTime = s->realpos / (double)s->par.rate;
+		PaUtil_BeginBufferProcessing(&s->bufproc, &ti, 0);
+		if (s->mode & SIO_PLAY) {
+			PaUtil_SetOutputFrameCount(&s->bufproc, s->par.round);
+			PaUtil_SetInterleavedOutputChannels(&s->bufproc,
+			    0, s->wbuf, s->par.pchan);
+		}
+		if (s->mode & SIO_REC) {
+			PaUtil_SetInputFrameCount(&s->bufproc, s->par.round);
+			PaUtil_SetInterleavedInputChannels(&s->bufproc,
+			    0, s->rbuf, s->par.rchan);
+		}
+		result = paContinue;
+		n = PaUtil_EndBufferProcessing(&s->bufproc, &result);
+		if (n != s->par.round) {
+			DPR("sndioThread: %d < %u frames, result = %d\n",
+			    n, s->par.round, result);
+		}
+		if (result != paContinue) {
+			break;
+		}
+		if (s->mode & SIO_PLAY) {
+			n = sio_write(s->hdl, s->wbuf, wblksz);
+			if (n < wblksz) {
+				DPR("sndioThread: sio_write failed\n");
+				goto failed;
+			}
+			s->wpos += s->par.round;
+		}
+	}
+ failed:
+	s->active = 0;
+	DPR("sndioThread: done\n");
+}
+
+static PaError
+OpenStream(struct PaUtilHostApiRepresentation *hostApi,
+    PaStream **stream,
+    const PaStreamParameters *inputPar,
+    const PaStreamParameters *outputPar,
+    double sampleRate,
+    unsigned long framesPerBuffer,
+    PaStreamFlags streamFlags,
+    PaStreamCallback *streamCallback,
+    void *userData)
+{
+	PaSndioHostApiRepresentation *sndioHostApi = (PaSndioHostApiRepresentation *)hostApi;
+	PaSndioStream *s;
+	PaError err;
+	struct sio_hdl *hdl;
+	struct sio_par par;
+	unsigned mode;
+	int inch, onch;
+	PaSampleFormat ifmt, ofmt, siofmt;
+
+	DPR("OpenStream:\n");
+
+	mode = 0;
+	inch = onch = 0;
+	ifmt = ofmt = 0;
+	sio_initpar(&par);
+
+	if (outputPar && outputPar->channelCount > 0) {
+		if (outputPar->device != 0) {
+			DPR("OpenStream: %d: bad output device\n", outputPar->device);
+			return paInvalidDevice;
+		}
+		if (outputPar->hostApiSpecificStreamInfo) {
+			DPR("OpenStream: output specific info\n");
+			return paIncompatibleHostApiSpecificStreamInfo;
+		}
+		if (!sndioSetFmt(&par, outputPar->sampleFormat)) {
+			return paSampleFormatNotSupported;
+		}
+		ofmt = outputPar->sampleFormat;
+		onch = par.pchan = outputPar->channelCount;
+		mode |= SIO_PLAY;
+	}
+	if (inputPar && inputPar->channelCount > 0) {
+		if (inputPar->device != 0) {
+			DPR("OpenStream: %d: bad input device\n", inputPar->device);
+			return paInvalidDevice;
+		}
+		if (inputPar->hostApiSpecificStreamInfo) {
+			DPR("OpenStream: input specific info\n");
+			return paIncompatibleHostApiSpecificStreamInfo;
+		}
+		if (!sndioSetFmt(&par, inputPar->sampleFormat)) {
+			return paSampleFormatNotSupported;
+		}
+		ifmt = inputPar->sampleFormat;
+		inch = par.rchan = inputPar->channelCount;
+		mode |= SIO_REC;
+	}
+	par.rate = sampleRate;
+	if (framesPerBuffer != paFramesPerBufferUnspecified)
+		par.round = framesPerBuffer;
+
+	DPR("OpenStream: mode = %x, trying rate = %u\n", mode, par.rate);
+
+	hdl = sio_open(SIO_DEVANY, mode, 0);
+	if (hdl == NULL)
+		return paUnanticipatedHostError;
+	if (!sio_setpar(hdl, &par)) {
+		sio_close(hdl);
+		return paUnanticipatedHostError;
+	}
+	if (!sio_getpar(hdl, &par)) {
+		sio_close(hdl);
+		return paUnanticipatedHostError;
+	}
+	if (!sndioGetFmt(&par, &siofmt)) {
+		sio_close(hdl);
+		return paSampleFormatNotSupported;
+	}
+	if ((mode & SIO_REC) && par.rchan != inputPar->channelCount) {
+		DPR("OpenStream: rchan(%u) != %d\n", par.rchan, inputPar->channelCount);
+		sio_close(hdl);
+		return paInvalidChannelCount;
+	}
+	if ((mode & SIO_PLAY) && par.pchan != outputPar->channelCount) {
+		DPR("OpenStream: pchan(%u) != %d\n", par.pchan, outputPar->channelCount);
+		sio_close(hdl);
+		return paInvalidChannelCount;
+	}
+	if ((double)par.rate < sampleRate * 0.995 ||
+	    (double)par.rate > sampleRate * 1.005) {
+		DPR("OpenStream: rate(%u) != %g\n", par.rate, sampleRate);
+		sio_close(hdl);
+		return paInvalidSampleRate;
+	}
+	
+	s = (PaSndioStream *)PaUtil_AllocateMemory(sizeof(PaSndioStream));
+	if (s == NULL) {
+		sio_close(hdl);
+		return paInsufficientMemory;
+	}
+	PaUtil_InitializeStreamRepresentation(&s->base, 
+	    streamCallback ? &sndioHostApi->callback : &sndioHostApi->blocking,
+	    streamCallback, userData);
+	DPR("inch = %d, onch = %d, ifmt = %x, ofmt = %x\n", 
+	    inch, onch, ifmt, ofmt);
+	err = PaUtil_InitializeBufferProcessor(&s->bufproc,
+	    inch, ifmt, siofmt,
+	    onch, ofmt, siofmt,
+	    sampleRate,
+	    streamFlags,
+	    framesPerBuffer,
+	    par.round,
+	    paUtilFixedHostBufferSize, 
+	    streamCallback, userData);
+	if (err) {
+		DPR("OpenStream: PaUtil_InitializeBufferProcessor failed\n");
+		PaUtil_FreeMemory(s);
+		sio_close(hdl);
+		return err;
+	}
+	if (mode & SIO_REC) {
+		s->rbuf = malloc(par.round * par.rchan * par.bps);
+		if (s->rbuf == NULL) {
+			DPR("OpenStream: failed to allocate rbuf\n");
+			PaUtil_FreeMemory(s);
+			sio_close(hdl);
+			return paInsufficientMemory;
+		}
+	}
+	if (mode & SIO_PLAY) {
+		s->wbuf = malloc(par.round * par.pchan * par.bps);
+		if (s->wbuf == NULL) {
+			DPR("OpenStream: failed to allocate wbuf\n");
+			free(s->rbuf);
+			PaUtil_FreeMemory(s);
+			sio_close(hdl);
+			return paInsufficientMemory;
+		}
+	}	
+	s->base.streamInfo.inputLatency = 0;
+	s->base.streamInfo.outputLatency = (mode & SIO_PLAY) ?
+	    (double)(par.bufsz + PaUtil_GetBufferProcessorOutputLatencyFrames(&s->bufproc)) / (double)par.rate : 0;
+	s->base.streamInfo.sampleRate = par.rate;
+	s->active = 0;
+	s->stopped = 1;
+	s->mode = mode;
+	s->hdl = hdl;
+	s->par = par;
+	*stream = s;	
+	DPR("OpenStream: done\n");
+	return paNoError;
+}
+
+static PaError
+BlockingReadStream(PaStream *stream, void *data, unsigned long numFrames)
+{
+	PaSndioStream *s = (PaSndioStream *)stream;
+	unsigned n, res, todo;
+	void *buf;
+	
+	while (numFrames > 0) {
+		n = s->par.round;
+		if (n > numFrames)
+			n = numFrames;
+		buf = s->rbuf;
+		todo = n * s->par.rchan * s->par.bps;
+		while (todo > 0) {
+			res = sio_read(s->hdl, buf, todo);
+			if (res == 0)
+				return paUnanticipatedHostError;
+			buf = (char *)buf + res;
+			todo -= res;
+		}
+		s->rpos += n;
+		PaUtil_SetInputFrameCount(&s->bufproc, n);
+		PaUtil_SetInterleavedInputChannels(&s->bufproc, 0, s->rbuf, s->par.rchan);
+		res = PaUtil_CopyInput(&s->bufproc, &data, n);
+		if (res != n) {
+			DPR("BlockingReadStream: copyInput: %u != %u\n");
+			return paUnanticipatedHostError;
+		}
+		numFrames -= n;
+	}
+	return paNoError;
+}
+
+static PaError
+BlockingWriteStream(PaStream* stream, const void *data, unsigned long numFrames)
+{
+	PaSndioStream *s = (PaSndioStream *)stream;
+	unsigned n, res;
+
+	while (numFrames > 0) {
+		n = s->par.round;
+		if (n > numFrames)
+			n = numFrames;
+		PaUtil_SetOutputFrameCount(&s->bufproc, n);
+		PaUtil_SetInterleavedOutputChannels(&s->bufproc, 0, s->wbuf, s->par.pchan);
+		res = PaUtil_CopyOutput(&s->bufproc, &data, n);
+		if (res != n) {
+			DPR("BlockingWriteStream: copyOutput: %u != %u\n");
+			return paUnanticipatedHostError;
+		}
+		res = sio_write(s->hdl, s->wbuf, n * s->par.pchan * s->par.bps);
+		if (res == 0)
+			return paUnanticipatedHostError;		
+		s->wpos += n;
+		numFrames -= n;
+	}
+	return paNoError;
+}
+
+static signed long
+BlockingGetStreamReadAvailable(PaStream *stream)
+{
+	PaSndioStream *s = (PaSndioStream *)stream;
+	struct pollfd pfd;
+	int n, events;
+
+	n = sio_pollfd(s->hdl, &pfd, POLLIN);
+	while (poll(&pfd, n, 0) < 0) {
+		if (errno == EINTR)
+			continue;
+		perror("poll");
+		abort();
+	}
+	events = sio_revents(s->hdl, &pfd);
+	if (!(events & POLLIN))
+		return 0;
+
+	return s->realpos - s->rpos;
+}
+
+static signed long
+BlockingGetStreamWriteAvailable(PaStream *stream)
+{
+	PaSndioStream *s = (PaSndioStream *)stream;
+	struct pollfd pfd;
+	int n, events;
+
+	n = sio_pollfd(s->hdl, &pfd, POLLOUT);
+	while (poll(&pfd, n, 0) < 0) {
+		if (errno == EINTR)
+			continue;
+		perror("poll");
+		abort();
+	}
+	events = sio_revents(s->hdl, &pfd);
+	if (!(events & POLLOUT))
+		return 0;
+
+	return s->par.bufsz - (s->wpos - s->realpos);
+}
+
+static PaError
+BlockingWaitEmpty( PaStream *stream )
+{
+	PaSndioStream *s = (PaSndioStream *)stream;
+
+	/*
+	 * drain playback buffers; sndio always does it in background
+	 * and there is no way to wait for completion
+	 */
+	DPR("BlockingWaitEmpty: s=%d, a=%d\n", s->stopped, s->active);
+
+	return paNoError;
+}
+
+static PaError
+StartStream(PaStream *stream)
+{
+	PaSndioStream *s = (PaSndioStream *)stream;
+	unsigned primes, wblksz;
+	int err;
+
+	DPR("StartStream: s=%d, a=%d\n", s->stopped, s->active);
+
+	if (!s->stopped) {
+		DPR("StartStream: already started\n");
+		return paNoError;
+	}
+	s->stopped = 0;
+	s->active = 1;
+	s->realpos = 0;
+	s->wpos = 0;
+	s->rpos = 0;
+	PaUtil_ResetBufferProcessor(&s->bufproc);
+	if (!sio_start(s->hdl))
+		return paUnanticipatedHostError;
+
+	/*
+	 * send a complete buffer of silence
+	 */
+	if (s->mode & SIO_PLAY) {
+		wblksz = s->par.round * s->par.pchan * s->par.bps;
+		memset(s->wbuf, 0, wblksz);
+		for (primes = s->par.bufsz / s->par.round; primes > 0; primes--)
+			s->wpos += sio_write(s->hdl, s->wbuf, wblksz);
+	}
+	if (s->base.streamCallback) {
+		err = pthread_create(&s->thread, NULL, sndioThread, s);
+		if (err) {
+			DPR("SndioStartStream: couldn't create thread\n");
+			return paUnanticipatedHostError;
+		}
+		DPR("StartStream: started...\n");
+	}
+	return paNoError;
+}
+
+static PaError
+StopStream(PaStream *stream)
+{
+	PaSndioStream *s = (PaSndioStream *)stream;
+	void *ret;
+	int err;
+
+	DPR("StopStream: s=%d, a=%d\n", s->stopped, s->active);
+
+	if (s->stopped) {
+		DPR("StartStream: already started\n");
+		return paNoError;
+	}
+	s->stopped = 1;
+	if (s->base.streamCallback) {
+		err = pthread_join(s->thread, &ret);
+		if (err) {
+			DPR("SndioStop: couldn't join thread\n");
+			return paUnanticipatedHostError;
+		}
+	}
+	if (!sio_stop(s->hdl))
+		return paUnanticipatedHostError;
+	return paNoError;
+}
+
+static PaError
+CloseStream(PaStream *stream)
+{
+	PaSndioStream *s = (PaSndioStream *)stream;
+
+	DPR("CloseStream:\n");
+
+	if (!s->stopped)
+		StopStream(stream);
+
+	if (s->mode & SIO_REC)
+		free(s->rbuf);
+	if (s->mode & SIO_PLAY)
+		free(s->wbuf);
+	sio_close(s->hdl);
+        PaUtil_TerminateStreamRepresentation(&s->base);
+	PaUtil_TerminateBufferProcessor(&s->bufproc);
+	PaUtil_FreeMemory(s);
+	return paNoError;
+}
+
+static PaError
+AbortStream(PaStream *stream)
+{
+	DPR("AbortStream:\n");
+
+	return StopStream(stream);
+}
+
+static PaError
+IsStreamStopped(PaStream *stream)
+{
+	PaSndioStream *s = (PaSndioStream *)stream;
+
+	//DPR("IsStreamStopped: s=%d, a=%d\n", s->stopped, s->active);
+
+	return s->stopped;
+}
+
+static PaError
+IsStreamActive(PaStream *stream)
+{
+	PaSndioStream *s = (PaSndioStream *)stream;
+
+	//DPR("IsStreamActive: s=%d, a=%d\n", s->stopped, s->active);
+
+	return s->active;
+}
+
+static PaTime
+GetStreamTime(PaStream *stream)
+{
+	PaSndioStream *s = (PaSndioStream *)stream;
+
+	return (double)s->realpos / s->base.streamInfo.sampleRate;
+}
+
+static PaError
+IsFormatSupported(struct PaUtilHostApiRepresentation *hostApi,
+    const PaStreamParameters *inputPar,
+    const PaStreamParameters *outputPar,
+    double sampleRate)
+{
+	return paFormatIsSupported;
+}
+
+static void
+Terminate(struct PaUtilHostApiRepresentation *hostApi)
+{
+	PaUtil_FreeMemory(hostApi);
+}
+
+PaError
+PaSndio_Initialize(PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex)
+{
+	PaSndioHostApiRepresentation *sndioHostApi;
+	PaDeviceInfo *info;
+	struct sio_hdl *hdl;
+	
+	DPR("PaSndio_Initialize: initializing...\n");
+
+	/* unusable APIs should return paNoError and a NULL hostApi */
+	*hostApi = NULL;
+
+	sndioHostApi = PaUtil_AllocateMemory(sizeof(PaSndioHostApiRepresentation));
+	if (sndioHostApi == NULL)
+		return paNoError;
+
+	info = &sndioHostApi->default_info;
+	info->structVersion = 2;
+	info->name = "default";
+	info->hostApi = hostApiIndex;
+	info->maxInputChannels = 128;
+	info->maxOutputChannels = 128;
+	info->defaultLowInputLatency = 0.01;
+	info->defaultLowOutputLatency = 0.01;
+	info->defaultHighInputLatency = 0.5;
+	info->defaultHighOutputLatency = 0.5;
+	info->defaultSampleRate = 48000;
+	sndioHostApi->infos[0] = info;
+	
+	*hostApi = &sndioHostApi->base;
+	(*hostApi)->info.structVersion = 1;
+	(*hostApi)->info.type = paSndio;
+	(*hostApi)->info.name = "sndio";
+	(*hostApi)->info.deviceCount = 1;
+	(*hostApi)->info.defaultInputDevice = 0;
+	(*hostApi)->info.defaultOutputDevice = 0;
+	(*hostApi)->deviceInfos = sndioHostApi->infos;
+	(*hostApi)->Terminate = Terminate;
+	(*hostApi)->OpenStream = OpenStream;
+	(*hostApi)->IsFormatSupported = IsFormatSupported;
+	
+	PaUtil_InitializeStreamInterface(&sndioHostApi->blocking,
+	    CloseStream,
+	    StartStream,
+	    StopStream,
+	    AbortStream,
+	    IsStreamStopped,
+	    IsStreamActive,
+	    GetStreamTime,
+	    PaUtil_DummyGetCpuLoad,
+	    BlockingReadStream,
+	    BlockingWriteStream,
+	    BlockingGetStreamReadAvailable,
+	    BlockingGetStreamWriteAvailable);
+
+	PaUtil_InitializeStreamInterface(&sndioHostApi->callback,
+	    CloseStream,
+	    StartStream,
+	    StopStream,
+	    AbortStream,
+	    IsStreamStopped,
+	    IsStreamActive,
+	    GetStreamTime,
+	    PaUtil_DummyGetCpuLoad,
+	    PaUtil_DummyRead,
+	    PaUtil_DummyWrite,
+	    PaUtil_DummyGetReadAvailable,
+	    PaUtil_DummyGetWriteAvailable);
+
+	DPR("PaSndio_Initialize: done\n");
+	return paNoError;
+}

Added: head/audio/portaudio/files/patch-Makefile.in
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/audio/portaudio/files/patch-Makefile.in	Tue Mar 21 12:05:55 2017	(r436589)
@@ -0,0 +1,11 @@
+$OpenBSD: patch-Makefile_in,v 1.4 2013/03/12 00:59:50 brad Exp $
+--- Makefile.in.orig	2016-06-22 08:28:31 UTC
++++ Makefile.in
+@@ -146,6 +146,7 @@ SRC_DIRS = \
+ 	src/hostapi/dsound \
+ 	src/hostapi/jack \
+ 	src/hostapi/oss \
++	src/hostapi/sndio \
+ 	src/hostapi/wasapi \
+ 	src/hostapi/wdmks \
+ 	src/hostapi/wmme \

Added: head/audio/portaudio/files/patch-configure.in
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/audio/portaudio/files/patch-configure.in	Tue Mar 21 12:05:55 2017	(r436589)
@@ -0,0 +1,47 @@
+$OpenBSD: patch-configure_in,v 1.4 2014/09/13 04:56:28 bentley Exp $
+--- configure.in.orig	2016-06-22 08:28:31 UTC
++++ configure.in
+@@ -24,6 +24,10 @@ AC_ARG_WITH(alsa,
+             AS_HELP_STRING([--with-alsa], [Enable support for ALSA @<:@autodetect@:>@]),
+             [with_alsa=$withval])
+ 
++AC_ARG_WITH(sndio,
++            AS_HELP_STRING([--with-sndio], [Enable support for sndio @<:@autodetect@:>@]),
++            [with_sndio=$withval])
++
+ AC_ARG_WITH(jack,
+             AS_HELP_STRING([--with-jack], [Enable support for JACK @<:@autodetect@:>@]),
+             [with_jack=$withval])
+@@ -120,6 +124,10 @@ have_alsa=no
+ if test "x$with_alsa" != "xno"; then
+     AC_CHECK_LIB(asound, snd_pcm_open, have_alsa=yes, have_alsa=no)
+ fi
++have_sndio=no
++if test "x$with_sndio" != "xno"; then
++    AC_CHECK_LIB(sndio, sio_open, have_sndio=yes, have_sndio=no)
++fi
+ have_asihpi=no
+ if test "x$with_asihpi" != "xno"; then
+     AC_CHECK_LIB(hpi, HPI_SubSysCreate, have_asihpi=yes, have_asihpi=no, -lm)
+@@ -397,6 +405,13 @@ case "${host_os}" in
+            AC_DEFINE(PA_USE_ALSA,1)
+         fi
+ 
++        if [[ "$have_sndio" = "yes" -a "$with_sndio" != "no" ]] ; then
++           DLL_LIBS="$DLL_LIBS -lsndio"
++           LIBS="$LIBS -lsndio"
++           OTHER_OBJS="$OTHER_OBJS src/hostapi/sndio/pa_sndio.o"
++           AC_DEFINE(PA_USE_SNDIO,1)
++        fi
++
+         if [[ "$have_jack" = "yes" ] && [ "$with_jack" != "no" ]] ; then
+            DLL_LIBS="$DLL_LIBS $JACK_LIBS"
+            CFLAGS="$CFLAGS $JACK_CFLAGS"
+@@ -500,6 +515,7 @@ case "$target_os" in
+         ;;
+      *)
+ 	AC_MSG_RESULT([
++  Sndio ....................... $have_sndio
+   OSS ......................... $have_oss
+   JACK ........................ $have_jack
+ ])

Added: head/audio/portaudio/files/patch-include_portaudio.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/audio/portaudio/files/patch-include_portaudio.h	Tue Mar 21 12:05:55 2017	(r436589)
@@ -0,0 +1,13 @@
+$OpenBSD: patch-include_portaudio_h,v 1.2 2013/03/12 00:59:50 brad Exp $
+--- include/portaudio.h.orig	2016-06-22 08:28:31 UTC
++++ include/portaudio.h
+@@ -236,7 +236,8 @@ typedef enum PaHostApiTypeId
+     paWDMKS=11,
+     paJACK=12,
+     paWASAPI=13,
+-    paAudioScienceHPI=14
++    paAudioScienceHPI=14,
++    paSndio=15
+ } PaHostApiTypeId;
+ 
+ 

Added: head/audio/portaudio/files/patch-src_os_unix_pa__unix__hostapis.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/audio/portaudio/files/patch-src_os_unix_pa__unix__hostapis.c	Tue Mar 21 12:05:55 2017	(r436589)
@@ -0,0 +1,26 @@
+$OpenBSD: patch-src_os_unix_pa_unix_hostapis_c,v 1.2 2013/03/12 00:59:50 brad Exp $
+
+Difference to OpenBSD patch: PA_USE_SNDIO has been moved before
+PA_USE_OSS, so that portaudio prefers the sndio output.
+
+--- src/os/unix/pa_unix_hostapis.c.orig	2016-06-22 08:28:31 UTC
++++ src/os/unix/pa_unix_hostapis.c
+@@ -44,6 +44,7 @@
+ 
+ PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
+ PaError PaAlsa_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
++PaError PaSndio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
+ PaError PaOSS_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
+ /* Added for IRIX, Pieter, oct 2, 2003: */
+ PaError PaSGI_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
+@@ -69,6 +70,10 @@ PaUtilHostApiInitializer *paHostApiIniti
+ 
+ #else   /* __linux__ */
+ 
++#ifdef PA_USE_SNDIO
++	PaSndio_Initialize,
++#endif
++
+ #if PA_USE_OSS
+         PaOSS_Initialize,
+ #endif


More information about the svn-ports-head mailing list