commit: 049c77997adbae7ec417945e23547291f0805e06
parent: 056c5b086ae297613ffacdd019cb8e3a0aa08af2
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Sat, 30 May 2020 15:00:04 +0200
media-libs/portaudio: Bump rev and patches
Diffstat:
5 files changed, 884 insertions(+), 892 deletions(-)
diff --git a/media-libs/portaudio/files/portaudio-19.06.00-AR.patch b/media-libs/portaudio/files/portaudio-19.06.00-AR.patch
@@ -0,0 +1,14 @@
+Accept relative paths to AR as well.
+
+https://bugs.gentoo.org/720966
+--- a/configure.in
++++ b/configure.in
+@@ -105,7 +105,7 @@ AC_LIBTOOL_WIN32_DLL
+ AC_PROG_LIBTOOL
+ AC_PROG_INSTALL
+ AC_PROG_LN_S
+-AC_PATH_PROG(AR, ar, no)
++AC_CHECK_PROG(AR, ar, no)
+ if [[ $AR = "no" ]] ; then
+ AC_MSG_ERROR("Could not find ar - needed to create a library")
+ fi
diff --git a/media-libs/portaudio/files/portaudio-19.06.00-pa_sndio.c b/media-libs/portaudio/files/portaudio-19.06.00-pa_sndio.c
@@ -0,0 +1,766 @@
+/*
+ * Copyright (c) 2009 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.
+ */
+#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 and PortAudio has
+ * no way of accepting raw device strings from users.
+ * Normally we just expose the default device, which can be
+ * changed via the AUDIODEVICE environment variable, but we
+ * also allow specifying a list of up to 16 devices via the
+ * PA_SNDIO_AUDIODEVICES environment variable.
+ *
+ * Example:
+ * PA_SNDIO_AUDIODEVICES=default:snd/0.monitor:snd@remote/0
+ */
+#define PA_SNDIO_AUDIODEVICES_MAX 16
+ PaDeviceInfo device_info[PA_SNDIO_AUDIODEVICES_MAX];
+ PaDeviceInfo *infos[PA_SNDIO_AUDIODEVICES_MAX];
+ char *audiodevices;
+} 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");
+ return NULL;
+}
+
+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;
+ const char *dev;
+
+ DPR("OpenStream:\n");
+
+ mode = 0;
+ inch = onch = 0;
+ ifmt = ofmt = 0;
+ sio_initpar(&par);
+
+ if (outputPar && outputPar->channelCount > 0) {
+ if (outputPar->device >= sndioHostApi->base.info.deviceCount) {
+ 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 >= sndioHostApi->base.info.deviceCount) {
+ 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);
+
+ if (outputPar) {
+ dev = sndioHostApi->device_info[outputPar->device].name;
+ } else if (inputPar) {
+ dev = sndioHostApi->device_info[inputPar->device].name;
+ } else {
+ return paUnanticipatedHostError;
+ }
+ hdl = sio_open(dev, 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)
+{
+ PaSndioHostApiRepresentation *sndioHostApi;
+ sndioHostApi = (PaSndioHostApiRepresentation *)hostApi;
+ free(sndioHostApi->audiodevices);
+ PaUtil_FreeMemory(hostApi);
+}
+
+static void
+InitDeviceInfo(PaDeviceInfo *info, PaHostApiIndex hostApiIndex, const char *name)
+{
+ info->structVersion = 2;
+ info->name = name;
+ 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;
+}
+
+PaError
+PaSndio_Initialize(PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex)
+{
+ PaSndioHostApiRepresentation *sndioHostApi;
+ PaDeviceInfo *info;
+ struct sio_hdl *hdl;
+ char *audiodevices;
+ char *device;
+ size_t deviceCount;
+
+ 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;
+
+ // Add default device
+ info = &sndioHostApi->device_info[0];
+ InitDeviceInfo(info, hostApiIndex, SIO_DEVANY);
+ sndioHostApi->infos[0] = info;
+ deviceCount = 1;
+
+ // Add additional devices as specified in the PA_SNDIO_AUDIODEVICES
+ // environment variable as a colon separated list
+ sndioHostApi->audiodevices = NULL;
+ audiodevices = getenv("PA_SNDIO_AUDIODEVICES");
+ if (audiodevices != NULL) {
+ sndioHostApi->audiodevices = strdup(audiodevices);
+ if (sndioHostApi->audiodevices == NULL)
+ return paNoError;
+
+ audiodevices = sndioHostApi->audiodevices;
+ while ((device = strsep(&audiodevices, ":")) != NULL &&
+ deviceCount < PA_SNDIO_AUDIODEVICES_MAX) {
+ if (*device == '\0')
+ continue;
+ info = &sndioHostApi->device_info[deviceCount];
+ InitDeviceInfo(info, hostApiIndex, device);
+ sndioHostApi->infos[deviceCount] = info;
+ deviceCount++;
+ }
+ }
+
+ *hostApi = &sndioHostApi->base;
+ (*hostApi)->info.structVersion = 1;
+ (*hostApi)->info.type = paSndio;
+ (*hostApi)->info.name = "sndio";
+ (*hostApi)->info.deviceCount = deviceCount;
+ (*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;
+}
diff --git a/media-libs/portaudio/files/portaudio-19.06.00-sndio.patch b/media-libs/portaudio/files/portaudio-19.06.00-sndio.patch
@@ -1,20 +1,6 @@
-Source: https://github.com/void-linux/void-packages/blob/master/srcpkgs/portaudio/patches/sndio.patch
-
-Requires an eautoreconf.
-
-diff --git Makefile.in Makefile.in
-index 5e1a764..2747f73 100644
---- a/Makefile.in
-+++ b/Makefile.in
-@@ -44,7 +44,7 @@ PALIB = libportaudio.la
- PAINC = include/portaudio.h
-
- PA_LDFLAGS = $(LDFLAGS) $(SHARED_FLAGS) -rpath $(libdir) -no-undefined \
-- -export-symbols-regex "(Pa|PaMacCore|PaJack|PaAlsa|PaAsio|PaOSS)_.*" \
-+ -export-symbols-regex "(Pa|PaMacCore|PaJack|PaAlsa|PaAsio|PaOSS|PaSndio)_.*" \
- -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
-
- COMMON_OBJS = \
+$OpenBSD: patch-Makefile_in,v 1.4 2013/03/12 00:59:50 brad Exp $
+--- portaudio/Makefile.in.orig Thu Jul 5 23:44:34 2012
++++ portaudio/Makefile.in Thu Jul 5 23:49:34 2012
@@ -146,6 +146,7 @@ SRC_DIRS = \
src/hostapi/dsound \
src/hostapi/jack \
@@ -23,10 +9,10 @@ index 5e1a764..2747f73 100644
src/hostapi/wasapi \
src/hostapi/wdmks \
src/hostapi/wmme \
-diff --git configure.in configure.in
-index 13816fb..4c06d10 100644
---- a/configure.in
-+++ b/configure.in
+$OpenBSD: patch-configure_in,v 1.5 2019/02/06 14:21:15 jca Exp $
+Index: configure.in
+--- portaudio/configure.in.orig
++++ portaudio/configure.in
@@ -24,6 +24,10 @@ AC_ARG_WITH(alsa,
AS_HELP_STRING([--with-alsa], [Enable support for ALSA @<:@autodetect@:>@]),
[with_alsa=$withval])
@@ -54,10 +40,10 @@ index 13816fb..4c06d10 100644
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)
++ 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
@@ -71,10 +57,10 @@ index 13816fb..4c06d10 100644
OSS ......................... $have_oss
JACK ........................ $have_jack
])
-diff --git include/portaudio.h include/portaudio.h
-index 8a94aaf..f94d9c4 100644
---- a/include/portaudio.h
-+++ b/include/portaudio.h
+$OpenBSD: patch-include_portaudio_h,v 1.3 2019/02/06 14:21:15 jca Exp $
+Index: include/portaudio.h
+--- portaudio/include/portaudio.h.orig
++++ portaudio/include/portaudio.h
@@ -287,7 +287,8 @@ typedef enum PaHostApiTypeId
paWDMKS=11,
paJACK=12,
@@ -85,781 +71,9 @@ index 8a94aaf..f94d9c4 100644
} PaHostApiTypeId;
-diff --git src/hostapi/sndio/pa_sndio.c src/hostapi/sndio/pa_sndio.c
-new file mode 100644
-index 0000000..725ef47
---- a//dev/null
-+++ b/src/hostapi/sndio/pa_sndio.c
-@@ -0,0 +1,765 @@
-+/*
-+ * Copyright (c) 2009 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.
-+ */
-+#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 and PortAudio has
-+ * no way of accepting raw device strings from users.
-+ * Normally we just expose the default device, which can be
-+ * changed via the AUDIODEVICE environment variable, but we
-+ * also allow specifying a list of up to 16 devices via the
-+ * PA_SNDIO_AUDIODEVICES environment variable.
-+ *
-+ * Example:
-+ * PA_SNDIO_AUDIODEVICES=default:snd/0.monitor:snd@remote/0
-+ */
-+#define PA_SNDIO_AUDIODEVICES_MAX 16
-+ PaDeviceInfo device_info[PA_SNDIO_AUDIODEVICES_MAX];
-+ PaDeviceInfo *infos[PA_SNDIO_AUDIODEVICES_MAX];
-+ char *audiodevices;
-+} 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;
-+ const char *dev;
-+
-+ DPR("OpenStream:\n");
-+
-+ mode = 0;
-+ inch = onch = 0;
-+ ifmt = ofmt = 0;
-+ sio_initpar(&par);
-+
-+ if (outputPar && outputPar->channelCount > 0) {
-+ if (outputPar->device >= sndioHostApi->base.info.deviceCount) {
-+ 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 >= sndioHostApi->base.info.deviceCount) {
-+ 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);
-+
-+ if (outputPar) {
-+ dev = sndioHostApi->device_info[outputPar->device].name;
-+ } else if (inputPar) {
-+ dev = sndioHostApi->device_info[inputPar->device].name;
-+ } else {
-+ return paUnanticipatedHostError;
-+ }
-+ hdl = sio_open(dev, 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)
-+{
-+ PaSndioHostApiRepresentation *sndioHostApi;
-+ sndioHostApi = (PaSndioHostApiRepresentation *)hostApi;
-+ free(sndioHostApi->audiodevices);
-+ PaUtil_FreeMemory(hostApi);
-+}
-+
-+static void
-+InitDeviceInfo(PaDeviceInfo *info, PaHostApiIndex hostApiIndex, const char *name)
-+{
-+ info->structVersion = 2;
-+ info->name = name;
-+ 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;
-+}
-+
-+PaError
-+PaSndio_Initialize(PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex)
-+{
-+ PaSndioHostApiRepresentation *sndioHostApi;
-+ PaDeviceInfo *info;
-+ struct sio_hdl *hdl;
-+ char *audiodevices;
-+ char *device;
-+ size_t deviceCount;
-+
-+ 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;
-+
-+ // Add default device
-+ info = &sndioHostApi->device_info[0];
-+ InitDeviceInfo(info, hostApiIndex, SIO_DEVANY);
-+ sndioHostApi->infos[0] = info;
-+ deviceCount = 1;
-+
-+ // Add additional devices as specified in the PA_SNDIO_AUDIODEVICES
-+ // environment variable as a colon separated list
-+ sndioHostApi->audiodevices = NULL;
-+ audiodevices = getenv("PA_SNDIO_AUDIODEVICES");
-+ if (audiodevices != NULL) {
-+ sndioHostApi->audiodevices = strdup(audiodevices);
-+ if (sndioHostApi->audiodevices == NULL)
-+ return paNoError;
-+
-+ audiodevices = sndioHostApi->audiodevices;
-+ while ((device = strsep(&audiodevices, ":")) != NULL &&
-+ deviceCount < PA_SNDIO_AUDIODEVICES_MAX) {
-+ if (*device == '\0')
-+ continue;
-+ info = &sndioHostApi->device_info[deviceCount];
-+ InitDeviceInfo(info, hostApiIndex, device);
-+ sndioHostApi->infos[deviceCount] = info;
-+ deviceCount++;
-+ }
-+ }
-+
-+ *hostApi = &sndioHostApi->base;
-+ (*hostApi)->info.structVersion = 1;
-+ (*hostApi)->info.type = paSndio;
-+ (*hostApi)->info.name = "sndio";
-+ (*hostApi)->info.deviceCount = deviceCount;
-+ (*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;
-+}
-diff --git src/os/unix/pa_unix_hostapis.c src/os/unix/pa_unix_hostapis.c
-index a9b4a05..c3fa2a3 100644
---- a/src/os/unix/pa_unix_hostapis.c
-+++ b/src/os/unix/pa_unix_hostapis.c
+$OpenBSD: patch-src_os_unix_pa_unix_hostapis_c,v 1.2 2013/03/12 00:59:50 brad Exp $
+--- portaudio/src/os/unix/pa_unix_hostapis.c.orig Thu Jul 5 23:44:45 2012
++++ portaudio/src/os/unix/pa_unix_hostapis.c Thu Jul 5 23:49:33 2012
@@ -44,6 +44,7 @@
PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
@@ -868,14 +82,14 @@ index a9b4a05..c3fa2a3 100644
PaError PaOSS_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
/* Added for IRIX, Pieter, oct 2, 2003: */
PaError PaSGI_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
-@@ -79,6 +80,10 @@ PaUtilHostApiInitializer *paHostApiInitializers[] =
+@@ -78,6 +79,10 @@ PaUtilHostApiInitializer *paHostApiInitializers[] =
+ #endif
#endif /* __linux__ */
-
++
+#ifdef PA_USE_SNDIO
-+ PaSndio_Initialize,
++ PaSndio_Initialize,
+#endif
-+
+
#if PA_USE_JACK
PaJack_Initialize,
- #endif
diff --git a/media-libs/portaudio/portaudio-19.06.00-r2.ebuild b/media-libs/portaudio/portaudio-19.06.00-r2.ebuild
@@ -1,83 +0,0 @@
-# Copyright 1999-2020 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-inherit multilib-minimal autotools
-
-DESCRIPTION="A free, cross-platform, open-source, audio I/O library"
-HOMEPAGE="http://www.portaudio.com/"
-SRC_URI="http://www.portaudio.com/archives/pa_stable_v190600_20161030.tgz
- https://sources.debian.org/data/main/p/portaudio19/19.6.0-1/debian/patches/audacity-portmixer.patch -> ${PN}-19.06.00-audacity-portmixer.patch"
-
-LICENSE="MIT"
-SLOT="0"
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~sparc ~x86 ~amd64-linux ~x86-linux"
-IUSE="alsa +cxx debug doc jack oss static-libs sndio"
-
-RDEPEND="alsa? ( >=media-libs/alsa-lib-1.0.27.2[${MULTILIB_USEDEP}] )
- jack? ( virtual/jack[${MULTILIB_USEDEP}] )
- sndio? ( media-sound/sndio:=[${MULTILIB_USEDEP}] )
-"
-DEPEND="${RDEPEND}"
-BDEPEND="
- doc? ( app-doc/doxygen )
- virtual/pkgconfig
-"
-
-S="${WORKDIR}/${PN}"
-
-DOCS=( README.txt )
-
-PATCHES=(
- "${DISTDIR}/${PN}-19.06.00-audacity-portmixer.patch"
- "${FILESDIR}/${PN}-19.06.00-sndio.patch"
-)
-
-src_prepare() {
- default
-
- # depcomp is required when building the bindings/cpp extension
- # but will be removed by autoreconf + libtool >= 2.4.6
- # Protect it from removal
- mv depcomp{,~} || die
-
- eautoreconf
-
- # Restore depcomp
- mv depcomp{~,} || die
-}
-
-multilib_src_configure() {
- local myeconfargs=(
- $(use_enable debug debug-output)
- $(use_enable cxx)
- $(use_enable static-libs static)
- $(use_with alsa)
- $(use_with jack)
- $(use_with oss)
- $(use_with sndio)
- )
-
- ECONF_SOURCE="${S}" econf "${myeconfargs[@]}"
-}
-
-multilib_src_compile() {
- # workaround parallel build issue
- emake lib/libportaudio.la
- emake
-}
-
-src_compile() {
- multilib-minimal_src_compile
-
- if use doc; then
- doxygen -u Doxyfile || die
- doxygen Doxyfile || die
- fi
-}
-
-multilib_src_install_all() {
- einstalldocs
- use doc && dodoc -r doc/html
- find "${ED}" -name "*.la" -delete || die
-}
diff --git a/media-libs/portaudio/portaudio-19.06.00-r3.ebuild b/media-libs/portaudio/portaudio-19.06.00-r3.ebuild
@@ -0,0 +1,81 @@
+# Copyright 1999-2020 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=7
+inherit autotools multilib-minimal
+
+DESCRIPTION="A free, cross-platform, open-source, audio I/O library"
+HOMEPAGE="http://www.portaudio.com/"
+SRC_URI="http://www.portaudio.com/archives/pa_stable_v190600_20161030.tgz
+ https://sources.debian.org/data/main/p/portaudio19/19.6.0-1/debian/patches/audacity-portmixer.patch -> ${PN}-19.06.00-audacity-portmixer.patch"
+
+LICENSE="MIT"
+SLOT="0"
+KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~sparc ~x86 ~amd64-linux ~x86-linux"
+IUSE="alsa +cxx debug doc jack oss sndio static-libs"
+
+RDEPEND="alsa? ( >=media-libs/alsa-lib-1.0.27.2[${MULTILIB_USEDEP}] )
+ jack? ( virtual/jack[${MULTILIB_USEDEP}] )
+ sndio? ( media-sound/sndio:=[${MULTILIB_USEDEP}] )
+"
+DEPEND="${RDEPEND}"
+BDEPEND="
+ doc? ( app-doc/doxygen )
+ virtual/pkgconfig
+"
+
+S="${WORKDIR}/${PN}"
+
+DOCS=( README.txt )
+
+PATCHES=(
+ "${DISTDIR}/${PN}-19.06.00-audacity-portmixer.patch"
+ "${FILESDIR}"/${PN}-19.06.00-AR.patch # bug #720966, trigger reconf
+ "${FILESDIR}/${PN}-19.06.00-sndio.patch"
+)
+
+src_prepare() {
+ default
+
+ mkdir -p "${S}/src/hostapi/sndio/" || die
+ cp "${FILESDIR}/${PN}-19.06.00-pa_sndio.c" "${S}/src/hostapi/sndio/pa_sndio.c" || die
+
+ eautoconf
+
+ multilib_copy_sources
+}
+
+multilib_src_configure() {
+ local myeconfargs=(
+ $(use_enable debug debug-output)
+ $(use_enable cxx)
+ $(use_enable static-libs static)
+ $(use_with alsa)
+ $(use_with jack)
+ $(use_with oss)
+ $(use_with sndio)
+ )
+
+ ECONF_SOURCE="${S}" econf "${myeconfargs[@]}"
+}
+
+multilib_src_compile() {
+ # workaround parallel build issue
+ emake lib/libportaudio.la
+ emake
+}
+
+src_compile() {
+ multilib-minimal_src_compile
+
+ if use doc; then
+ doxygen -u Doxyfile || die
+ doxygen Doxyfile || die
+ fi
+}
+
+multilib_src_install_all() {
+ einstalldocs
+ use doc && dodoc -r doc/html
+ find "${ED}" -name "*.la" -delete || die
+}