From efd70272ab7a253a9187c8ba3c6409004f1343b4 Mon Sep 17 00:00:00 2001 From: Spencer Russell Date: Thu, 18 May 2017 12:38:13 -0400 Subject: [PATCH] adds cross-compiled multiplatform builds and infrastructure to load them --- .gitignore | 3 + deps/src/Makefile | 90 +- deps/src/build.sh | 54 + deps/src/dockerbuild_cb.sh | 8 + deps/src/dockerbuild_hbb.sh | 13 + deps/src/pa_shim.c | 2 +- deps/src/portaudio.h | 1225 +++++++++++++++++ deps/usr/lib/pa_shim.so | Bin 8536 -> 0 bytes deps/usr/lib/pa_shim_arm-linux-gnueabihf.so | Bin 0 -> 6376 bytes deps/usr/lib/pa_shim_i686-linux-gnu.so | Bin 0 -> 6373 bytes deps/usr/lib/pa_shim_i686-w64-mingw32.dll | Bin 0 -> 81524 bytes deps/usr/lib/pa_shim_powerpc64le-linux-gnu.so | Bin 0 -> 9320 bytes ...ib => pa_shim_x86_64-apple-darwin14.dylib} | Bin 8972 -> 8972 bytes deps/usr/lib/pa_shim_x86_64-linux-gnu.so | Bin 0 -> 8340 bytes deps/usr/lib/pa_shim_x86_64-w64-mingw32.dll | Bin 0 -> 110424 bytes src/pa_shim.jl | 27 +- test/runtests.jl | 10 +- 17 files changed, 1385 insertions(+), 47 deletions(-) create mode 100755 deps/src/build.sh create mode 100755 deps/src/dockerbuild_cb.sh create mode 100755 deps/src/dockerbuild_hbb.sh create mode 100644 deps/src/portaudio.h delete mode 100755 deps/usr/lib/pa_shim.so create mode 100755 deps/usr/lib/pa_shim_arm-linux-gnueabihf.so create mode 100755 deps/usr/lib/pa_shim_i686-linux-gnu.so create mode 100755 deps/usr/lib/pa_shim_i686-w64-mingw32.dll create mode 100755 deps/usr/lib/pa_shim_powerpc64le-linux-gnu.so rename deps/usr/lib/{pa_shim.dylib => pa_shim_x86_64-apple-darwin14.dylib} (63%) create mode 100755 deps/usr/lib/pa_shim_x86_64-linux-gnu.so create mode 100755 deps/usr/lib/pa_shim_x86_64-w64-mingw32.dll diff --git a/.gitignore b/.gitignore index d7bc517..dd2812d 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,6 @@ deps/deps.jl *.flac *.cov coverage +deps/usr/lib/pa_shim.so +deps/usr/lib/pa_shim.dylib +deps/usr/lib/pa_shim.dll diff --git a/deps/src/Makefile b/deps/src/Makefile index 7c87b0a..c711226 100644 --- a/deps/src/Makefile +++ b/deps/src/Makefile @@ -1,68 +1,80 @@ -# Makefile lifted from Clang.jl +# Makefile originally lifted from Clang.jl # Copyright (c) 2012-: Isaiah Norton and [contributors](https://github.com/ihnorton/Clang.jl/graphs/contributors) ifeq (exists, $(shell [ -e Make.user ] && echo exists )) include Make.user endif -TARGETDIR = ../usr/lib +TARGETDIR=../usr/lib +TARGETBASENAME=pa_shim OBJS = pa_shim.o -# Figure out OS and architecture -OS=$(shell uname) -ifneq (,$(findstring MINGW,$(OS))) - OS=WINNT +# check to see if the user passed in a HOST variable for cross-compiling +ifeq ($(HOST),) + # Figure out OS and architecture + OS=$(shell uname) + ifneq ($(findstring MINGW,$(OS)),) + OS=WINNT + endif +else + HOSTSUFFIX=_$(HOST) + ifneq ($(findstring linux,$(HOST)),) + OS=Linux + else ifneq ($(findstring darwin,$(HOST)),) + OS=Darwin + else ifneq ($(findstring mingw,$(HOST)),) + OS=WINNT + endif endif -# file extensions and platform-specific libs +CFLAGS = -Wall -Wno-strict-aliasing -fno-omit-frame-pointer -I../../../RingBuffers/deps/src +LDFLAGS += + ifeq ($(OS), WINNT) - LIBS += - LDFLAGS += -shared -L../../../RingBuffers/deps/usr/lib -lpa_ringbuffer - INC += - SHACMD = sha256sum - SHLIB_EXT = dll + LIBS += + LDFLAGS += -shared -L../../../RingBuffers/deps/usr/lib -lpa_ringbuffer$(HOSTSUFFIX) + INC += + SHACMD = sha256sum + SHLIB_EXT = dll else ifeq ($(OS), Darwin) - LIBS += - INC += -# we'll rely on Julia to load RingBuffers.jl, which will in turn load the C -# library that we depend on for these symbols - LDFLAGS += -dynamiclib -Wl,-undefined,dynamic_lookup - SHLIB_EXT = dylib - SHACMD = shasum -a256 + LIBS += + INC += + # we'll rely on Julia to load RingBuffers.jl, which will in turn load the C + # library that we depend on for these symbols + LDFLAGS += -dynamiclib -Wl,-undefined,dynamic_lookup + SHLIB_EXT = dylib + SHACMD = shasum -a256 else - LIBS += - INC += - LDFLAGS += -shared - SHLIB_EXT = so - SHACMD = sha256sum + CFLAGS += -fPIC + LIBS += + INC += + LDFLAGS += -shared + SHLIB_EXT = so + SHACMD = sha256sum endif SOURCEHASH = $(shell $(SHACMD) pa_shim.c | awk '{print $$1}') +CFLAGS += -DSOURCEHASH=\"$(SOURCEHASH)\" -CFLAGS += -I../../../RingBuffers/deps/src -Wall -Wno-strict-aliasing -fno-omit-frame-pointer -fPIC -DSOURCEHASH=\"$(SOURCEHASH)\" -LDFLAGS += -# LINUX_LIBS =-lrt -# LINUX_LDFLAGS =-rdynamic -# add the Homebrew.jl tree to the include dirs in case we used it for -# portaudio and libsndfile -# DARWIN_LDFLAGS =-L../../../Homebrew/deps/usr/lib -# DARWIN_INC =-I../../../Homebrew/deps/usr/include +TARGET=$(TARGETDIR)/$(TARGETBASENAME)$(HOSTSUFFIX).$(SHLIB_EXT) -TARGET = $(TARGETDIR)/pa_shim.$(SHLIB_EXT) - -.PHONY: clean default +.PHONY: clean cleantemp default default: $(TARGET) %.o: %.c Makefile - $(CC) $< -fPIC -c -o $@ $(INC) $(CFLAGS) + $(CC) $< -c -o $@ $(INC) $(CFLAGS) $(TARGETDIR): mkdir -p $@ $(TARGET): $(OBJS) $(TARGETDIR) Makefile - $(CC) $(OBJS) -shared -o $@ $(LDFLAGS) $(LIBS) + $(CC) $(OBJS) $(LDFLAGS) -o $@ $(LIBS) -clean: +cleantemp: rm -f $(OBJS) - rm -f $(TARGET) + +clean: cleantemp + rm -f $(TARGETDIR)/$(TARGETBASENAME)*.so + rm -f $(TARGETDIR)/$(TARGETBASENAME)*.dylib + rm -f $(TARGETDIR)/$(TARGETBASENAME)*.dll diff --git a/deps/src/build.sh b/deps/src/build.sh new file mode 100755 index 0000000..4e210e1 --- /dev/null +++ b/deps/src/build.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# User docker to build pa_shim library for all supported platforms. + +set -e + +make clean + +echo "" +# NOTE: the darwin build ends up actually being x86_64-apple-darwin14. It gets +# mapped within the docker machine +for platform in \ + arm-linux-gnueabihf \ + powerpc64le-linux-gnu \ + x86_64-apple-darwin \ + x86_64-w64-mingw32 \ + i686-w64-mingw32; do + echo "================================" + echo "building for $platform..." + docker run --rm \ + -v $(pwd)/../..:/workdir \ + -v $(pwd)/../../../RingBuffers:/RingBuffers \ + -w /workdir/deps/src \ + -e CROSS_TRIPLE=$platform \ + multiarch/crossbuild \ + ./dockerbuild_cb.sh + echo "================================" + echo "" +done + +# we use holy-build-box for the x86 linux builds because it uses an older +# glibc so it should be compatible with more user environments +echo "================================" +echo "building for x86_64-linux-gnu..." +docker run --rm \ + -v $(pwd)/../..:/workdir \ + -v $(pwd)/../../../RingBuffers:/RingBuffers \ + -w /workdir/deps/src \ + -e HOST=x86_64-linux-gnu \ + phusion/holy-build-box-64 \ + ./dockerbuild_hbb.sh +echo "================================" +echo "" + +echo "================================" +echo "building for i686-linux-gnu..." +docker run --rm \ + -v $(pwd)/../..:/workdir \ + -v $(pwd)/../../../RingBuffers:/RingBuffers \ + -w /workdir/deps/src \ + -e HOST=i686-linux-gnu \ + phusion/holy-build-box-32 \ + ./dockerbuild_hbb.sh +echo "================================" diff --git a/deps/src/dockerbuild_cb.sh b/deps/src/dockerbuild_cb.sh new file mode 100755 index 0000000..7b04f2b --- /dev/null +++ b/deps/src/dockerbuild_cb.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# this script is run by build.sh within each docker instance to do the build. + +set -e + +make HOST=$CROSS_TRIPLE +make cleantemp diff --git a/deps/src/dockerbuild_hbb.sh b/deps/src/dockerbuild_hbb.sh new file mode 100755 index 0000000..090611a --- /dev/null +++ b/deps/src/dockerbuild_hbb.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# this script is run by build.sh within each docker instance to do the build. +# it's meant to be run from within a "Holy Build Box" docker instance. + +set -e + +# Activate Holy Build Box environment. +source /hbb_exe/activate + +set -x +make HOST=$HOST +make cleantemp diff --git a/deps/src/pa_shim.c b/deps/src/pa_shim.c index 6976290..c6d67cc 100644 --- a/deps/src/pa_shim.c +++ b/deps/src/pa_shim.c @@ -1,4 +1,4 @@ -#include +#include "portaudio.h" #include #include #include diff --git a/deps/src/portaudio.h b/deps/src/portaudio.h new file mode 100644 index 0000000..8a94aaf --- /dev/null +++ b/deps/src/portaudio.h @@ -0,0 +1,1225 @@ +#ifndef PORTAUDIO_H +#define PORTAUDIO_H +/* + * $Id$ + * PortAudio Portable Real-Time Audio Library + * PortAudio API Header File + * Latest version available at: http://www.portaudio.com/ + * + * Copyright (c) 1999-2002 Ross Bencina and Phil Burk + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * The text above constitutes the entire PortAudio license; however, + * the PortAudio community also makes the following non-binding requests: + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the + * license above. + */ + +/** @file + @ingroup public_header + @brief The portable PortAudio API. +*/ + + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** Retrieve the release number of the currently running PortAudio build. + For example, for version "19.5.1" this will return 0x00130501. + + @see paMakeVersionNumber +*/ +int Pa_GetVersion( void ); + +/** Retrieve a textual description of the current PortAudio build, + e.g. "PortAudio V19.5.0-devel, revision 1952M". + The format of the text may change in the future. Do not try to parse the + returned string. + + @deprecated As of 19.5.0, use Pa_GetVersionInfo()->versionText instead. +*/ +const char* Pa_GetVersionText( void ); + +/** + Generate a packed integer version number in the same format used + by Pa_GetVersion(). Use this to compare a specified version number with + the currently running version. For example: + + @code + if( Pa_GetVersion() < paMakeVersionNumber(19,5,1) ) {} + @endcode + + @see Pa_GetVersion, Pa_GetVersionInfo + @version Available as of 19.5.0. +*/ +#define paMakeVersionNumber(major, minor, subminor) \ + (((major)&0xFF)<<16 | ((minor)&0xFF)<<8 | ((subminor)&0xFF)) + + +/** + A structure containing PortAudio API version information. + @see Pa_GetVersionInfo, paMakeVersionNumber + @version Available as of 19.5.0. +*/ +typedef struct PaVersionInfo { + int versionMajor; + int versionMinor; + int versionSubMinor; + /** + This is currently the Git revision hash but may change in the future. + The versionControlRevision is updated by running a script before compiling the library. + If the update does not occur, this value may refer to an earlier revision. + */ + const char *versionControlRevision; + /** Version as a string, for example "PortAudio V19.5.0-devel, revision 1952M" */ + const char *versionText; +} PaVersionInfo; + +/** Retrieve version information for the currently running PortAudio build. + @return A pointer to an immutable PaVersionInfo structure. + + @note This function can be called at any time. It does not require PortAudio + to be initialized. The structure pointed to is statically allocated. Do not + attempt to free it or modify it. + + @see PaVersionInfo, paMakeVersionNumber + @version Available as of 19.5.0. +*/ +const PaVersionInfo* Pa_GetVersionInfo(); + + +/** Error codes returned by PortAudio functions. + Note that with the exception of paNoError, all PaErrorCodes are negative. +*/ + +typedef int PaError; +typedef enum PaErrorCode +{ + paNoError = 0, + + paNotInitialized = -10000, + paUnanticipatedHostError, + paInvalidChannelCount, + paInvalidSampleRate, + paInvalidDevice, + paInvalidFlag, + paSampleFormatNotSupported, + paBadIODeviceCombination, + paInsufficientMemory, + paBufferTooBig, + paBufferTooSmall, + paNullCallback, + paBadStreamPtr, + paTimedOut, + paInternalError, + paDeviceUnavailable, + paIncompatibleHostApiSpecificStreamInfo, + paStreamIsStopped, + paStreamIsNotStopped, + paInputOverflowed, + paOutputUnderflowed, + paHostApiNotFound, + paInvalidHostApi, + paCanNotReadFromACallbackStream, + paCanNotWriteToACallbackStream, + paCanNotReadFromAnOutputOnlyStream, + paCanNotWriteToAnInputOnlyStream, + paIncompatibleStreamHostApi, + paBadBufferPtr +} PaErrorCode; + + +/** Translate the supplied PortAudio error code into a human readable + message. +*/ +const char *Pa_GetErrorText( PaError errorCode ); + + +/** Library initialization function - call this before using PortAudio. + This function initializes internal data structures and prepares underlying + host APIs for use. With the exception of Pa_GetVersion(), Pa_GetVersionText(), + and Pa_GetErrorText(), this function MUST be called before using any other + PortAudio API functions. + + If Pa_Initialize() is called multiple times, each successful + call must be matched with a corresponding call to Pa_Terminate(). + Pairs of calls to Pa_Initialize()/Pa_Terminate() may overlap, and are not + required to be fully nested. + + Note that if Pa_Initialize() returns an error code, Pa_Terminate() should + NOT be called. + + @return paNoError if successful, otherwise an error code indicating the cause + of failure. + + @see Pa_Terminate +*/ +PaError Pa_Initialize( void ); + + +/** Library termination function - call this when finished using PortAudio. + This function deallocates all resources allocated by PortAudio since it was + initialized by a call to Pa_Initialize(). In cases where Pa_Initialise() has + been called multiple times, each call must be matched with a corresponding call + to Pa_Terminate(). The final matching call to Pa_Terminate() will automatically + close any PortAudio streams that are still open. + + Pa_Terminate() MUST be called before exiting a program which uses PortAudio. + Failure to do so may result in serious resource leaks, such as audio devices + not being available until the next reboot. + + @return paNoError if successful, otherwise an error code indicating the cause + of failure. + + @see Pa_Initialize +*/ +PaError Pa_Terminate( void ); + + + +/** The type used to refer to audio devices. Values of this type usually + range from 0 to (Pa_GetDeviceCount()-1), and may also take on the PaNoDevice + and paUseHostApiSpecificDeviceSpecification values. + + @see Pa_GetDeviceCount, paNoDevice, paUseHostApiSpecificDeviceSpecification +*/ +typedef int PaDeviceIndex; + + +/** A special PaDeviceIndex value indicating that no device is available, + or should be used. + + @see PaDeviceIndex +*/ +#define paNoDevice ((PaDeviceIndex)-1) + + +/** A special PaDeviceIndex value indicating that the device(s) to be used + are specified in the host api specific stream info structure. + + @see PaDeviceIndex +*/ +#define paUseHostApiSpecificDeviceSpecification ((PaDeviceIndex)-2) + + +/* Host API enumeration mechanism */ + +/** The type used to enumerate to host APIs at runtime. Values of this type + range from 0 to (Pa_GetHostApiCount()-1). + + @see Pa_GetHostApiCount +*/ +typedef int PaHostApiIndex; + + +/** Retrieve the number of available host APIs. Even if a host API is + available it may have no devices available. + + @return A non-negative value indicating the number of available host APIs + or, a PaErrorCode (which are always negative) if PortAudio is not initialized + or an error is encountered. + + @see PaHostApiIndex +*/ +PaHostApiIndex Pa_GetHostApiCount( void ); + + +/** Retrieve the index of the default host API. The default host API will be + the lowest common denominator host API on the current platform and is + unlikely to provide the best performance. + + @return A non-negative value ranging from 0 to (Pa_GetHostApiCount()-1) + indicating the default host API index or, a PaErrorCode (which are always + negative) if PortAudio is not initialized or an error is encountered. +*/ +PaHostApiIndex Pa_GetDefaultHostApi( void ); + + +/** Unchanging unique identifiers for each supported host API. This type + is used in the PaHostApiInfo structure. The values are guaranteed to be + unique and to never change, thus allowing code to be written that + conditionally uses host API specific extensions. + + New type ids will be allocated when support for a host API reaches + "public alpha" status, prior to that developers should use the + paInDevelopment type id. + + @see PaHostApiInfo +*/ +typedef enum PaHostApiTypeId +{ + paInDevelopment=0, /* use while developing support for a new host API */ + paDirectSound=1, + paMME=2, + paASIO=3, + paSoundManager=4, + paCoreAudio=5, + paOSS=7, + paALSA=8, + paAL=9, + paBeOS=10, + paWDMKS=11, + paJACK=12, + paWASAPI=13, + paAudioScienceHPI=14 +} PaHostApiTypeId; + + +/** A structure containing information about a particular host API. */ + +typedef struct PaHostApiInfo +{ + /** this is struct version 1 */ + int structVersion; + /** The well known unique identifier of this host API @see PaHostApiTypeId */ + PaHostApiTypeId type; + /** A textual description of the host API for display on user interfaces. */ + const char *name; + + /** The number of devices belonging to this host API. This field may be + used in conjunction with Pa_HostApiDeviceIndexToDeviceIndex() to enumerate + all devices for this host API. + @see Pa_HostApiDeviceIndexToDeviceIndex + */ + int deviceCount; + + /** The default input device for this host API. The value will be a + device index ranging from 0 to (Pa_GetDeviceCount()-1), or paNoDevice + if no default input device is available. + */ + PaDeviceIndex defaultInputDevice; + + /** The default output device for this host API. The value will be a + device index ranging from 0 to (Pa_GetDeviceCount()-1), or paNoDevice + if no default output device is available. + */ + PaDeviceIndex defaultOutputDevice; + +} PaHostApiInfo; + + +/** Retrieve a pointer to a structure containing information about a specific + host Api. + + @param hostApi A valid host API index ranging from 0 to (Pa_GetHostApiCount()-1) + + @return A pointer to an immutable PaHostApiInfo structure describing + a specific host API. If the hostApi parameter is out of range or an error + is encountered, the function returns NULL. + + The returned structure is owned by the PortAudio implementation and must not + be manipulated or freed. The pointer is only guaranteed to be valid between + calls to Pa_Initialize() and Pa_Terminate(). +*/ +const PaHostApiInfo * Pa_GetHostApiInfo( PaHostApiIndex hostApi ); + + +/** Convert a static host API unique identifier, into a runtime + host API index. + + @param type A unique host API identifier belonging to the PaHostApiTypeId + enumeration. + + @return A valid PaHostApiIndex ranging from 0 to (Pa_GetHostApiCount()-1) or, + a PaErrorCode (which are always negative) if PortAudio is not initialized + or an error is encountered. + + The paHostApiNotFound error code indicates that the host API specified by the + type parameter is not available. + + @see PaHostApiTypeId +*/ +PaHostApiIndex Pa_HostApiTypeIdToHostApiIndex( PaHostApiTypeId type ); + + +/** Convert a host-API-specific device index to standard PortAudio device index. + This function may be used in conjunction with the deviceCount field of + PaHostApiInfo to enumerate all devices for the specified host API. + + @param hostApi A valid host API index ranging from 0 to (Pa_GetHostApiCount()-1) + + @param hostApiDeviceIndex A valid per-host device index in the range + 0 to (Pa_GetHostApiInfo(hostApi)->deviceCount-1) + + @return A non-negative PaDeviceIndex ranging from 0 to (Pa_GetDeviceCount()-1) + or, a PaErrorCode (which are always negative) if PortAudio is not initialized + or an error is encountered. + + A paInvalidHostApi error code indicates that the host API index specified by + the hostApi parameter is out of range. + + A paInvalidDevice error code indicates that the hostApiDeviceIndex parameter + is out of range. + + @see PaHostApiInfo +*/ +PaDeviceIndex Pa_HostApiDeviceIndexToDeviceIndex( PaHostApiIndex hostApi, + int hostApiDeviceIndex ); + + + +/** Structure used to return information about a host error condition. +*/ +typedef struct PaHostErrorInfo{ + PaHostApiTypeId hostApiType; /**< the host API which returned the error code */ + long errorCode; /**< the error code returned */ + const char *errorText; /**< a textual description of the error if available, otherwise a zero-length string */ +}PaHostErrorInfo; + + +/** Return information about the last host error encountered. The error + information returned by Pa_GetLastHostErrorInfo() will never be modified + asynchronously by errors occurring in other PortAudio owned threads + (such as the thread that manages the stream callback.) + + This function is provided as a last resort, primarily to enhance debugging + by providing clients with access to all available error information. + + @return A pointer to an immutable structure constraining information about + the host error. The values in this structure will only be valid if a + PortAudio function has previously returned the paUnanticipatedHostError + error code. +*/ +const PaHostErrorInfo* Pa_GetLastHostErrorInfo( void ); + + + +/* Device enumeration and capabilities */ + +/** Retrieve the number of available devices. The number of available devices + may be zero. + + @return A non-negative value indicating the number of available devices or, + a PaErrorCode (which are always negative) if PortAudio is not initialized + or an error is encountered. +*/ +PaDeviceIndex Pa_GetDeviceCount( void ); + + +/** Retrieve the index of the default input device. The result can be + used in the inputDevice parameter to Pa_OpenStream(). + + @return The default input device index for the default host API, or paNoDevice + if no default input device is available or an error was encountered. +*/ +PaDeviceIndex Pa_GetDefaultInputDevice( void ); + + +/** Retrieve the index of the default output device. The result can be + used in the outputDevice parameter to Pa_OpenStream(). + + @return The default output device index for the default host API, or paNoDevice + if no default output device is available or an error was encountered. + + @note + On the PC, the user can specify a default device by + setting an environment variable. For example, to use device #1. +
+ set PA_RECOMMENDED_OUTPUT_DEVICE=1
+
+ The user should first determine the available device ids by using + the supplied application "pa_devs". +*/ +PaDeviceIndex Pa_GetDefaultOutputDevice( void ); + + +/** The type used to represent monotonic time in seconds. PaTime is + used for the fields of the PaStreamCallbackTimeInfo argument to the + PaStreamCallback and as the result of Pa_GetStreamTime(). + + PaTime values have unspecified origin. + + @see PaStreamCallback, PaStreamCallbackTimeInfo, Pa_GetStreamTime +*/ +typedef double PaTime; + + +/** A type used to specify one or more sample formats. Each value indicates + a possible format for sound data passed to and from the stream callback, + Pa_ReadStream and Pa_WriteStream. + + The standard formats paFloat32, paInt16, paInt32, paInt24, paInt8 + and aUInt8 are usually implemented by all implementations. + + The floating point representation (paFloat32) uses +1.0 and -1.0 as the + maximum and minimum respectively. + + paUInt8 is an unsigned 8 bit format where 128 is considered "ground" + + The paNonInterleaved flag indicates that audio data is passed as an array + of pointers to separate buffers, one buffer for each channel. Usually, + when this flag is not used, audio data is passed as a single buffer with + all channels interleaved. + + @see Pa_OpenStream, Pa_OpenDefaultStream, PaDeviceInfo + @see paFloat32, paInt16, paInt32, paInt24, paInt8 + @see paUInt8, paCustomFormat, paNonInterleaved +*/ +typedef unsigned long PaSampleFormat; + + +#define paFloat32 ((PaSampleFormat) 0x00000001) /**< @see PaSampleFormat */ +#define paInt32 ((PaSampleFormat) 0x00000002) /**< @see PaSampleFormat */ +#define paInt24 ((PaSampleFormat) 0x00000004) /**< Packed 24 bit format. @see PaSampleFormat */ +#define paInt16 ((PaSampleFormat) 0x00000008) /**< @see PaSampleFormat */ +#define paInt8 ((PaSampleFormat) 0x00000010) /**< @see PaSampleFormat */ +#define paUInt8 ((PaSampleFormat) 0x00000020) /**< @see PaSampleFormat */ +#define paCustomFormat ((PaSampleFormat) 0x00010000) /**< @see PaSampleFormat */ + +#define paNonInterleaved ((PaSampleFormat) 0x80000000) /**< @see PaSampleFormat */ + +/** A structure providing information and capabilities of PortAudio devices. + Devices may support input, output or both input and output. +*/ +typedef struct PaDeviceInfo +{ + int structVersion; /* this is struct version 2 */ + const char *name; + PaHostApiIndex hostApi; /**< note this is a host API index, not a type id*/ + + int maxInputChannels; + int maxOutputChannels; + + /** Default latency values for interactive performance. */ + PaTime defaultLowInputLatency; + PaTime defaultLowOutputLatency; + /** Default latency values for robust non-interactive applications (eg. playing sound files). */ + PaTime defaultHighInputLatency; + PaTime defaultHighOutputLatency; + + double defaultSampleRate; +} PaDeviceInfo; + + +/** Retrieve a pointer to a PaDeviceInfo structure containing information + about the specified device. + @return A pointer to an immutable PaDeviceInfo structure. If the device + parameter is out of range the function returns NULL. + + @param device A valid device index in the range 0 to (Pa_GetDeviceCount()-1) + + @note PortAudio manages the memory referenced by the returned pointer, + the client must not manipulate or free the memory. The pointer is only + guaranteed to be valid between calls to Pa_Initialize() and Pa_Terminate(). + + @see PaDeviceInfo, PaDeviceIndex +*/ +const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceIndex device ); + + +/** Parameters for one direction (input or output) of a stream. +*/ +typedef struct PaStreamParameters +{ + /** A valid device index in the range 0 to (Pa_GetDeviceCount()-1) + specifying the device to be used or the special constant + paUseHostApiSpecificDeviceSpecification which indicates that the actual + device(s) to use are specified in hostApiSpecificStreamInfo. + This field must not be set to paNoDevice. + */ + PaDeviceIndex device; + + /** The number of channels of sound to be delivered to the + stream callback or accessed by Pa_ReadStream() or Pa_WriteStream(). + It can range from 1 to the value of maxInputChannels in the + PaDeviceInfo record for the device specified by the device parameter. + */ + int channelCount; + + /** The sample format of the buffer provided to the stream callback, + a_ReadStream() or Pa_WriteStream(). It may be any of the formats described + by the PaSampleFormat enumeration. + */ + PaSampleFormat sampleFormat; + + /** The desired latency in seconds. Where practical, implementations should + configure their latency based on these parameters, otherwise they may + choose the closest viable latency instead. Unless the suggested latency + is greater than the absolute upper limit for the device implementations + should round the suggestedLatency up to the next practical value - ie to + provide an equal or higher latency than suggestedLatency wherever possible. + Actual latency values for an open stream may be retrieved using the + inputLatency and outputLatency fields of the PaStreamInfo structure + returned by Pa_GetStreamInfo(). + @see default*Latency in PaDeviceInfo, *Latency in PaStreamInfo + */ + PaTime suggestedLatency; + + /** An optional pointer to a host api specific data structure + containing additional information for device setup and/or stream processing. + hostApiSpecificStreamInfo is never required for correct operation, + if not used it should be set to NULL. + */ + void *hostApiSpecificStreamInfo; + +} PaStreamParameters; + + +/** Return code for Pa_IsFormatSupported indicating success. */ +#define paFormatIsSupported (0) + +/** Determine whether it would be possible to open a stream with the specified + parameters. + + @param inputParameters A structure that describes the input parameters used to + open a stream. The suggestedLatency field is ignored. See PaStreamParameters + for a description of these parameters. inputParameters must be NULL for + output-only streams. + + @param outputParameters A structure that describes the output parameters used + to open a stream. The suggestedLatency field is ignored. See PaStreamParameters + for a description of these parameters. outputParameters must be NULL for + input-only streams. + + @param sampleRate The required sampleRate. For full-duplex streams it is the + sample rate for both input and output + + @return Returns 0 if the format is supported, and an error code indicating why + the format is not supported otherwise. The constant paFormatIsSupported is + provided to compare with the return value for success. + + @see paFormatIsSupported, PaStreamParameters +*/ +PaError Pa_IsFormatSupported( const PaStreamParameters *inputParameters, + const PaStreamParameters *outputParameters, + double sampleRate ); + + + +/* Streaming types and functions */ + + +/** + A single PaStream can provide multiple channels of real-time + streaming audio input and output to a client application. A stream + provides access to audio hardware represented by one or more + PaDevices. Depending on the underlying Host API, it may be possible + to open multiple streams using the same device, however this behavior + is implementation defined. Portable applications should assume that + a PaDevice may be simultaneously used by at most one PaStream. + + Pointers to PaStream objects are passed between PortAudio functions that + operate on streams. + + @see Pa_OpenStream, Pa_OpenDefaultStream, Pa_OpenDefaultStream, Pa_CloseStream, + Pa_StartStream, Pa_StopStream, Pa_AbortStream, Pa_IsStreamActive, + Pa_GetStreamTime, Pa_GetStreamCpuLoad + +*/ +typedef void PaStream; + + +/** Can be passed as the framesPerBuffer parameter to Pa_OpenStream() + or Pa_OpenDefaultStream() to indicate that the stream callback will + accept buffers of any size. +*/ +#define paFramesPerBufferUnspecified (0) + + +/** Flags used to control the behavior of a stream. They are passed as + parameters to Pa_OpenStream or Pa_OpenDefaultStream. Multiple flags may be + ORed together. + + @see Pa_OpenStream, Pa_OpenDefaultStream + @see paNoFlag, paClipOff, paDitherOff, paNeverDropInput, + paPrimeOutputBuffersUsingStreamCallback, paPlatformSpecificFlags +*/ +typedef unsigned long PaStreamFlags; + +/** @see PaStreamFlags */ +#define paNoFlag ((PaStreamFlags) 0) + +/** Disable default clipping of out of range samples. + @see PaStreamFlags +*/ +#define paClipOff ((PaStreamFlags) 0x00000001) + +/** Disable default dithering. + @see PaStreamFlags +*/ +#define paDitherOff ((PaStreamFlags) 0x00000002) + +/** Flag requests that where possible a full duplex stream will not discard + overflowed input samples without calling the stream callback. This flag is + only valid for full duplex callback streams and only when used in combination + with the paFramesPerBufferUnspecified (0) framesPerBuffer parameter. Using + this flag incorrectly results in a paInvalidFlag error being returned from + Pa_OpenStream and Pa_OpenDefaultStream. + + @see PaStreamFlags, paFramesPerBufferUnspecified +*/ +#define paNeverDropInput ((PaStreamFlags) 0x00000004) + +/** Call the stream callback to fill initial output buffers, rather than the + default behavior of priming the buffers with zeros (silence). This flag has + no effect for input-only and blocking read/write streams. + + @see PaStreamFlags +*/ +#define paPrimeOutputBuffersUsingStreamCallback ((PaStreamFlags) 0x00000008) + +/** A mask specifying the platform specific bits. + @see PaStreamFlags +*/ +#define paPlatformSpecificFlags ((PaStreamFlags)0xFFFF0000) + +/** + Timing information for the buffers passed to the stream callback. + + Time values are expressed in seconds and are synchronised with the time base used by Pa_GetStreamTime() for the associated stream. + + @see PaStreamCallback, Pa_GetStreamTime +*/ +typedef struct PaStreamCallbackTimeInfo{ + PaTime inputBufferAdcTime; /**< The time when the first sample of the input buffer was captured at the ADC input */ + PaTime currentTime; /**< The time when the stream callback was invoked */ + PaTime outputBufferDacTime; /**< The time when the first sample of the output buffer will output the DAC */ +} PaStreamCallbackTimeInfo; + + +/** + Flag bit constants for the statusFlags to PaStreamCallback. + + @see paInputUnderflow, paInputOverflow, paOutputUnderflow, paOutputOverflow, + paPrimingOutput +*/ +typedef unsigned long PaStreamCallbackFlags; + +/** In a stream opened with paFramesPerBufferUnspecified, indicates that + input data is all silence (zeros) because no real data is available. In a + stream opened without paFramesPerBufferUnspecified, it indicates that one or + more zero samples have been inserted into the input buffer to compensate + for an input underflow. + @see PaStreamCallbackFlags +*/ +#define paInputUnderflow ((PaStreamCallbackFlags) 0x00000001) + +/** In a stream opened with paFramesPerBufferUnspecified, indicates that data + prior to the first sample of the input buffer was discarded due to an + overflow, possibly because the stream callback is using too much CPU time. + Otherwise indicates that data prior to one or more samples in the + input buffer was discarded. + @see PaStreamCallbackFlags +*/ +#define paInputOverflow ((PaStreamCallbackFlags) 0x00000002) + +/** Indicates that output data (or a gap) was inserted, possibly because the + stream callback is using too much CPU time. + @see PaStreamCallbackFlags +*/ +#define paOutputUnderflow ((PaStreamCallbackFlags) 0x00000004) + +/** Indicates that output data will be discarded because no room is available. + @see PaStreamCallbackFlags +*/ +#define paOutputOverflow ((PaStreamCallbackFlags) 0x00000008) + +/** Some of all of the output data will be used to prime the stream, input + data may be zero. + @see PaStreamCallbackFlags +*/ +#define paPrimingOutput ((PaStreamCallbackFlags) 0x00000010) + +/** + Allowable return values for the PaStreamCallback. + @see PaStreamCallback +*/ +typedef enum PaStreamCallbackResult +{ + paContinue=0, /**< Signal that the stream should continue invoking the callback and processing audio. */ + paComplete=1, /**< Signal that the stream should stop invoking the callback and finish once all output samples have played. */ + paAbort=2 /**< Signal that the stream should stop invoking the callback and finish as soon as possible. */ +} PaStreamCallbackResult; + + +/** + Functions of type PaStreamCallback are implemented by PortAudio clients. + They consume, process or generate audio in response to requests from an + active PortAudio stream. + + When a stream is running, PortAudio calls the stream callback periodically. + The callback function is responsible for processing buffers of audio samples + passed via the input and output parameters. + + The PortAudio stream callback runs at very high or real-time priority. + It is required to consistently meet its time deadlines. Do not allocate + memory, access the file system, call library functions or call other functions + from the stream callback that may block or take an unpredictable amount of + time to complete. + + In order for a stream to maintain glitch-free operation the callback + must consume and return audio data faster than it is recorded and/or + played. PortAudio anticipates that each callback invocation may execute for + a duration approaching the duration of frameCount audio frames at the stream + sample rate. It is reasonable to expect to be able to utilise 70% or more of + the available CPU time in the PortAudio callback. However, due to buffer size + adaption and other factors, not all host APIs are able to guarantee audio + stability under heavy CPU load with arbitrary fixed callback buffer sizes. + When high callback CPU utilisation is required the most robust behavior + can be achieved by using paFramesPerBufferUnspecified as the + Pa_OpenStream() framesPerBuffer parameter. + + @param input and @param output are either arrays of interleaved samples or; + if non-interleaved samples were requested using the paNonInterleaved sample + format flag, an array of buffer pointers, one non-interleaved buffer for + each channel. + + The format, packing and number of channels used by the buffers are + determined by parameters to Pa_OpenStream(). + + @param frameCount The number of sample frames to be processed by + the stream callback. + + @param timeInfo Timestamps indicating the ADC capture time of the first sample + in the input buffer, the DAC output time of the first sample in the output buffer + and the time the callback was invoked. + See PaStreamCallbackTimeInfo and Pa_GetStreamTime() + + @param statusFlags Flags indicating whether input and/or output buffers + have been inserted or will be dropped to overcome underflow or overflow + conditions. + + @param userData The value of a user supplied pointer passed to + Pa_OpenStream() intended for storing synthesis data etc. + + @return + The stream callback should return one of the values in the + ::PaStreamCallbackResult enumeration. To ensure that the callback continues + to be called, it should return paContinue (0). Either paComplete or paAbort + can be returned to finish stream processing, after either of these values is + returned the callback will not be called again. If paAbort is returned the + stream will finish as soon as possible. If paComplete is returned, the stream + will continue until all buffers generated by the callback have been played. + This may be useful in applications such as soundfile players where a specific + duration of output is required. However, it is not necessary to utilize this + mechanism as Pa_StopStream(), Pa_AbortStream() or Pa_CloseStream() can also + be used to stop the stream. The callback must always fill the entire output + buffer irrespective of its return value. + + @see Pa_OpenStream, Pa_OpenDefaultStream + + @note With the exception of Pa_GetStreamCpuLoad() it is not permissible to call + PortAudio API functions from within the stream callback. +*/ +typedef int PaStreamCallback( + const void *input, void *output, + unsigned long frameCount, + const PaStreamCallbackTimeInfo* timeInfo, + PaStreamCallbackFlags statusFlags, + void *userData ); + + +/** Opens a stream for either input, output or both. + + @param stream The address of a PaStream pointer which will receive + a pointer to the newly opened stream. + + @param inputParameters A structure that describes the input parameters used by + the opened stream. See PaStreamParameters for a description of these parameters. + inputParameters must be NULL for output-only streams. + + @param outputParameters A structure that describes the output parameters used by + the opened stream. See PaStreamParameters for a description of these parameters. + outputParameters must be NULL for input-only streams. + + @param sampleRate The desired sampleRate. For full-duplex streams it is the + sample rate for both input and output + + @param framesPerBuffer The number of frames passed to the stream callback + function, or the preferred block granularity for a blocking read/write stream. + The special value paFramesPerBufferUnspecified (0) may be used to request that + the stream callback will receive an optimal (and possibly varying) number of + frames based on host requirements and the requested latency settings. + Note: With some host APIs, the use of non-zero framesPerBuffer for a callback + stream may introduce an additional layer of buffering which could introduce + additional latency. PortAudio guarantees that the additional latency + will be kept to the theoretical minimum however, it is strongly recommended + that a non-zero framesPerBuffer value only be used when your algorithm + requires a fixed number of frames per stream callback. + + @param streamFlags Flags which modify the behavior of the streaming process. + This parameter may contain a combination of flags ORed together. Some flags may + only be relevant to certain buffer formats. + + @param streamCallback A pointer to a client supplied function that is responsible + for processing and filling input and output buffers. If this parameter is NULL + the stream will be opened in 'blocking read/write' mode. In blocking mode, + the client can receive sample data using Pa_ReadStream and write sample data + using Pa_WriteStream, the number of samples that may be read or written + without blocking is returned by Pa_GetStreamReadAvailable and + Pa_GetStreamWriteAvailable respectively. + + @param userData A client supplied pointer which is passed to the stream callback + function. It could for example, contain a pointer to instance data necessary + for processing the audio buffers. This parameter is ignored if streamCallback + is NULL. + + @return + Upon success Pa_OpenStream() returns paNoError and places a pointer to a + valid PaStream in the stream argument. The stream is inactive (stopped). + If a call to Pa_OpenStream() fails, a non-zero error code is returned (see + PaError for possible error codes) and the value of stream is invalid. + + @see PaStreamParameters, PaStreamCallback, Pa_ReadStream, Pa_WriteStream, + Pa_GetStreamReadAvailable, Pa_GetStreamWriteAvailable +*/ +PaError Pa_OpenStream( PaStream** stream, + const PaStreamParameters *inputParameters, + const PaStreamParameters *outputParameters, + double sampleRate, + unsigned long framesPerBuffer, + PaStreamFlags streamFlags, + PaStreamCallback *streamCallback, + void *userData ); + + +/** A simplified version of Pa_OpenStream() that opens the default input + and/or output devices. + + @param stream The address of a PaStream pointer which will receive + a pointer to the newly opened stream. + + @param numInputChannels The number of channels of sound that will be supplied + to the stream callback or returned by Pa_ReadStream. It can range from 1 to + the value of maxInputChannels in the PaDeviceInfo record for the default input + device. If 0 the stream is opened as an output-only stream. + + @param numOutputChannels The number of channels of sound to be delivered to the + stream callback or passed to Pa_WriteStream. It can range from 1 to the value + of maxOutputChannels in the PaDeviceInfo record for the default output device. + If 0 the stream is opened as an output-only stream. + + @param sampleFormat The sample format of both the input and output buffers + provided to the callback or passed to and from Pa_ReadStream and Pa_WriteStream. + sampleFormat may be any of the formats described by the PaSampleFormat + enumeration. + + @param sampleRate Same as Pa_OpenStream parameter of the same name. + @param framesPerBuffer Same as Pa_OpenStream parameter of the same name. + @param streamCallback Same as Pa_OpenStream parameter of the same name. + @param userData Same as Pa_OpenStream parameter of the same name. + + @return As for Pa_OpenStream + + @see Pa_OpenStream, PaStreamCallback +*/ +PaError Pa_OpenDefaultStream( PaStream** stream, + int numInputChannels, + int numOutputChannels, + PaSampleFormat sampleFormat, + double sampleRate, + unsigned long framesPerBuffer, + PaStreamCallback *streamCallback, + void *userData ); + + +/** Closes an audio stream. If the audio stream is active it + discards any pending buffers as if Pa_AbortStream() had been called. +*/ +PaError Pa_CloseStream( PaStream *stream ); + + +/** Functions of type PaStreamFinishedCallback are implemented by PortAudio + clients. They can be registered with a stream using the Pa_SetStreamFinishedCallback + function. Once registered they are called when the stream becomes inactive + (ie once a call to Pa_StopStream() will not block). + A stream will become inactive after the stream callback returns non-zero, + or when Pa_StopStream or Pa_AbortStream is called. For a stream providing audio + output, if the stream callback returns paComplete, or Pa_StopStream() is called, + the stream finished callback will not be called until all generated sample data + has been played. + + @param userData The userData parameter supplied to Pa_OpenStream() + + @see Pa_SetStreamFinishedCallback +*/ +typedef void PaStreamFinishedCallback( void *userData ); + + +/** Register a stream finished callback function which will be called when the + stream becomes inactive. See the description of PaStreamFinishedCallback for + further details about when the callback will be called. + + @param stream a pointer to a PaStream that is in the stopped state - if the + stream is not stopped, the stream's finished callback will remain unchanged + and an error code will be returned. + + @param streamFinishedCallback a pointer to a function with the same signature + as PaStreamFinishedCallback, that will be called when the stream becomes + inactive. Passing NULL for this parameter will un-register a previously + registered stream finished callback function. + + @return on success returns paNoError, otherwise an error code indicating the cause + of the error. + + @see PaStreamFinishedCallback +*/ +PaError Pa_SetStreamFinishedCallback( PaStream *stream, PaStreamFinishedCallback* streamFinishedCallback ); + + +/** Commences audio processing. +*/ +PaError Pa_StartStream( PaStream *stream ); + + +/** Terminates audio processing. It waits until all pending + audio buffers have been played before it returns. +*/ +PaError Pa_StopStream( PaStream *stream ); + + +/** Terminates audio processing immediately without waiting for pending + buffers to complete. +*/ +PaError Pa_AbortStream( PaStream *stream ); + + +/** Determine whether the stream is stopped. + A stream is considered to be stopped prior to a successful call to + Pa_StartStream and after a successful call to Pa_StopStream or Pa_AbortStream. + If a stream callback returns a value other than paContinue the stream is NOT + considered to be stopped. + + @return Returns one (1) when the stream is stopped, zero (0) when + the stream is running or, a PaErrorCode (which are always negative) if + PortAudio is not initialized or an error is encountered. + + @see Pa_StopStream, Pa_AbortStream, Pa_IsStreamActive +*/ +PaError Pa_IsStreamStopped( PaStream *stream ); + + +/** Determine whether the stream is active. + A stream is active after a successful call to Pa_StartStream(), until it + becomes inactive either as a result of a call to Pa_StopStream() or + Pa_AbortStream(), or as a result of a return value other than paContinue from + the stream callback. In the latter case, the stream is considered inactive + after the last buffer has finished playing. + + @return Returns one (1) when the stream is active (ie playing or recording + audio), zero (0) when not playing or, a PaErrorCode (which are always negative) + if PortAudio is not initialized or an error is encountered. + + @see Pa_StopStream, Pa_AbortStream, Pa_IsStreamStopped +*/ +PaError Pa_IsStreamActive( PaStream *stream ); + + + +/** A structure containing unchanging information about an open stream. + @see Pa_GetStreamInfo +*/ + +typedef struct PaStreamInfo +{ + /** this is struct version 1 */ + int structVersion; + + /** The input latency of the stream in seconds. This value provides the most + accurate estimate of input latency available to the implementation. It may + differ significantly from the suggestedLatency value passed to Pa_OpenStream(). + The value of this field will be zero (0.) for output-only streams. + @see PaTime + */ + PaTime inputLatency; + + /** The output latency of the stream in seconds. This value provides the most + accurate estimate of output latency available to the implementation. It may + differ significantly from the suggestedLatency value passed to Pa_OpenStream(). + The value of this field will be zero (0.) for input-only streams. + @see PaTime + */ + PaTime outputLatency; + + /** The sample rate of the stream in Hertz (samples per second). In cases + where the hardware sample rate is inaccurate and PortAudio is aware of it, + the value of this field may be different from the sampleRate parameter + passed to Pa_OpenStream(). If information about the actual hardware sample + rate is not available, this field will have the same value as the sampleRate + parameter passed to Pa_OpenStream(). + */ + double sampleRate; + +} PaStreamInfo; + + +/** Retrieve a pointer to a PaStreamInfo structure containing information + about the specified stream. + @return A pointer to an immutable PaStreamInfo structure. If the stream + parameter is invalid, or an error is encountered, the function returns NULL. + + @param stream A pointer to an open stream previously created with Pa_OpenStream. + + @note PortAudio manages the memory referenced by the returned pointer, + the client must not manipulate or free the memory. The pointer is only + guaranteed to be valid until the specified stream is closed. + + @see PaStreamInfo +*/ +const PaStreamInfo* Pa_GetStreamInfo( PaStream *stream ); + + +/** Returns the current time in seconds for a stream according to the same clock used + to generate callback PaStreamCallbackTimeInfo timestamps. The time values are + monotonically increasing and have unspecified origin. + + Pa_GetStreamTime returns valid time values for the entire life of the stream, + from when the stream is opened until it is closed. Starting and stopping the stream + does not affect the passage of time returned by Pa_GetStreamTime. + + This time may be used for synchronizing other events to the audio stream, for + example synchronizing audio to MIDI. + + @return The stream's current time in seconds, or 0 if an error occurred. + + @see PaTime, PaStreamCallback, PaStreamCallbackTimeInfo +*/ +PaTime Pa_GetStreamTime( PaStream *stream ); + + +/** Retrieve CPU usage information for the specified stream. + The "CPU Load" is a fraction of total CPU time consumed by a callback stream's + audio processing routines including, but not limited to the client supplied + stream callback. This function does not work with blocking read/write streams. + + This function may be called from the stream callback function or the + application. + + @return + A floating point value, typically between 0.0 and 1.0, where 1.0 indicates + that the stream callback is consuming the maximum number of CPU cycles possible + to maintain real-time operation. A value of 0.5 would imply that PortAudio and + the stream callback was consuming roughly 50% of the available CPU time. The + return value may exceed 1.0. A value of 0.0 will always be returned for a + blocking read/write stream, or if an error occurs. +*/ +double Pa_GetStreamCpuLoad( PaStream* stream ); + + +/** Read samples from an input stream. The function doesn't return until + the entire buffer has been filled - this may involve waiting for the operating + system to supply the data. + + @param stream A pointer to an open stream previously created with Pa_OpenStream. + + @param buffer A pointer to a buffer of sample frames. The buffer contains + samples in the format specified by the inputParameters->sampleFormat field + used to open the stream, and the number of channels specified by + inputParameters->numChannels. If non-interleaved samples were requested using + the paNonInterleaved sample format flag, buffer is a pointer to the first element + of an array of buffer pointers, one non-interleaved buffer for each channel. + + @param frames The number of frames to be read into buffer. This parameter + is not constrained to a specific range, however high performance applications + will want to match this parameter to the framesPerBuffer parameter used + when opening the stream. + + @return On success PaNoError will be returned, or PaInputOverflowed if input + data was discarded by PortAudio after the previous call and before this call. +*/ +PaError Pa_ReadStream( PaStream* stream, + void *buffer, + unsigned long frames ); + + +/** Write samples to an output stream. This function doesn't return until the + entire buffer has been written - this may involve waiting for the operating + system to consume the data. + + @param stream A pointer to an open stream previously created with Pa_OpenStream. + + @param buffer A pointer to a buffer of sample frames. The buffer contains + samples in the format specified by the outputParameters->sampleFormat field + used to open the stream, and the number of channels specified by + outputParameters->numChannels. If non-interleaved samples were requested using + the paNonInterleaved sample format flag, buffer is a pointer to the first element + of an array of buffer pointers, one non-interleaved buffer for each channel. + + @param frames The number of frames to be written from buffer. This parameter + is not constrained to a specific range, however high performance applications + will want to match this parameter to the framesPerBuffer parameter used + when opening the stream. + + @return On success PaNoError will be returned, or paOutputUnderflowed if + additional output data was inserted after the previous call and before this + call. +*/ +PaError Pa_WriteStream( PaStream* stream, + const void *buffer, + unsigned long frames ); + + +/** Retrieve the number of frames that can be read from the stream without + waiting. + + @return Returns a non-negative value representing the maximum number of frames + that can be read from the stream without blocking or busy waiting or, a + PaErrorCode (which are always negative) if PortAudio is not initialized or an + error is encountered. +*/ +signed long Pa_GetStreamReadAvailable( PaStream* stream ); + + +/** Retrieve the number of frames that can be written to the stream without + waiting. + + @return Returns a non-negative value representing the maximum number of frames + that can be written to the stream without blocking or busy waiting or, a + PaErrorCode (which are always negative) if PortAudio is not initialized or an + error is encountered. +*/ +signed long Pa_GetStreamWriteAvailable( PaStream* stream ); + + +/* Miscellaneous utilities */ + + +/** Retrieve the size of a given sample format in bytes. + + @return The size in bytes of a single sample in the specified format, + or paSampleFormatNotSupported if the format is not supported. +*/ +PaError Pa_GetSampleSize( PaSampleFormat format ); + + +/** Put the caller to sleep for at least 'msec' milliseconds. This function is + provided only as a convenience for authors of portable code (such as the tests + and examples in the PortAudio distribution.) + + The function may sleep longer than requested so don't rely on this for accurate + musical timing. +*/ +void Pa_Sleep( long msec ); + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* PORTAUDIO_H */ diff --git a/deps/usr/lib/pa_shim.so b/deps/usr/lib/pa_shim.so deleted file mode 100755 index 228a44d1f3a98412d8a8a3c3238139445d4e1b11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8536 zcmd^EZE##w89tkBnv|y5w1C7GWyMws!pj z0OLNo#rG_OZ$bm9J>Ej?4tqiHAqf2ZKLME^ZU7JC@s=|H{Ni>34||otC-7YDgZ~!T zS|7Yaw(|;cpebA-ErMGou*g=~a8^loOZ{eX(4+rTrGHfEuUG5hy9&=LoaU8ExANnS zOJlPRK@ZePHRtC85?>=8UhP13Mc0S3xiP(98F@?Bg`OG9SVB*O2z~edem!O8&EZVJ zGV}ZUdq;C)=6+*n)U;*(5D5~!t&w(TnAJprr&x*&bXG3A>kM=UB8Oncg%&mUlq-Tt5;5X(U0s-w{88em ziwn<7K2JP#ZQ%*Y-$6W0$-=bchlr=HEF6>kKkC9FJq=zKZL0egC}>l)L7K<>@tigpU(_aJ zU{B58d9hr^NCfV!I~6}i6W|D^`p>;cGo+P%Mv4!RqHP$a(Za|{FJWzR0NxUvTItv2 z+3D9#%3xEqo8fHGW+vW_A@aOdDxTI#19Mubf3~j_f3>gFKLaN-S}A@O6iv|9pwIc*=aZJ~Q={;L3oWc<9AoCQ9ob)C>c zJ5K;p5$dV!*EkGpbZN6lz46$fThuBU<>QVC>_1G*WULw0OJUa)KOfo?KVOQI6DO23 zyWMGubTrwIQINygg{aCUby^N5R4@XQ1E7h`ayZHQQSGMqTwyIKzl@=f{e1JhV@(|j zeeUZJI6WXgcrW`;t5`2BY5T^Cs#uFE)}V}K&;6;jx^RNslLo!kI#N&p=!$uf;UCc0@^%M@0ZJcpnn9lK+mChUj#KU zIo|*s1N{joofoMDjwVFlNK;@#LtXte#%CiiItwMrw)Hn% z*S7I$g2{ddo)PG|zZYctDLe-eSDuBoH#Xg0)4OJ6%?KjczVC+oS;*xXhvk|S%h-=Y z{$*`@p9lE+&qF~=n+lyRs5IEbIUn+QlFx-7RB}FVY*0MUrE_gm z=MI`zDlGro#d41Lvnn2+C88?`weNaFJ81((;j_c-N}taR&9+$HZ)8<{mz9}#TFH66 z@;Ceng+IU2t}s5Q8p7?IQ+lfu<#^a|W&2-H`uLQ~Rp8xpUccglw#OH;KD z|04CP^C1@{UcDYJL&w69c}ogAh8Oo$|m4` z`rD*_gYf2;27q5(AaCO^;9vN9fygFlPRtWRdtw_P28E--XGWFdv;JVOg5P7sX|U4F~(Aq{n~Ncp6&g+ zd!d0(q8`_D+f3V$0E9#tJJ{8?w`Y5wzIW%&TjTrn{o8x`;&A&f@@jr5vC0&c%02lh zdU9uW7SB#z#bWN$(ez`w873XOV4Tx_tkwaDH z`SgkuqsNy_VA^@VN{NUR#I&FpUlYcSTQnG%#5aP$fShiWL7bf8XtqD zkkrcClEY@ckjafzFgj#;bJQS3RXa3liHK}b1l7oJ4ygK1X{#$M_GG5Ofq`d%iy~UBrG!h2m0`?fG0E z14h2tp3jj?`ThYFS(H0wg@zj41=ya?n@q1$n%sWYV>$pi-7T2sb1BoXviG)M!6JnU z$=IIHuMSm;9N*jjF=gMQ^!S|1^l6tpzS33WcLW%XiMm!f=VAUo1K+!p8`)N_6D{Cz z+w-}Z=`m7r75?@!{VZf|dp=(?<^Hk@FaHIPz0*OZ_%IKga=>xf-;~Fm&+AP29?AMN zSMKs9Fw}mYKR(wp&A63O_qP8rkNtB0w`4co_|JIk`JTY^`)sJFH~zPQQ(m2iiSHBq ze@(AG^GtsL+mOrNxp$CL6xOr3C7$sgLqOxl@%esI|8MNs-z+M$cG;fqG5mk$8FG%o zSQg9PCcKgBoE`2eB(`@8pG)obBC|*S_1u5f#5#Z7lSixd9KipZ9Ni izqsvg`)S&&P$oUjIj$|W&!&F%8`RbEJyulIYyVHmTFGeu diff --git a/deps/usr/lib/pa_shim_arm-linux-gnueabihf.so b/deps/usr/lib/pa_shim_arm-linux-gnueabihf.so new file mode 100755 index 0000000000000000000000000000000000000000..fc997729717e619fcb4fce3deabb7ee690b9b04a GIT binary patch literal 6376 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 literal 0 HcmV?d00001 diff --git a/deps/usr/lib/pa_shim_i686-w64-mingw32.dll b/deps/usr/lib/pa_shim_i686-w64-mingw32.dll new file mode 100755 index 0000000000000000000000000000000000000000..956032baf7284bb152631a84c6d37aaafd2140c7 GIT binary patch literal 81524 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 delta 893 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 C&;dFC literal 0 HcmV?d00001 diff --git a/deps/usr/lib/pa_shim_x86_64-w64-mingw32.dll b/deps/usr/lib/pa_shim_x86_64-w64-mingw32.dll new file mode 100755 index 0000000000000000000000000000000000000000..1a39c4434e26670c415dba8639f3b4cec8b4eb5f GIT binary patch literal 110424 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 B`&j@0 literal 0 HcmV?d00001 diff --git a/src/pa_shim.jl b/src/pa_shim.jl index acd81fa..c1100be 100644 --- a/src/pa_shim.jl +++ b/src/pa_shim.jl @@ -1,7 +1,28 @@ function init_pa_shim() - global const libpa_shim = Libdl.find_library( - ["pa_shim"], - [joinpath(dirname(@__FILE__), "..", "deps", "usr", "lib")]) + libdir = joinpath(dirname(@__FILE__), "..", "deps", "usr", "lib") + libsuffix = "" + basename = "pa_shim" + @static if is_linux() && Sys.ARCH == :x86_64 + libsuffix = "x86_64-linux-gnu" + elseif is_linux() && Sys.ARCH == :i686 + libsuffix = "i686-linux-gnu" + elseif is_apple() && Sys.ARCH == :x86_64 + libsuffix = "x86_64-apple-darwin14" + elseif is_windows() && Sys.ARCH == :x86_64 + libsuffix = "x86_64-w64-mingw32" + elseif is_windows() && Sys.ARCH == :i686 + libsuffix = "i686-w64-mingw32" + elseif !any( + (sfx) -> isfile(joinpath(libdir, "$basename.$sfx")), + ("so", "dll", "dylib")) + error("Unsupported platform $(Sys.MACHINE). You can build your own library by running `make` from $(joinpath(@__FILE__, "..", "deps", "src"))") + end + # if there's a suffix-less library, it was built natively on this machine, + # so load that one first, otherwise load the pre-built one + global const libpa_shim = Base.Libdl.find_library( + [basename, "$(basename)_$libsuffix"], + [libdir]) + libpa_shim == "" && error("Could not load $basename library, please file an issue at https://github.com/JuliaAudio/RingBuffers.jl/issues with your `versioninfo()` output") shim_dlib = Libdl.dlopen(libpa_shim) # pointer to the shim's process callback global const shim_processcb_c = Libdl.dlsym(shim_dlib, :pa_shim_processcb) diff --git a/test/runtests.jl b/test/runtests.jl index 0c26a30..2a40ac0 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -177,9 +177,8 @@ function test_callback_overflow(inchans, outchans, synced) end end -# these test are currently set up to run on OSX - -@testset DottedTestSet "PortAudio Tests" begin +# these default values are specific to my machines +@testset ExtendedTestSet "PortAudio Tests" begin if is_windows() default_indev = "Microphone Array (Realtek High " default_outdev = "Speaker/Headphone (Realtek High" @@ -205,7 +204,10 @@ end result = split(String(take!((io))), "\n") # make sure this is the same version I tested with @test startswith(result[1], "PortAudio V19") - @test result[3] == "Shim Source Hash: 4ea2a8526b" + end + + @testset "using correct shim version" begin + @test PortAudio.shimhash() == "87021557a9f999545828eb11e4ebad2cd278b734dd91a8bd3faf05c89912cf80" end @testset "Basic callback functionality" begin