diff --git a/srcpkgs/portaudio/patches/sndio-portaudio.patch b/srcpkgs/portaudio/patches/sndio-portaudio.patch new file mode 100644 index 00000000000..72f4c44443c --- /dev/null +++ b/srcpkgs/portaudio/patches/sndio-portaudio.patch @@ -0,0 +1,892 @@ +--- Makefile.in 2018-11-27 14:33:02.442999726 +0100 ++++ Makefile.in 2018-11-27 14:38:09.544966833 +0100 +@@ -44,7 +44,7 @@ + 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|PaSndio|PaAsio|PaOSS)_.*" \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) + + COMMON_OBJS = \ +@@ -140,6 +140,7 @@ + SRC_DIRS = \ + src/common \ + src/hostapi/alsa \ ++ src/hostapi/sndio \ + src/hostapi/asihpi \ + src/hostapi/asio \ + src/hostapi/coreaudio \ +--- configure.in 2018-11-27 14:33:02.448999725 +0100 ++++ configure.in 2018-11-27 14:43:04.712935218 +0100 +@@ -24,6 +24,10 @@ + AS_HELP_STRING([--with-alsa], [Enable support for ALSA @<:@autodetect@:>@]), + [with_alsa=$withval]) + ++AC_ARG_WITH(sndio, ++ AS_HELP_STRING([--with-sndio], [Enable support for sndio @<:@autodetect@:>@]), ++ [with_sndio=$withval]) ++ + AC_ARG_WITH(jack, + AS_HELP_STRING([--with-jack], [Enable support for JACK @<:@autodetect@:>@]), + [with_jack=$withval]) +@@ -120,6 +124,10 @@ + if test "x$with_alsa" != "xno"; then + AC_CHECK_LIB(asound, snd_pcm_open, have_alsa=yes, have_alsa=no) + fi ++have_sndio=no ++if test "x$with_sndio" != "xno"; then ++ AC_CHECK_LIB(sndio, sio_open, have_sndio=yes, have_sndio=no) ++fi + have_asihpi=no + if test "x$with_asihpi" != "xno"; then + AC_CHECK_LIB(hpi, HPI_SubSysCreate, have_asihpi=yes, have_asihpi=no, -lm) +@@ -406,6 +414,13 @@ + AC_DEFINE(PA_USE_ALSA,1) + fi + ++ if [[ "$have_sndio" = "yes" -a "$with_sndio" != "no" ]] ; then ++ DLL_LIBS="$DLL_LIBS -lsndio" ++ LIBS="$LIBS -lsndio" ++ OTHER_OBJS="$OTHER_OBJS src/hostapi/sndio/pa_sndio.o" ++ AC_DEFINE(PA_USE_SNDIO,1) ++ fi ++ + if [[ "$have_jack" = "yes" ] && [ "$with_jack" != "no" ]] ; then + DLL_LIBS="$DLL_LIBS $JACK_LIBS" + CFLAGS="$CFLAGS $JACK_CFLAGS" +@@ -484,6 +499,7 @@ + + case "$target_os" in *linux*) + AC_MSG_RESULT([ ++ Sndio ....................... $have_sndio + ALSA ........................ $have_alsa + ASIHPI ...................... $have_asihpi]) + ;; +@@ -509,6 +525,7 @@ + ;; + *) + AC_MSG_RESULT([ ++ Sndio ....................... $have_sndio + OSS ......................... $have_oss + JACK ........................ $have_jack + ]) +--- include/portaudio.h 2018-11-27 14:33:02.449999725 +0100 ++++ include/portaudio.h 2018-11-27 16:31:38.419237546 +0100 +@@ -281,13 +281,14 @@ + paSoundManager=4, + paCoreAudio=5, + paOSS=7, +- paALSA=8, ++ paSndio=8, + paAL=9, + paBeOS=10, + paWDMKS=11, + paJACK=12, + paWASAPI=13, +- paAudioScienceHPI=14 ++ paAudioScienceHPI=14, ++ paALSA=15 + } PaHostApiTypeId; + + +--- src/hostapi/sndio/pa_sndio.c 1970-01-01 01:00:00.000000000 +0100 ++++ src/hostapi/sndio/pa_sndio.c 2018-11-27 14:36:43.241976077 +0100 +@@ -0,0 +1,765 @@ ++/* ++ * Copyright (c) 2009 Alexandre Ratchov ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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; ++} +--- src/os/unix/pa_unix_hostapis.c 2018-11-27 14:33:02.454999725 +0100 ++++ src/os/unix/pa_unix_hostapis.c 2018-11-27 14:56:51.801846630 +0100 +@@ -44,6 +44,7 @@ + + PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index ); + PaError PaAlsa_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index ); ++PaError PaSndio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index ); + PaError PaOSS_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index ); + /* Added for IRIX, Pieter, oct 2, 2003: */ + PaError PaSGI_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index ); +@@ -59,6 +60,10 @@ + { + #ifdef __linux__ + ++#ifdef PA_USE_SNDIO ++ PaSndio_Initialize, ++#endif ++ + #if PA_USE_ALSA + PaAlsa_Initialize, + #endif +@@ -69,6 +74,10 @@ + + #else /* __linux__ */ + ++#ifdef PA_USE_SNDIO ++ PaSndio_Initialize, ++#endif ++ + #if PA_USE_OSS + PaOSS_Initialize, + #endif diff --git a/srcpkgs/portaudio/template b/srcpkgs/portaudio/template index 96a46fd7ed3..7f649c0787f 100644 --- a/srcpkgs/portaudio/template +++ b/srcpkgs/portaudio/template @@ -1,19 +1,18 @@ # Template file for 'portaudio' pkgname=portaudio version=190600.20161030 -revision=1 +revision=2 wrksrc=portaudio build_style=gnu-configure -configure_args="--enable-cxx --with-jack" +configure_args="--enable-cxx --with-jack --enable-sndio" hostmakedepends="automake libtool pkg-config" -makedepends="alsa-lib-devel jack-devel" -homepage="http://www.portaudio.com" -license="MIT" +makedepends="alsa-lib-devel jack-devel sndio-devel" short_desc="Portable cross-platform audio I/O library" maintainer="Juan RP " +license="MIT" +homepage="http://www.portaudio.com" distfiles="http://www.${pkgname}.com/archives/pa_stable_v${version%.*}_${version#*.}.tgz" checksum=f5a21d7dcd6ee84397446fa1fa1a0675bb2e8a4a6dceb4305a8404698d8d1513 - disable_parallel_build=yes pre_configure() {