diff --git a/lib-src/portaudio-v19/jack.patch b/lib-src/portaudio-v19/jack.patch new file mode 100644 index 000000000..54b6c2ba4 --- /dev/null +++ b/lib-src/portaudio-v19/jack.patch @@ -0,0 +1,1348 @@ +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) +@@ -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 ++#else ++#include ++#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; ++} +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) +@@ -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 ++#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 */ +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) +@@ -48,16 +48,22 @@ + */ + + #include +-#include + #include + #include + #include + #include ++#if !defined(_WIN32) + #include ++#endif + #include /* EBUSY */ + #include /* sig_atomic_t */ + #include ++#if defined(_WIN32) ++#include ++#else + #include ++#include ++#endif + + #include + #include +@@ -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 @@ + 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 @@ + 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 @@ + 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 @@ + 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; + +@@ -248,6 +269,178 @@ + * + */ + ++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. */ +@@ -294,7 +487,7 @@ + if( !stream->data_available ) + { + stream->data_available = 1; +- sem_post( &stream->data_semaphore ); ++ PaJack_SignalStreamDataAvailable( stream ); + } + return paContinue; + } +@@ -333,7 +526,7 @@ + } + + stream->data_available = 0; +- sem_init( &stream->data_semaphore, 0, 0 ); ++ PaJack_InitStreamDataSync( stream ); + + error: + return result; +@@ -345,7 +538,7 @@ + BlockingTermFIFO( &stream->inFIFO ); + BlockingTermFIFO( &stream->outFIFO ); + +- sem_destroy( &stream->data_semaphore ); ++ PaJack_TerminateStreamDataSync( stream ); + } + + static PaError BlockingReadStream( PaStream* s, void *data, unsigned long numFrames ) +@@ -367,7 +560,7 @@ + if( stream->data_available ) + stream->data_available = 0; + else +- sem_wait( &stream->data_semaphore ); ++ PaJack_WaitForStreamDataToBecomeAvailable( stream ); + } + } + +@@ -405,7 +598,7 @@ + if( stream->data_available ) + stream->data_available = 0; + else +- sem_wait( &stream->data_semaphore ); ++ PaJack_WaitForStreamDataToBecomeAvailable( stream ); + } + } + +@@ -438,7 +631,7 @@ + while( PaUtil_GetRingBufferReadAvailable( &stream->outFIFO ) > 0 ) + { + stream->data_available = 0; +- sem_wait( &stream->data_semaphore ); ++ PaJack_WaitForStreamDataToBecomeAvailable( stream ); + } + return 0; + } +@@ -469,7 +662,6 @@ + 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; + +@@ -477,9 +669,6 @@ + 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 ); +@@ -492,7 +681,7 @@ + * 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 ); + /* Find number of ports */ + while( jack_ports[numPorts] ) + ++numPorts; +@@ -504,16 +693,15 @@ + 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++ ) +@@ -599,7 +787,7 @@ + * 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)? */ +@@ -620,7 +808,7 @@ + * 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 */ +@@ -633,8 +821,7 @@ + } + + error: +- regfree( &port_regex ); +- free( jack_ports ); ++ jack_free( jack_ports ); + return result; + } + +@@ -647,7 +834,7 @@ + + static void JackErrorCallback( const char *msg ) + { +- if( pthread_self() == mainThread_ ) ++ if( PaJack_IsOnMainThread() ) + { + assert( msg ); + jackErr_ = realloc( jackErr_, strlen( msg ) + 1 ); +@@ -667,11 +854,10 @@ + } + + /* 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 ) +@@ -706,18 +892,20 @@ + 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. +@@ -803,6 +991,9 @@ + + PaUtil_FreeMemory( jackHostApi ); + } ++ ++ PaJack_Unload(); ++ + return result; + } + +@@ -815,8 +1006,8 @@ + * 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 ); + +@@ -830,6 +1021,8 @@ + + free( jackErr_ ); + jackErr_ = NULL; ++ ++ PaJack_Unload(); + } + + static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi, +@@ -997,39 +1190,19 @@ + 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 ); +@@ -1045,14 +1218,14 @@ + 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: +@@ -1165,7 +1338,7 @@ + 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 ) +@@ -1245,7 +1418,7 @@ + break; + } + } +- free( jack_ports ); ++ jack_free( jack_ports ); + UNLESS( !err, paInsufficientMemory ); + + /* Fewer ports than expected? */ +@@ -1269,7 +1442,7 @@ + break; + } + } +- free( jack_ports ); ++ jack_free( jack_ports ); + UNLESS( !err , paInsufficientMemory ); + + /* Fewer ports than expected? */ +@@ -1423,9 +1596,9 @@ + 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; + } + +@@ -1484,11 +1657,11 @@ + 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; + } +@@ -1517,7 +1690,7 @@ + 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 */ +@@ -1525,12 +1698,12 @@ + 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 ); +@@ -1568,15 +1741,15 @@ + 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 ); + } + } + } +@@ -1622,11 +1795,11 @@ + + /* 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 + { +@@ -1638,7 +1811,7 @@ + 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 ); + +@@ -1657,15 +1830,15 @@ + 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 ); +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) +@@ -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 ++ * Copyright (c) 2004 Arve Knudsen ++ * Copyright (c) 2002 Joshua Haberman ++ * ++ * 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 ++} +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) +@@ -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 ++ * Copyright (c) 2004 Arve Knudsen ++ * Copyright (c) 2002 Joshua Haberman ++ * ++ * 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 ++ ++#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 */ +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 @@ + 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 @@ + 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 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 $ + * 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 +#else +#include +#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; +} 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 +/* + * $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 +#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 */ 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 25b7fd2d7..eff0650e3 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 @@ */ #include -#include #include #include #include #include +#if !defined(_WIN32) #include +#endif #include /* EBUSY */ #include /* sig_atomic_t */ #include +#if defined(_WIN32) +#include +#else #include +#include +#endif #include #include @@ -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; @@ -248,6 +269,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. */ @@ -294,7 +487,7 @@ BlockingCallback( const void *inputBuffer, if( !stream->data_available ) { stream->data_available = 1; - sem_post( &stream->data_semaphore ); + PaJack_SignalStreamDataAvailable( stream ); } return paContinue; } @@ -333,7 +526,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; @@ -345,7 +538,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 ) @@ -367,7 +560,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 ); } } @@ -405,7 +598,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 ); } } @@ -438,7 +631,7 @@ BlockingWaitEmpty( PaStream *s ) while( PaUtil_GetRingBufferReadAvailable( &stream->outFIFO ) > 0 ) { stream->data_available = 0; - sem_wait( &stream->data_semaphore ); + PaJack_WaitForStreamDataToBecomeAvailable( stream ); } return 0; } @@ -469,7 +662,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; @@ -477,9 +669,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 ); @@ -492,7 +681,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 ); /* Find number of ports */ while( jack_ports[numPorts] ) ++numPorts; @@ -504,16 +693,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++ ) @@ -599,7 +787,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)? */ @@ -620,7 +808,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 */ @@ -633,8 +821,7 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi ) } error: - regfree( &port_regex ); - free( jack_ports ); + jack_free( jack_ports ); return result; } @@ -647,7 +834,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 ); @@ -667,11 +854,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 ) @@ -706,18 +892,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. @@ -803,6 +991,9 @@ error: PaUtil_FreeMemory( jackHostApi ); } + + PaJack_Unload(); + return result; } @@ -815,8 +1006,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 ); @@ -830,6 +1021,8 @@ static void Terminate( struct PaUtilHostApiRepresentation *hostApi ) free( jackErr_ ); jackErr_ = NULL; + + PaJack_Unload(); } static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi, @@ -997,39 +1190,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 ); @@ -1045,14 +1218,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: @@ -1165,7 +1338,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 ) @@ -1245,7 +1418,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, break; } } - free( jack_ports ); + jack_free( jack_ports ); UNLESS( !err, paInsufficientMemory ); /* Fewer ports than expected? */ @@ -1269,7 +1442,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, break; } } - free( jack_ports ); + jack_free( jack_ports ); UNLESS( !err , paInsufficientMemory ); /* Fewer ports than expected? */ @@ -1423,9 +1596,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; } @@ -1484,11 +1657,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; } @@ -1517,7 +1690,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 */ @@ -1525,12 +1698,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 ); @@ -1568,15 +1741,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 ); } } } @@ -1622,11 +1795,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 { @@ -1638,7 +1811,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 ); @@ -1657,15 +1830,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 ); 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 $ + * PortAudio Portable Real-Time Audio Library + * Latest Version at: http://www.portaudio.com + * JACK Implementation by Joshua Haberman + * + * Copyright (c) 2004 Stefan Westerfeld + * Copyright (c) 2004 Arve Knudsen + * Copyright (c) 2002 Joshua Haberman + * + * 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 +} 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 $ + * PortAudio Portable Real-Time Audio Library + * Latest Version at: http://www.portaudio.com + * JACK Implementation by Joshua Haberman + * + * Copyright (c) 2004 Stefan Westerfeld + * Copyright (c) 2004 Arve Knudsen + * Copyright (c) 2002 Joshua Haberman + * + * 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 + +#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 */ 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 5d2243879..be3cd7277 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 ); +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 diff --git a/win/Projects/portaudio-v19/portaudio-v19.vcproj b/win/Projects/portaudio-v19/portaudio-v19.vcproj index 591aa62b6..65dac0031 100644 --- a/win/Projects/portaudio-v19/portaudio-v19.vcproj +++ b/win/Projects/portaudio-v19/portaudio-v19.vcproj @@ -25,7 +25,7 @@ > @@ -337,6 +337,14 @@ RelativePath="..\..\..\lib-src\portaudio-v19\src\common\pa_dither.h" > + + + + @@ -677,6 +685,70 @@ > + + + + + + + + + + + + + + + + + + + + + + + + + +