logo

overlay

My own overlay for experimentations, use with caution, no support is provided
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:

Amedia-libs/portaudio/files/portaudio-19.06.00-AR.patch14++++++++++++++
Amedia-libs/portaudio/files/portaudio-19.06.00-pa_sndio.c766+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmedia-libs/portaudio/files/portaudio-19.06.00-sndio.patch832+++----------------------------------------------------------------------------
Dmedia-libs/portaudio/portaudio-19.06.00-r2.ebuild83-------------------------------------------------------------------------------
Amedia-libs/portaudio/portaudio-19.06.00-r3.ebuild81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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 +}