Recreate and apply JACK dynload patch

This commit is contained in:
Leland Lucius 2019-12-15 02:39:11 -06:00
parent be7467c0e3
commit 99010038a5
10 changed files with 1003 additions and 149 deletions

View File

@ -281,9 +281,9 @@ ELSE()
ENDIF()
IF(PA_USE_JACK)
SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} ${JACK_INCLUDE_DIRS})
SET(PA_JACK_SOURCES src/hostapi/jack/pa_jack.c)
SET(PA_JACK_SOURCES src/hostapi/jack/pa_jack.c src/hostapi/jack/pa_jack_dynload.c)
SOURCE_GROUP("hostapi\\JACK" FILES ${PA_JACK_SOURCES})
SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_jack.h)
SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_jack.h src/hostapi/jack/pa_jack_dynload.h)
SET(PA_SOURCES ${PA_SOURCES} ${PA_JACK_SOURCES})
SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PA_USE_JACK)
SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} ${JACK_LIBRARIES})

View File

@ -53,6 +53,7 @@ COMMON_OBJS = \
src/common/pa_cpuload.o \
src/common/pa_dither.o \
src/common/pa_debugprint.o \
src/common/pa_dynload.o \
src/common/pa_front.o \
src/common/pa_process.o \
src/common/pa_stream.o \

View File

@ -412,7 +412,7 @@ case "${host_os}" in
if [[ "$have_jack" = "yes" ] && [ "$with_jack" != "no" ]] ; then
DLL_LIBS="$DLL_LIBS $JACK_LIBS"
CFLAGS="$CFLAGS $JACK_CFLAGS"
OTHER_OBJS="$OTHER_OBJS src/hostapi/jack/pa_jack.o src/common/pa_ringbuffer.o"
OTHER_OBJS="$OTHER_OBJS src/hostapi/jack/pa_jack.o src/common/pa_ringbuffer.o src/hostapi/jack/pa_jack_dynload.o"
INCLUDES="$INCLUDES pa_jack.h"
AC_DEFINE(PA_USE_JACK,1)
fi

View File

@ -1,7 +1,49 @@
Index: portaudio-v19/src/common/pa_dynload.c
===================================================================
--- portaudio-v19/src/common/pa_dynload.c (revision 0)
+++ portaudio-v19/src/common/pa_dynload.c (working copy)
diff --git a/lib-src/portaudio-v19/CMakeLists.txt b/lib-src/portaudio-v19/CMakeLists.txt
index 102401674..06c23bf47 100644
--- a/lib-src/portaudio-v19/CMakeLists.txt
+++ b/lib-src/portaudio-v19/CMakeLists.txt
@@ -281,9 +281,9 @@ ELSE()
ENDIF()
IF(PA_USE_JACK)
SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} ${JACK_INCLUDE_DIRS})
- SET(PA_JACK_SOURCES src/hostapi/jack/pa_jack.c)
+ SET(PA_JACK_SOURCES src/hostapi/jack/pa_jack.c src/hostapi/jack/pa_jack_dynload.c)
SOURCE_GROUP("hostapi\\JACK" FILES ${PA_JACK_SOURCES})
- SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_jack.h)
+ SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_jack.h src/hostapi/jack/pa_jack_dynload.h)
SET(PA_SOURCES ${PA_SOURCES} ${PA_JACK_SOURCES})
SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PA_USE_JACK)
SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} ${JACK_LIBRARIES})
diff --git a/lib-src/portaudio-v19/Makefile.in b/lib-src/portaudio-v19/Makefile.in
index 918bbad42..22ed79ad3 100644
--- a/lib-src/portaudio-v19/Makefile.in
+++ b/lib-src/portaudio-v19/Makefile.in
@@ -53,6 +53,7 @@ COMMON_OBJS = \
src/common/pa_cpuload.o \
src/common/pa_dither.o \
src/common/pa_debugprint.o \
+ src/common/pa_dynload.o \
src/common/pa_front.o \
src/common/pa_process.o \
src/common/pa_stream.o \
diff --git a/lib-src/portaudio-v19/configure.in b/lib-src/portaudio-v19/configure.in
index b2129ba68..a3628bd09 100644
--- a/lib-src/portaudio-v19/configure.in
+++ b/lib-src/portaudio-v19/configure.in
@@ -412,7 +412,7 @@ case "${host_os}" in
if [[ "$have_jack" = "yes" ] && [ "$with_jack" != "no" ]] ; then
DLL_LIBS="$DLL_LIBS $JACK_LIBS"
CFLAGS="$CFLAGS $JACK_CFLAGS"
- OTHER_OBJS="$OTHER_OBJS src/hostapi/jack/pa_jack.o src/common/pa_ringbuffer.o"
+ OTHER_OBJS="$OTHER_OBJS src/hostapi/jack/pa_jack.o src/common/pa_ringbuffer.o src/hostapi/jack/pa_jack_dynload.o"
INCLUDES="$INCLUDES pa_jack.h"
AC_DEFINE(PA_USE_JACK,1)
fi
diff --git a/lib-src/portaudio-v19/src/common/pa_dynload.c b/lib-src/portaudio-v19/src/common/pa_dynload.c
new file mode 100644
index 000000000..337266515
--- /dev/null
+++ b/lib-src/portaudio-v19/src/common/pa_dynload.c
@@ -0,0 +1,108 @@
+/*
+ * $Id: pa_dynlink.c 1339 2008-02-15 07:50:33Z rossb $
@ -111,10 +153,11 @@ Index: portaudio-v19/src/common/pa_dynload.c
+
+ return addr;
+}
Index: portaudio-v19/src/common/pa_dynload.h
===================================================================
--- portaudio-v19/src/common/pa_dynload.h (revision 0)
+++ portaudio-v19/src/common/pa_dynload.h (working copy)
diff --git a/lib-src/portaudio-v19/src/common/pa_dynload.h b/lib-src/portaudio-v19/src/common/pa_dynload.h
new file mode 100644
index 000000000..f586c138f
--- /dev/null
+++ b/lib-src/portaudio-v19/src/common/pa_dynload.h
@@ -0,0 +1,136 @@
+#ifndef PA_DYNLINK_H
+#define PA_DYNLINK_H
@ -252,10 +295,10 @@ Index: portaudio-v19/src/common/pa_dynload.h
+}
+#endif /* __cplusplus */
+#endif /* PA_DYNLINK_H */
Index: portaudio-v19/src/hostapi/jack/pa_jack.c
===================================================================
--- portaudio-v19/src/hostapi/jack/pa_jack.c (revision 12233)
+++ portaudio-v19/src/hostapi/jack/pa_jack.c (working copy)
diff --git a/lib-src/portaudio-v19/src/hostapi/jack/pa_jack.c b/lib-src/portaudio-v19/src/hostapi/jack/pa_jack.c
index a800f8e1d..887128c3b 100644
--- a/lib-src/portaudio-v19/src/hostapi/jack/pa_jack.c
+++ b/lib-src/portaudio-v19/src/hostapi/jack/pa_jack.c
@@ -48,16 +48,22 @@
*/
@ -294,7 +337,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
static char *jackErr_ = NULL;
static const char* clientName_ = "PortAudio";
@@ -84,7 +96,7 @@
@@ -84,7 +96,7 @@ static const char* clientName_ = "PortAudio";
PaError paErr; \
if( (paErr = (expr)) < paNoError ) \
{ \
@ -303,7 +346,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
{ \
const char *err = jackErr_; \
if (! err ) err = "unknown error"; \
@@ -100,7 +112,7 @@
@@ -100,7 +112,7 @@ static const char* clientName_ = "PortAudio";
do { \
if( (expr) == 0 ) \
{ \
@ -312,7 +355,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
{ \
const char *err = jackErr_; \
if (!err) err = "unknown error"; \
@@ -166,8 +178,13 @@
@@ -166,8 +178,13 @@ typedef struct
int jack_buffer_size;
PaHostApiIndex hostApiIndex;
@ -326,7 +369,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
unsigned long inputBase, outputBase;
/* For dealing with the process thread */
@@ -224,7 +241,11 @@
@@ -224,7 +241,11 @@ typedef struct PaJackStream
PaUtilRingBuffer inFIFO;
PaUtilRingBuffer outFIFO;
volatile sig_atomic_t data_available;
@ -338,7 +381,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
int bytesPerFrame;
int samplesPerFrame;
@@ -248,6 +269,178 @@
@@ -252,6 +273,178 @@ static int JackCallback( jack_nframes_t frames, void *userData );
*
*/
@ -517,7 +560,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
/* ---- blocking emulation layer ---- */
/* Allocate buffer. */
@@ -294,7 +487,7 @@
@@ -298,7 +491,7 @@ BlockingCallback( const void *inputBuffer,
if( !stream->data_available )
{
stream->data_available = 1;
@ -526,7 +569,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
}
return paContinue;
}
@@ -333,7 +526,7 @@
@@ -337,7 +530,7 @@ BlockingBegin( PaJackStream *stream, int minimum_buffer_size )
}
stream->data_available = 0;
@ -535,7 +578,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
error:
return result;
@@ -345,7 +538,7 @@
@@ -349,7 +542,7 @@ BlockingEnd( PaJackStream *stream )
BlockingTermFIFO( &stream->inFIFO );
BlockingTermFIFO( &stream->outFIFO );
@ -544,7 +587,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
}
static PaError BlockingReadStream( PaStream* s, void *data, unsigned long numFrames )
@@ -367,7 +560,7 @@
@@ -371,7 +564,7 @@ static PaError BlockingReadStream( PaStream* s, void *data, unsigned long numFra
if( stream->data_available )
stream->data_available = 0;
else
@ -553,7 +596,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
}
}
@@ -405,7 +598,7 @@
@@ -409,7 +602,7 @@ static PaError BlockingWriteStream( PaStream* s, const void *data, unsigned long
if( stream->data_available )
stream->data_available = 0;
else
@ -562,7 +605,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
}
}
@@ -438,7 +631,7 @@
@@ -442,7 +635,7 @@ BlockingWaitEmpty( PaStream *s )
while( PaUtil_GetRingBufferReadAvailable( &stream->outFIFO ) > 0 )
{
stream->data_available = 0;
@ -571,7 +614,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
}
return 0;
}
@@ -469,7 +662,6 @@
@@ -473,7 +666,6 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
char *regex_pattern = NULL;
int port_index, client_index, i;
double globalSampleRate;
@ -579,7 +622,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
unsigned long numClients = 0, numPorts = 0;
char *tmp_client_name = NULL;
@@ -477,9 +669,6 @@
@@ -481,9 +673,6 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
commonApi->info.defaultOutputDevice = paNoDevice;
commonApi->info.deviceCount = 0;
@ -589,16 +632,16 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
/* since we are rebuilding the list of devices, free all memory
* associated with the previous list */
PaUtil_FreeAllAllocations( jackApi->deviceInfoMemory );
@@ -492,7 +681,7 @@
@@ -496,7 +685,7 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
* according to the client_name:port_name convention (which is
* enforced by jackd)
* A: If jack_get_ports returns NULL, there's nothing for us to do */
- UNLESS( (jack_ports = jack_get_ports( jackApi->jack_client, "", "", 0 )) && jack_ports[0], paNoError );
+ UNLESS( (jack_ports = jack_get_ports( jackApi->jack_client, "^[^:]*", "", 0 )) && jack_ports[0], paNoError );
- UNLESS( (jack_ports = jack_get_ports( jackApi->jack_client, "", JACK_PORT_TYPE_FILTER, 0 )) && jack_ports[0], paNoError );
+ UNLESS( (jack_ports = jack_get_ports( jackApi->jack_client, "^[^:]*", JACK_PORT_TYPE_FILTER, 0 )) && jack_ports[0], paNoError );
/* Find number of ports */
while( jack_ports[numPorts] )
++numPorts;
@@ -504,16 +693,15 @@
@@ -508,16 +697,15 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
for( numClients = 0, port_index = 0; jack_ports[port_index] != NULL; port_index++ )
{
int client_seen = FALSE;
@ -620,7 +663,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
/* do we know about this port's client yet? */
for( i = 0; i < numClients; i++ )
@@ -599,7 +787,7 @@
@@ -603,7 +791,7 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
* We don't care what they are, we just care how many */
curDevInfo->maxInputChannels++;
}
@ -629,7 +672,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
}
/* ... what are your input ports (that we could output to)? */
@@ -620,7 +808,7 @@
@@ -624,7 +812,7 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
* We don't care what they are, we just care how many */
curDevInfo->maxOutputChannels++;
}
@ -638,7 +681,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
}
/* Add this client to the list of devices */
@@ -633,8 +821,7 @@
@@ -637,8 +825,7 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
}
error:
@ -648,7 +691,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
return result;
}
@@ -647,7 +834,7 @@
@@ -651,7 +838,7 @@ static void UpdateSampleRate( PaJackStream *stream, double sampleRate )
static void JackErrorCallback( const char *msg )
{
@ -657,7 +700,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
{
assert( msg );
jackErr_ = realloc( jackErr_, strlen( msg ) + 1 );
@@ -667,11 +854,10 @@
@@ -671,11 +858,10 @@ static void JackOnShutdown( void *arg )
}
/* Make sure that the main thread doesn't get stuck waiting on the condition */
@ -672,7 +715,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
}
static int JackSrCb( jack_nframes_t nframes, void *arg )
@@ -706,18 +892,20 @@
@@ -710,18 +896,20 @@ PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi,
PaHostApiIndex hostApiIndex )
{
PaError result = paNoError;
@ -697,7 +740,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
/* Try to become a client of the JACK server. If we cannot do
* this, then this API cannot be used.
@@ -803,6 +991,9 @@
@@ -807,6 +995,9 @@ error:
PaUtil_FreeMemory( jackHostApi );
}
@ -707,7 +750,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
return result;
}
@@ -815,8 +1006,8 @@
@@ -819,8 +1010,8 @@ static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
* client is not allowed to have any ports connected */
ASSERT_CALL( jack_deactivate( jackHostApi->jack_client ), 0 );
@ -718,7 +761,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
ASSERT_CALL( jack_client_close( jackHostApi->jack_client ), 0 );
@@ -830,6 +1021,8 @@
@@ -834,6 +1025,8 @@ static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
free( jackErr_ );
jackErr_ = NULL;
@ -727,7 +770,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
}
static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
@@ -997,39 +1190,19 @@
@@ -1001,39 +1194,19 @@ static void CleanUpStream( PaJackStream *stream, int terminateStreamRepresentati
PaUtil_FreeMemory( stream );
}
@ -770,7 +813,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
ENSURE_PA( result );
UNLESS( !hostApi->jackIsDown, paDeviceUnavailable );
@@ -1045,14 +1218,14 @@
@@ -1049,14 +1222,14 @@ static PaError RemoveStream( PaJackStream *stream )
PaJackHostApiRepresentation *hostApi = stream->hostApi;
/* Add to queue over streams that should be processed */
@ -788,7 +831,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
ENSURE_PA( result );
error:
@@ -1165,7 +1338,7 @@
@@ -1169,7 +1342,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
stream->isBlockingStream = !streamCallback;
if( stream->isBlockingStream )
{
@ -797,7 +840,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
int minimum_buffer_frames = 0;
if( inputParameters && inputParameters->suggestedLatency > latency )
@@ -1245,7 +1418,7 @@
@@ -1249,7 +1422,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
break;
}
}
@ -806,7 +849,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
UNLESS( !err, paInsufficientMemory );
/* Fewer ports than expected? */
@@ -1269,7 +1442,7 @@
@@ -1273,7 +1446,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
break;
}
}
@ -815,7 +858,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
UNLESS( !err , paInsufficientMemory );
/* Fewer ports than expected? */
@@ -1423,9 +1596,9 @@
@@ -1427,9 +1600,9 @@ static PaError UpdateQueue( PaJackHostApiRepresentation *hostApi )
const double jackSr = jack_get_sample_rate( hostApi->jack_client );
int err;
@ -827,7 +870,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
return paNoError;
}
@@ -1484,11 +1657,11 @@
@@ -1488,11 +1661,11 @@ static PaError UpdateQueue( PaJackHostApiRepresentation *hostApi )
if( queueModified )
{
/* Signal that we've done what was asked of us */
@ -841,7 +884,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
return result;
}
@@ -1517,7 +1690,7 @@
@@ -1521,7 +1694,7 @@ static int JackCallback( jack_nframes_t frames, void *userData )
if( stream->doStart )
{
/* If we can't obtain a lock, we'll try next time */
@ -850,7 +893,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
if( !err )
{
if( stream->doStart ) /* Could potentially change before obtaining the lock */
@@ -1525,12 +1698,12 @@
@@ -1529,12 +1702,12 @@ static int JackCallback( jack_nframes_t frames, void *userData )
stream->is_active = 1;
stream->doStart = 0;
PA_DEBUG(( "%s: Starting stream\n", __FUNCTION__ ));
@ -865,7 +908,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
}
else
assert( err == EBUSY );
@@ -1568,15 +1741,15 @@
@@ -1572,15 +1745,15 @@ static int JackCallback( jack_nframes_t frames, void *userData )
if( !stream->is_active ) /* Ok, signal to the main thread that we've carried out the operation */
{
/* If we can't obtain a lock, we'll try next time */
@ -885,7 +928,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
}
}
}
@@ -1622,11 +1795,11 @@
@@ -1626,11 +1799,11 @@ static PaError StartStream( PaStream *s )
/* Enable processing */
@ -899,7 +942,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
/*
do
{
@@ -1638,7 +1811,7 @@
@@ -1642,7 +1815,7 @@ static PaError StartStream( PaStream *s )
stream->doStart = 0;
stream->is_active = 0; /* Cancel any processing */
}
@ -908,7 +951,7 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
ENSURE_PA( result );
@@ -1657,15 +1830,15 @@
@@ -1661,15 +1834,15 @@ static PaError RealStop( PaJackStream *stream, int abort )
if( stream->isBlockingStream )
BlockingWaitEmpty ( stream );
@ -927,10 +970,11 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack.c
ENSURE_PA( result );
UNLESS( !stream->is_active, paInternalError );
Index: portaudio-v19/src/hostapi/jack/pa_jack_dynload.c
===================================================================
--- portaudio-v19/src/hostapi/jack/pa_jack_dynload.c (revision 0)
+++ portaudio-v19/src/hostapi/jack/pa_jack_dynload.c (working copy)
diff --git a/lib-src/portaudio-v19/src/hostapi/jack/pa_jack_dynload.c b/lib-src/portaudio-v19/src/hostapi/jack/pa_jack_dynload.c
new file mode 100644
index 000000000..172b00334
--- /dev/null
+++ b/lib-src/portaudio-v19/src/hostapi/jack/pa_jack_dynload.c
@@ -0,0 +1,162 @@
+/*
+ * $Id: pa_jack.c 1668 2011-05-02 17:07:11Z rossb $
@ -1094,10 +1138,11 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack_dynload.c
+ }
+#endif
+}
Index: portaudio-v19/src/hostapi/jack/pa_jack_dynload.h
===================================================================
--- portaudio-v19/src/hostapi/jack/pa_jack_dynload.h (revision 0)
+++ portaudio-v19/src/hostapi/jack/pa_jack_dynload.h (working copy)
diff --git a/lib-src/portaudio-v19/src/hostapi/jack/pa_jack_dynload.h b/lib-src/portaudio-v19/src/hostapi/jack/pa_jack_dynload.h
new file mode 100644
index 000000000..88bdfc715
--- /dev/null
+++ b/lib-src/portaudio-v19/src/hostapi/jack/pa_jack_dynload.h
@@ -0,0 +1,224 @@
+/*
+ * $Id: pa_jack.c 1668 2011-05-02 17:07:11Z rossb $
@ -1323,11 +1368,11 @@ Index: portaudio-v19/src/hostapi/jack/pa_jack_dynload.h
+}
+#endif /* __cplusplus */
+#endif /* INCLUDED_PA_JACK_DYNLINK_H */
Index: portaudio-v19/src/os/win/pa_win_hostapis.c
===================================================================
--- portaudio-v19/src/os/win/pa_win_hostapis.c (revision 12233)
+++ portaudio-v19/src/os/win/pa_win_hostapis.c (working copy)
@@ -63,6 +63,7 @@
diff --git a/lib-src/portaudio-v19/src/os/win/pa_win_hostapis.c b/lib-src/portaudio-v19/src/os/win/pa_win_hostapis.c
index 9c9927ab7..42af409fa 100644
--- a/lib-src/portaudio-v19/src/os/win/pa_win_hostapis.c
+++ b/lib-src/portaudio-v19/src/os/win/pa_win_hostapis.c
@@ -63,6 +63,7 @@ PaError PaWinDs_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInde
PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
PaError PaWinWdm_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
@ -1335,7 +1380,7 @@ Index: portaudio-v19/src/os/win/pa_win_hostapis.c
#ifdef __cplusplus
}
@@ -92,6 +93,10 @@
@@ -92,6 +93,10 @@ PaUtilHostApiInitializer *paHostApiInitializers[] =
PaWinWdm_Initialize,
#endif

View File

@ -0,0 +1,108 @@
/*
* $Id: pa_dynlink.c 1339 2008-02-15 07:50:33Z rossb $
* Portable Audio I/O Library
* dynamic library helper
*
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 2008 Ross Bencina
*
* 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 common_src
@brief dynamic library helper functions.
*/
#if defined(WIN32)
#include <windows.h>
#else
#include <dlfcn.h>
#endif
#include "pa_debugprint.h"
#include "pa_dynload.h"
#if !defined(NULL)
#define NULL 0
#endif
paDynamicLib PaDL_Load( char *name )
{
paDynamicLib lib;
#if defined(WIN32)
lib = LoadLibrary(name);
#else
lib = dlopen(name, RTLD_LAZY);
#endif
if (!lib) {
#if defined(WIN32)
PA_DEBUG(("Couldn't load %s, error code: %d\n", name, GetLastError()));
#else
PA_DEBUG(("Couldn't load %s, error: %s\n", name, dlerror()));
#endif
}
return lib;
}
void PaDL_Unload( paDynamicLib lib )
{
#if defined(WIN32)
FreeLibrary(lib);
#else
dlclose(lib);
#endif
}
void *PaDL_FindSymbol( paDynamicLib lib, char *name )
{
void *addr;
#if defined(WIN32)
addr = (void *) GetProcAddress(lib, name);
#else
addr = dlsym(lib, name);
#endif
if (addr == NULL) {
#if defined(WIN32)
PA_DEBUG(("Couldn't find %s function, error code: %d\n", name, GetLastError()));
#else
PA_DEBUG(("Couldn't find %s function, error: %s\n", name, dlerror()));
#endif
}
return addr;
}

View File

@ -0,0 +1,136 @@
#ifndef PA_DYNLINK_H
#define PA_DYNLINK_H
/*
* $Id: pa_dynlink.h 1339 2008-02-15 07:50:33Z rossb $
* Portable Audio I/O Library
* Dynamic library helper
*
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 1999-2008 Ross Bencina, 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 common_src
@brief Dynamic library helper functions.
*/
#include "pa_debugprint.h"
#if defined(WIN32)
#include <windows.h>
#endif
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
#if defined(WIN32)
typedef HANDLE paDynamicLib;
#define PADL_INLINE __inline
#else
typedef void * paDynamicLib;
#define PADL_INLINE inline
#endif
paDynamicLib PaDL_Load( char *name );
void PaDL_Unload( paDynamicLib lib );
void *PaDL_FindSymbol( paDynamicLib lib, char *name );
/* A little explanation of what's going on here.
*
* Only one source file should define PADL_DEFINE_POINTERS before including the header which
* defines the functions. This will cause the compiler to dump all of the function pointers
* to a single object file and prevent duplicate symbol definitions during link.
*
* The PADL_FUNC_WITH_RETURN and PADL_FUNC_NO_RETURN macros do two things each:
* 1) Define or reference the variable that contains the actual function pointer
* 2) Define an inline function to pass control to the real function
*
* Since the macros redefine the real functions of the same name, the compiler will make
* sure that the definitions are the same. If not, it will complain. For this to occur,
* the functions MUST be defined in an extern "C" block otherwise the compiler just thinks the
* functions are being overloaded.
*
* The compiler should optimize away the inline function since it just passes control to the real
* function and we should wind up with about the same function call we had before, only now it is
* safer due to the validation.
*
* The PADL_FUNC_WITH_RETURN takes 4 arguments:
* 1) The return type <---|
* 2) The function name | Taken from the real funciton prototype
* 3) The function arguments <---|
* 4) The argument list to pass to the real function
*
* The PADL_FUNC_NO_RETURN takes 3 arguments:
* 1) The function name <---| Taken from the FFmpeg funciton prototype
* 2) The function arguments <---|
* 3) The argument list to pass to the real function
*
* The PADL_FINDSYMBOL macro is responsible for retrieving the address of the real function
* and storing that address in the function pointer variable.
*/
#if defined(PADL_DEFINE_POINTERS)
#define FFX
#else
#define FFX extern
#endif
#define PADL_FUNC_WITH_RETURN(r, n, a, p) \
FFX r (*paDynFunc_ ## n ## _fp) a; \
PADL_INLINE r n a \
{ \
return paDynFunc_ ## n ## _fp p; \
} \
#define PADL_FUNC_NO_RETURN(n, a, p) \
FFX void (*paDynFunc_ ## n ## _fp) a; \
PADL_INLINE void n a \
{ \
paDynFunc_ ## n ## _fp p; \
} \
#define PADL_FINDSYMBOL(l, f, e) \
*(void**)& paDynFunc_ ## f ## _fp = PaDL_FindSymbol(l, #f); \
if (!paDynFunc_ ## f ## _fp) \
{ \
PA_DEBUG(("Could not locate address of %s\n", #f)); \
e; \
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_DYNLINK_H */

View File

@ -48,16 +48,22 @@
*/
#include <string.h>
#include <regex.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <sys/types.h>
#if !defined(_WIN32)
#include <unistd.h>
#endif
#include <errno.h> /* EBUSY */
#include <signal.h> /* sig_atomic_t */
#include <math.h>
#if defined(_WIN32)
#include <windows.h>
#else
#include <semaphore.h>
#include <pthread.h>
#endif
#include <jack/types.h>
#include <jack/jack.h>
@ -71,7 +77,13 @@
#include "pa_ringbuffer.h"
#include "pa_debugprint.h"
#include "pa_jack_dynload.h"
#if defined(WIN32)
static DWORD mainThread_;
#else
static pthread_t mainThread_;
#endif
static char *jackErr_ = NULL;
static const char* clientName_ = "PortAudio";
@ -84,7 +96,7 @@ static const char* clientName_ = "PortAudio";
PaError paErr; \
if( (paErr = (expr)) < paNoError ) \
{ \
if( (paErr) == paUnanticipatedHostError && pthread_self() == mainThread_ ) \
if( (paErr) == paUnanticipatedHostError && PaJack_IsOnMainThread() ) \
{ \
const char *err = jackErr_; \
if (! err ) err = "unknown error"; \
@ -100,7 +112,7 @@ static const char* clientName_ = "PortAudio";
do { \
if( (expr) == 0 ) \
{ \
if( (code) == paUnanticipatedHostError && pthread_self() == mainThread_ ) \
if( (code) == paUnanticipatedHostError && PaJack_IsOnMainThread() ) \
{ \
const char *err = jackErr_; \
if (!err) err = "unknown error"; \
@ -166,8 +178,13 @@ typedef struct
int jack_buffer_size;
PaHostApiIndex hostApiIndex;
#if defined(WIN32)
HANDLE mtx;
HANDLE cond;
#else
pthread_mutex_t mtx;
pthread_cond_t cond;
#endif
unsigned long inputBase, outputBase;
/* For dealing with the process thread */
@ -224,7 +241,11 @@ typedef struct PaJackStream
PaUtilRingBuffer inFIFO;
PaUtilRingBuffer outFIFO;
volatile sig_atomic_t data_available;
#if defined(WIN32)
HANDLE data_event;
#else
sem_t data_semaphore;
#endif
int bytesPerFrame;
int samplesPerFrame;
@ -252,6 +273,178 @@ static int JackCallback( jack_nframes_t frames, void *userData );
*
*/
static void PaJack_InitMainThread( void )
{
#if defined(WIN32)
mainThread_ = GetCurrentThreadId();
#else
mainThread_ = pthread_self();
#endif
}
static int PaJack_IsOnMainThread( void )
{
#if defined(WIN32)
return GetCurrentThreadId() == mainThread_;
#else
return pthread_self() == mainThread_;
#endif
}
static void PaJack_InitHostApiMutex( PaJackHostApiRepresentation *hostApi )
{
#if defined(WIN32)
ASSERT_CALL( (hostApi->mtx = CreateMutex( NULL, FALSE, NULL )) == NULL, 0 );
#else
ASSERT_CALL( pthread_mutex_init( &hostApi->mtx, NULL ), 0 );
#endif
}
static void PaJack_TerminateHostApiMutex( PaJackHostApiRepresentation *hostApi )
{
#if defined(WIN32)
CloseHandle( hostApi->mtx );
hostApi->mtx = NULL;
#else
ASSERT_CALL( pthread_mutex_destroy( &hostApi->mtx ), 0 );
#endif
}
static void PaJack_LockHostAPI( PaJackHostApiRepresentation *hostApi )
{
#if defined(WIN32)
ASSERT_CALL( WaitForSingleObject( hostApi->mtx, INFINITE ), 0 );
#else
ASSERT_CALL( pthread_mutex_lock( &hostApi->mtx ), 0 );
#endif
}
/* returns 0 on success, -1 on failure ??? or similar. document make sure it's correct etc */
static int PaJack_TryLockHostAPI( PaJackHostApiRepresentation *hostApi )
{
#if defined(WIN32)
return WaitForSingleObject( hostApi->mtx, 0 ) == WAIT_OBJECT_0 ? 0 : -1;
#else
return ( pthread_mutex_trylock( &hostApi->mtx ) == 0 ? 0 : -1 );
#endif
}
static void PaJack_UnlockHostAPI( PaJackHostApiRepresentation *hostApi )
{
#if defined(WIN32)
ReleaseMutex( hostApi->mtx );
#else
ASSERT_CALL( pthread_mutex_unlock( &hostApi->mtx ), 0 );
#endif
}
static void PaJack_InitCommandSync( PaJackHostApiRepresentation *hostApi )
{
#if defined(WIN32)
hostApi->cond = CreateEvent( NULL, FALSE, FALSE, NULL );
assert( hostApi->cond );
#else
ASSERT_CALL( pthread_cond_init( &hostApi->cond, NULL ), 0 );
#endif
}
static void PaJack_TerminateCommandSync( PaJackHostApiRepresentation *hostApi )
{
#if defined(WIN32)
CloseHandle( hostApi->cond );
hostApi->cond = NULL;
#else
ASSERT_CALL( pthread_cond_init( &hostApi->cond, NULL ), 0 );
#endif
}
static void PaJack_SignalCommandCompleted( PaJackHostApiRepresentation *hostApi )
{
#if defined(WIN32)
ASSERT_CALL( !SetEvent( hostApi->cond ), 0 );
#else
ASSERT_CALL( pthread_cond_signal( &hostApi->cond ), 0 );
#endif
}
static PaError WaitForCommandToComplete( PaJackHostApiRepresentation *hostApi )
{
PaError result = paNoError;
#if defined(WIN32)
switch( SignalObjectAndWait( hostApi->mtx, hostApi->cond, 10 * 60 * 1000, FALSE ) )
{
case WAIT_OBJECT_0:
result = paNoError;
break;
case WAIT_TIMEOUT:
result = paTimedOut;
break;
default:
result = paInternalError;
break;
}
PaJack_LockHostAPI( hostApi );
#else
int err = 0;
PaTime pt = PaUtil_GetTime();
struct timespec ts;
ts.tv_sec = (time_t) floor( pt + 10 * 60 /* 10 minutes */ );
ts.tv_nsec = (long) ((pt - floor( pt )) * 1000000000);
/* XXX: Best enclose in loop, in case of spurious wakeups? */
err = pthread_cond_timedwait( &hostApi->cond, &hostApi->mtx, &ts );
/* Make sure we didn't time out */
UNLESS( err != ETIMEDOUT, paTimedOut );
UNLESS( !err, paInternalError );
error:
#endif
return result;
}
static void PaJack_InitStreamDataSync( PaJackStream *stream )
{
#if defined(WIN32)
stream->data_event = CreateEvent( NULL, FALSE, FALSE, NULL );
assert( stream->data_event );
#else
ASSERT_CALL( sem_init( &stream->data_semaphore, 0, 0 ) == -1, 0);
#endif
}
static void PaJack_TerminateStreamDataSync( PaJackStream *stream )
{
#if defined(WIN32)
CloseHandle( stream->data_event );
#else
sem_destroy( &stream->data_semaphore );
#endif
}
static void PaJack_SignalStreamDataAvailable( PaJackStream *stream )
{
#if defined(WIN32)
SetEvent( stream->data_event );
#else
sem_post( &stream->data_semaphore );
#endif
}
static void PaJack_WaitForStreamDataToBecomeAvailable( PaJackStream *stream )
{
#if defined(WIN32)
WaitForSingleObject( stream->data_event, INFINITE );
#else
sem_wait( &stream->data_semaphore );
#endif
}
#if defined(WIN32)
#define snprintf _snprintf
#endif
/* ---- blocking emulation layer ---- */
/* Allocate buffer. */
@ -298,7 +491,7 @@ BlockingCallback( const void *inputBuffer,
if( !stream->data_available )
{
stream->data_available = 1;
sem_post( &stream->data_semaphore );
PaJack_SignalStreamDataAvailable( stream );
}
return paContinue;
}
@ -337,7 +530,7 @@ BlockingBegin( PaJackStream *stream, int minimum_buffer_size )
}
stream->data_available = 0;
sem_init( &stream->data_semaphore, 0, 0 );
PaJack_InitStreamDataSync( stream );
error:
return result;
@ -349,7 +542,7 @@ BlockingEnd( PaJackStream *stream )
BlockingTermFIFO( &stream->inFIFO );
BlockingTermFIFO( &stream->outFIFO );
sem_destroy( &stream->data_semaphore );
PaJack_TerminateStreamDataSync( stream );
}
static PaError BlockingReadStream( PaStream* s, void *data, unsigned long numFrames )
@ -371,7 +564,7 @@ static PaError BlockingReadStream( PaStream* s, void *data, unsigned long numFra
if( stream->data_available )
stream->data_available = 0;
else
sem_wait( &stream->data_semaphore );
PaJack_WaitForStreamDataToBecomeAvailable( stream );
}
}
@ -409,7 +602,7 @@ static PaError BlockingWriteStream( PaStream* s, const void *data, unsigned long
if( stream->data_available )
stream->data_available = 0;
else
sem_wait( &stream->data_semaphore );
PaJack_WaitForStreamDataToBecomeAvailable( stream );
}
}
@ -442,7 +635,7 @@ BlockingWaitEmpty( PaStream *s )
while( PaUtil_GetRingBufferReadAvailable( &stream->outFIFO ) > 0 )
{
stream->data_available = 0;
sem_wait( &stream->data_semaphore );
PaJack_WaitForStreamDataToBecomeAvailable( stream );
}
return 0;
}
@ -473,7 +666,6 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
char *regex_pattern = NULL;
int port_index, client_index, i;
double globalSampleRate;
regex_t port_regex;
unsigned long numClients = 0, numPorts = 0;
char *tmp_client_name = NULL;
@ -481,9 +673,6 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
commonApi->info.defaultOutputDevice = paNoDevice;
commonApi->info.deviceCount = 0;
/* Parse the list of ports, using a regex to grab the client names */
ASSERT_CALL( regcomp( &port_regex, "^[^:]*", REG_EXTENDED ), 0 );
/* since we are rebuilding the list of devices, free all memory
* associated with the previous list */
PaUtil_FreeAllAllocations( jackApi->deviceInfoMemory );
@ -496,7 +685,7 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
* according to the client_name:port_name convention (which is
* enforced by jackd)
* A: If jack_get_ports returns NULL, there's nothing for us to do */
UNLESS( (jack_ports = jack_get_ports( jackApi->jack_client, "", JACK_PORT_TYPE_FILTER, 0 )) && jack_ports[0], paNoError );
UNLESS( (jack_ports = jack_get_ports( jackApi->jack_client, "^[^:]*", JACK_PORT_TYPE_FILTER, 0 )) && jack_ports[0], paNoError );
/* Find number of ports */
while( jack_ports[numPorts] )
++numPorts;
@ -508,16 +697,15 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
for( numClients = 0, port_index = 0; jack_ports[port_index] != NULL; port_index++ )
{
int client_seen = FALSE;
regmatch_t match_info;
const char *port = jack_ports[port_index];
const char *colon;
/* extract the client name from the port name, using a regex
* that parses the clientname:portname syntax */
UNLESS( !regexec( &port_regex, port, 1, &match_info, 0 ), paInternalError );
assert(match_info.rm_eo - match_info.rm_so < jack_client_name_size());
memcpy( tmp_client_name, port + match_info.rm_so,
match_info.rm_eo - match_info.rm_so );
tmp_client_name[match_info.rm_eo - match_info.rm_so] = '\0';
UNLESS( colon = strchr(port, ':'), paInternalError );
assert(colon - port < jack_client_name_size());
memcpy( tmp_client_name, port, colon - port );
tmp_client_name[colon - port] = '\0';
/* do we know about this port's client yet? */
for( i = 0; i < numClients; i++ )
@ -603,7 +791,7 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
* We don't care what they are, we just care how many */
curDevInfo->maxInputChannels++;
}
free(clientPorts);
jack_free(clientPorts);
}
/* ... what are your input ports (that we could output to)? */
@ -624,7 +812,7 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
* We don't care what they are, we just care how many */
curDevInfo->maxOutputChannels++;
}
free(clientPorts);
jack_free(clientPorts);
}
/* Add this client to the list of devices */
@ -637,8 +825,7 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
}
error:
regfree( &port_regex );
free( jack_ports );
jack_free( jack_ports );
return result;
}
@ -651,7 +838,7 @@ static void UpdateSampleRate( PaJackStream *stream, double sampleRate )
static void JackErrorCallback( const char *msg )
{
if( pthread_self() == mainThread_ )
if( PaJack_IsOnMainThread() )
{
assert( msg );
jackErr_ = realloc( jackErr_, strlen( msg ) + 1 );
@ -671,11 +858,10 @@ static void JackOnShutdown( void *arg )
}
/* Make sure that the main thread doesn't get stuck waiting on the condition */
ASSERT_CALL( pthread_mutex_lock( &jackApi->mtx ), 0 );
PaJack_LockHostAPI( jackApi );
jackApi->jackIsDown = 1;
ASSERT_CALL( pthread_cond_signal( &jackApi->cond ), 0 );
ASSERT_CALL( pthread_mutex_unlock( &jackApi->mtx ), 0 );
PaJack_SignalCommandCompleted( jackApi );
PaJack_UnlockHostAPI( jackApi );
}
static int JackSrCb( jack_nframes_t nframes, void *arg )
@ -710,18 +896,20 @@ PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi,
PaHostApiIndex hostApiIndex )
{
PaError result = paNoError;
PaJackHostApiRepresentation *jackHostApi;
PaJackHostApiRepresentation *jackHostApi = NULL;
int activated = 0;
jack_status_t jackStatus = 0;
*hostApi = NULL; /* Initialize to NULL */
UNLESS( PaJack_Load(), paNoError );
UNLESS( jackHostApi = (PaJackHostApiRepresentation*)
PaUtil_AllocateMemory( sizeof(PaJackHostApiRepresentation) ), paInsufficientMemory );
UNLESS( jackHostApi->deviceInfoMemory = PaUtil_CreateAllocationGroup(), paInsufficientMemory );
mainThread_ = pthread_self();
ASSERT_CALL( pthread_mutex_init( &jackHostApi->mtx, NULL ), 0 );
ASSERT_CALL( pthread_cond_init( &jackHostApi->cond, NULL ), 0 );
PaJack_InitMainThread();
PaJack_InitHostApiMutex( jackHostApi );
PaJack_InitCommandSync( jackHostApi );
/* Try to become a client of the JACK server. If we cannot do
* this, then this API cannot be used.
@ -807,6 +995,9 @@ error:
PaUtil_FreeMemory( jackHostApi );
}
PaJack_Unload();
return result;
}
@ -819,8 +1010,8 @@ static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
* client is not allowed to have any ports connected */
ASSERT_CALL( jack_deactivate( jackHostApi->jack_client ), 0 );
ASSERT_CALL( pthread_mutex_destroy( &jackHostApi->mtx ), 0 );
ASSERT_CALL( pthread_cond_destroy( &jackHostApi->cond ), 0 );
PaJack_TerminateHostApiMutex( jackHostApi );
PaJack_TerminateCommandSync( jackHostApi );
ASSERT_CALL( jack_client_close( jackHostApi->jack_client ), 0 );
@ -834,6 +1025,8 @@ static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
free( jackErr_ );
jackErr_ = NULL;
PaJack_Unload();
}
static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
@ -1001,39 +1194,19 @@ static void CleanUpStream( PaJackStream *stream, int terminateStreamRepresentati
PaUtil_FreeMemory( stream );
}
static PaError WaitCondition( PaJackHostApiRepresentation *hostApi )
{
PaError result = paNoError;
int err = 0;
PaTime pt = PaUtil_GetTime();
struct timespec ts;
ts.tv_sec = (time_t) floor( pt + 10 * 60 /* 10 minutes */ );
ts.tv_nsec = (long) ((pt - floor( pt )) * 1000000000);
/* XXX: Best enclose in loop, in case of spurious wakeups? */
err = pthread_cond_timedwait( &hostApi->cond, &hostApi->mtx, &ts );
/* Make sure we didn't time out */
UNLESS( err != ETIMEDOUT, paTimedOut );
UNLESS( !err, paInternalError );
error:
return result;
}
static PaError AddStream( PaJackStream *stream )
{
PaError result = paNoError;
PaJackHostApiRepresentation *hostApi = stream->hostApi;
/* Add to queue of streams that should be processed */
ASSERT_CALL( pthread_mutex_lock( &hostApi->mtx ), 0 );
PaJack_LockHostAPI( hostApi );
if( !hostApi->jackIsDown )
{
hostApi->toAdd = stream;
/* Unlock mutex and await signal from processing thread */
result = WaitCondition( stream->hostApi );
result = WaitForCommandToComplete( stream->hostApi );
}
ASSERT_CALL( pthread_mutex_unlock( &hostApi->mtx ), 0 );
PaJack_UnlockHostAPI( hostApi );
ENSURE_PA( result );
UNLESS( !hostApi->jackIsDown, paDeviceUnavailable );
@ -1049,14 +1222,14 @@ static PaError RemoveStream( PaJackStream *stream )
PaJackHostApiRepresentation *hostApi = stream->hostApi;
/* Add to queue over streams that should be processed */
ASSERT_CALL( pthread_mutex_lock( &hostApi->mtx ), 0 );
PaJack_LockHostAPI( hostApi );
if( !hostApi->jackIsDown )
{
hostApi->toRemove = stream;
/* Unlock mutex and await signal from processing thread */
result = WaitCondition( stream->hostApi );
result = WaitForCommandToComplete( stream->hostApi );
}
ASSERT_CALL( pthread_mutex_unlock( &hostApi->mtx ), 0 );
PaJack_UnlockHostAPI( hostApi );
ENSURE_PA( result );
error:
@ -1169,7 +1342,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
stream->isBlockingStream = !streamCallback;
if( stream->isBlockingStream )
{
float latency = 0.001; /* 1ms is the absolute minimum we support */
PaTime latency = 0.001f; /* 1ms is the absolute minimum we support */
int minimum_buffer_frames = 0;
if( inputParameters && inputParameters->suggestedLatency > latency )
@ -1249,7 +1422,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
break;
}
}
free( jack_ports );
jack_free( jack_ports );
UNLESS( !err, paInsufficientMemory );
/* Fewer ports than expected? */
@ -1273,7 +1446,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
break;
}
}
free( jack_ports );
jack_free( jack_ports );
UNLESS( !err , paInsufficientMemory );
/* Fewer ports than expected? */
@ -1427,9 +1600,9 @@ static PaError UpdateQueue( PaJackHostApiRepresentation *hostApi )
const double jackSr = jack_get_sample_rate( hostApi->jack_client );
int err;
if( (err = pthread_mutex_trylock( &hostApi->mtx )) != 0 )
if( (err = PaJack_TryLockHostAPI( hostApi )) != 0 )
{
assert( err == EBUSY );
assert( err );
return paNoError;
}
@ -1488,11 +1661,11 @@ static PaError UpdateQueue( PaJackHostApiRepresentation *hostApi )
if( queueModified )
{
/* Signal that we've done what was asked of us */
ASSERT_CALL( pthread_cond_signal( &hostApi->cond ), 0 );
PaJack_SignalCommandCompleted( hostApi );
}
error:
ASSERT_CALL( pthread_mutex_unlock( &hostApi->mtx ), 0 );
PaJack_UnlockHostAPI( hostApi );
return result;
}
@ -1521,7 +1694,7 @@ static int JackCallback( jack_nframes_t frames, void *userData )
if( stream->doStart )
{
/* If we can't obtain a lock, we'll try next time */
int err = pthread_mutex_trylock( &stream->hostApi->mtx );
int err = PaJack_TryLockHostAPI( stream->hostApi );
if( !err )
{
if( stream->doStart ) /* Could potentially change before obtaining the lock */
@ -1529,12 +1702,12 @@ static int JackCallback( jack_nframes_t frames, void *userData )
stream->is_active = 1;
stream->doStart = 0;
PA_DEBUG(( "%s: Starting stream\n", __FUNCTION__ ));
ASSERT_CALL( pthread_cond_signal( &stream->hostApi->cond ), 0 );
PaJack_SignalCommandCompleted( hostApi );
stream->callbackResult = paContinue;
stream->isSilenced = 0;
}
ASSERT_CALL( pthread_mutex_unlock( &stream->hostApi->mtx ), 0 );
PaJack_UnlockHostAPI( stream->hostApi );
}
else
assert( err == EBUSY );
@ -1572,15 +1745,15 @@ static int JackCallback( jack_nframes_t frames, void *userData )
if( !stream->is_active ) /* Ok, signal to the main thread that we've carried out the operation */
{
/* If we can't obtain a lock, we'll try next time */
int err = pthread_mutex_trylock( &stream->hostApi->mtx );
int err = PaJack_TryLockHostAPI( stream->hostApi );
if( !err )
{
stream->doStop = stream->doAbort = 0;
ASSERT_CALL( pthread_cond_signal( &stream->hostApi->cond ), 0 );
ASSERT_CALL( pthread_mutex_unlock( &stream->hostApi->mtx ), 0 );
PaJack_SignalCommandCompleted( stream->hostApi );
PaJack_UnlockHostAPI( stream->hostApi );
}
else
assert( err == EBUSY );
assert( err );
}
}
}
@ -1626,11 +1799,11 @@ static PaError StartStream( PaStream *s )
/* Enable processing */
ASSERT_CALL( pthread_mutex_lock( &stream->hostApi->mtx ), 0 );
PaJack_LockHostAPI( stream->hostApi );
stream->doStart = 1;
/* Wait for stream to be started */
result = WaitCondition( stream->hostApi );
result = WaitForCommandToComplete( stream->hostApi );
/*
do
{
@ -1642,7 +1815,7 @@ static PaError StartStream( PaStream *s )
stream->doStart = 0;
stream->is_active = 0; /* Cancel any processing */
}
ASSERT_CALL( pthread_mutex_unlock( &stream->hostApi->mtx ), 0 );
PaJack_UnlockHostAPI( stream->hostApi );
ENSURE_PA( result );
@ -1661,15 +1834,15 @@ static PaError RealStop( PaJackStream *stream, int abort )
if( stream->isBlockingStream )
BlockingWaitEmpty ( stream );
ASSERT_CALL( pthread_mutex_lock( &stream->hostApi->mtx ), 0 );
PaJack_LockHostAPI( stream->hostApi );
if( abort )
stream->doAbort = 1;
else
stream->doStop = 1;
/* Wait for stream to be stopped */
result = WaitCondition( stream->hostApi );
ASSERT_CALL( pthread_mutex_unlock( &stream->hostApi->mtx ), 0 );
result = WaitForCommandToComplete( stream->hostApi );
PaJack_UnlockHostAPI( stream->hostApi );
ENSURE_PA( result );
UNLESS( !stream->is_active, paInternalError );

View File

@ -0,0 +1,162 @@
/*
* $Id: pa_jack.c 1668 2011-05-02 17:07:11Z rossb $
* PortAudio Portable Real-Time Audio Library
* Latest Version at: http://www.portaudio.com
* JACK Implementation by Joshua Haberman
*
* Copyright (c) 2004 Stefan Westerfeld <stefan@space.twc.de>
* Copyright (c) 2004 Arve Knudsen <aknuds-1@broadpark.no>
* Copyright (c) 2002 Joshua Haberman <joshua@haberman.com>
*
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 1999-2002 Ross Bencina, 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 hostapi_src
*/
#define PADL_DEFINE_POINTERS
#include "pa_dynload.h"
#include "pa_jack_dynload.h"
#if defined(PA_DYNAMIC_JACK)
static paDynamicLib jacklib = NULL;
#endif
int PaJack_Load(void)
{
#if !defined(PA_DYNAMIC_JACK)
return 1;
#else
#if defined(__APPLE__)
jacklib = PaDL_Load("libjack.dylib");
#elif defined(_WIN64)
jacklib = PaDL_Load("libjack64.dll");
#elif defined(WIN32)
jacklib = PaDL_Load("libjack.dll");
#else
jacklib = PaDL_Load("libjack.so");
#endif
if (!jacklib) {
return 0;
}
PADL_FINDSYMBOL(jacklib, jack_client_name_size, goto error);
PADL_FINDSYMBOL(jacklib, jack_client_name_size, goto error);
PADL_FINDSYMBOL(jacklib, jack_get_ports, goto error);
PADL_FINDSYMBOL(jacklib, jack_get_sample_rate, goto error);
PADL_FINDSYMBOL(jacklib, jack_get_ports, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_by_name, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_get_latency, goto error);
PADL_FINDSYMBOL(jacklib, jack_free, goto error);
PADL_FINDSYMBOL(jacklib, jack_get_ports, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_by_name, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_get_latency, goto error);
PADL_FINDSYMBOL(jacklib, jack_free, goto error);
PADL_FINDSYMBOL(jacklib, jack_client_open, goto error);
PADL_FINDSYMBOL(jacklib, jack_on_shutdown, goto error);
PADL_FINDSYMBOL(jacklib, jack_set_error_function, goto error);
PADL_FINDSYMBOL(jacklib, jack_get_buffer_size, goto error);
PADL_FINDSYMBOL(jacklib, jack_set_sample_rate_callback, goto error);
PADL_FINDSYMBOL(jacklib, jack_set_xrun_callback, goto error);
PADL_FINDSYMBOL(jacklib, jack_set_process_callback, goto error);
PADL_FINDSYMBOL(jacklib, jack_activate, goto error);
PADL_FINDSYMBOL(jacklib, jack_deactivate, goto error);
PADL_FINDSYMBOL(jacklib, jack_client_close, goto error);
PADL_FINDSYMBOL(jacklib, jack_deactivate, goto error);
PADL_FINDSYMBOL(jacklib, jack_client_close, goto error);
PADL_FINDSYMBOL(jacklib, jack_get_sample_rate, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_unregister, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_unregister, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_name_size, goto error);
PADL_FINDSYMBOL(jacklib, jack_client_name_size, goto error);
PADL_FINDSYMBOL(jacklib, jack_get_sample_rate, goto error);
PADL_FINDSYMBOL(jacklib, jack_get_sample_rate, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_name_size, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_register, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_name_size, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_register, goto error);
PADL_FINDSYMBOL(jacklib, jack_get_ports, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_by_name, goto error);
PADL_FINDSYMBOL(jacklib, jack_free, goto error);
PADL_FINDSYMBOL(jacklib, jack_get_ports, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_by_name, goto error);
PADL_FINDSYMBOL(jacklib, jack_free, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_get_latency, goto error);
PADL_FINDSYMBOL(jacklib, jack_get_buffer_size, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_get_latency, goto error);
PADL_FINDSYMBOL(jacklib, jack_get_buffer_size, goto error);
PADL_FINDSYMBOL(jacklib, jack_frame_time, goto error);
PADL_FINDSYMBOL(jacklib, jack_get_sample_rate, goto error);
PADL_FINDSYMBOL(jacklib, jack_frame_time, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_get_latency, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_get_latency, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_get_buffer, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_get_buffer, goto error);
PADL_FINDSYMBOL(jacklib, jack_get_sample_rate, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_get_buffer, goto error);
PADL_FINDSYMBOL(jacklib, jack_connect, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_name, goto error);
PADL_FINDSYMBOL(jacklib, jack_connect, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_name, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_connected, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_disconnect, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_connected, goto error);
PADL_FINDSYMBOL(jacklib, jack_port_disconnect, goto error);
PADL_FINDSYMBOL(jacklib, jack_frame_time, goto error);
PADL_FINDSYMBOL(jacklib, jack_client_name_size, goto error);
PADL_FINDSYMBOL(jacklib, jack_get_client_name, goto error);
return 1;
error:
PaJack_Unload();
return 0;
#endif
}
void PaJack_Unload(void)
{
#if defined(PA_DYNAMIC_JACK)
if (jacklib) {
PaDL_Unload(jacklib);
jacklib = NULL;
}
#endif
}

View File

@ -0,0 +1,224 @@
/*
* $Id: pa_jack.c 1668 2011-05-02 17:07:11Z rossb $
* PortAudio Portable Real-Time Audio Library
* Latest Version at: http://www.portaudio.com
* JACK Implementation by Joshua Haberman
*
* Copyright (c) 2004 Stefan Westerfeld <stefan@space.twc.de>
* Copyright (c) 2004 Arve Knudsen <aknuds-1@broadpark.no>
* Copyright (c) 2002 Joshua Haberman <joshua@haberman.com>
*
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 1999-2002 Ross Bencina, 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 hostapi_src
*/
#ifndef INCLUDED_PA_JACK_DYNLINK_H
#define INCLUDED_PA_JACK_DYNLINK_H
#include <jack/jack.h>
#include "pa_dynload.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
#if defined(PA_DYNAMIC_JACK)
PADL_FUNC_WITH_RETURN(
int,
jack_activate,
(jack_client_t *client),
(client)
);
PADL_FUNC_WITH_RETURN(
int,
jack_client_close,
(jack_client_t *client),
(client)
);
PADL_FUNC_WITH_RETURN(
int,
jack_client_name_size,
(void),
()
);
PADL_FUNC_WITH_RETURN(
jack_client_t *,
jack_client_open,
(const char *client_name, jack_options_t options, jack_status_t *status, ...),
(client_name, options, status)
);
PADL_FUNC_WITH_RETURN(
int,
jack_connect,
(jack_client_t *client, const char *source_port, const char *destination_port),
(client, source_port, destination_port)
);
PADL_FUNC_WITH_RETURN(
int,
jack_deactivate,
(jack_client_t *client),
(client)
);
PADL_FUNC_WITH_RETURN(
jack_nframes_t,
jack_frame_time,
(const jack_client_t *client),
(client)
);
PADL_FUNC_NO_RETURN(
jack_free,
(void *ptr),
(ptr)
);
PADL_FUNC_WITH_RETURN(
jack_nframes_t,
jack_get_buffer_size,
(jack_client_t *client),
(client)
);
PADL_FUNC_WITH_RETURN(
char *,
jack_get_client_name,
(jack_client_t *client),
(client)
);
PADL_FUNC_WITH_RETURN(
const char **,
jack_get_ports,
(jack_client_t *client, const char *port_name_pattern, const char *type_name_pattern, unsigned long flags),
(client, port_name_pattern, type_name_pattern, flags)
);
PADL_FUNC_WITH_RETURN(
jack_nframes_t,
jack_get_sample_rate,
(jack_client_t *client),
(client)
);
PADL_FUNC_NO_RETURN(
jack_on_shutdown,
(jack_client_t *client, JackShutdownCallback shutdown_callback, void *arg),
(client, shutdown_callback, arg)
);
PADL_FUNC_WITH_RETURN(
jack_port_t *,
jack_port_by_name,
(jack_client_t *client, const char *port_name),
(client, port_name)
);
PADL_FUNC_WITH_RETURN(
int,
jack_port_connected,
(const jack_port_t *port),
(port)
);
PADL_FUNC_WITH_RETURN(
int,
jack_port_disconnect,
(jack_client_t *client, jack_port_t *port),
(client, port)
);
PADL_FUNC_WITH_RETURN(
void *,
jack_port_get_buffer,
(jack_port_t *port, jack_nframes_t frames),
(port, frames)
);
PADL_FUNC_WITH_RETURN(
jack_nframes_t,
jack_port_get_latency,
(jack_port_t *port),
(port)
);
PADL_FUNC_WITH_RETURN(
const char *,
jack_port_name,
(const jack_port_t *port),
(port)
);
PADL_FUNC_WITH_RETURN(
int,
jack_port_name_size,
(void),
()
);
PADL_FUNC_WITH_RETURN(
jack_port_t *,
jack_port_register,
(jack_client_t *client, const char *port_name, const char *port_type, unsigned long flags, unsigned long buffer_size),
(client, port_name, port_type, flags, buffer_size)
);
PADL_FUNC_WITH_RETURN(
int,
jack_port_unregister,
(jack_client_t *client, jack_port_t *port),
(client, port)
);
PADL_FUNC_NO_RETURN(
jack_set_error_function,
(void (*func)(const char *)),
(func)
);
PADL_FUNC_WITH_RETURN(
int,
jack_set_process_callback,
(jack_client_t *client, JackProcessCallback process_callback, void *arg),
(client, process_callback, arg)
);
PADL_FUNC_WITH_RETURN(
int,
jack_set_sample_rate_callback,
(jack_client_t *client, JackSampleRateCallback srate_callback, void *arg),
(client, srate_callback, arg)
);
PADL_FUNC_WITH_RETURN(
int,
jack_set_xrun_callback,
(jack_client_t *client, JackXRunCallback xrun_callback, void *arg),
(client, xrun_callback, arg)
);
#endif /* PA_DYNAMIC_JACK */
int PaJack_Load(void);
void PaJack_Unload(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* INCLUDED_PA_JACK_DYNLINK_H */

View File

@ -63,6 +63,7 @@ PaError PaWinDs_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInde
PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
PaError PaWinWdm_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
#ifdef __cplusplus
}
@ -92,6 +93,10 @@ PaUtilHostApiInitializer *paHostApiInitializers[] =
PaWinWdm_Initialize,
#endif
#if PA_USE_JACK
PaJack_Initialize,
#endif
#if PA_USE_SKELETON
PaSkeleton_Initialize, /* just for testing. last in list so it isn't marked as default. */
#endif