} PaHostApiTypeId;
+/** Select host APIs and their initialization order.
+
+ The selected host APIs take effect the next time that Pa_Initialize() is
+ invoked.
+
+ @param hostApiTypes An array of host API identifiers belonging to the
+ PaHostApiTypeId enumeration.
+
+ @param count The number of elements in the hostApiTypes array. A count of
+ zero causes the default host API selection to be restored.
+
+ @return A PaErrorCode indicating whether the call succeeded or failed.
+
+ The paHostApiNotFound error code indicates that a host API specified by the
+ hostApiTypeIds parameter is not available.
+
+ The paInvalidHostApi error indicates that there was a problem with the
+ hostApiTypes array. E.g. it contained duplicate entries.
+
+ @note The host API initialization order determines default devices.
+
+ @see PaHostApiTypeId
+*/
+PaError Pa_SelectHostApis( const PaHostApiTypeId *hostApiTypes, int count );
+
+/** Returns the type ids of the selected host APIs in initialization order.
+
+ @param hostApiTypes (IN/OUT) An array that will be filled with
+ host API identifiers belonging to the PaHostApiTypeId enumeration.
+
+ @param count (OUT) The number of selected host APIs, returned even on error.
+
+ @param countAvailable The number of available elements in the hostApiTypes array.
+
+ @return A PaErrorCode indicating whether the call succeeded or failed.
+
+ The paInsufficientMemory error indicates that countAvailable was not large enough
+ to accommodate the list of selected host APIs. In this case, the needed
+ count is returned in the count parameter.
+
+ @see Pa_SelectHostApis
+*/
+PaError Pa_GetSelectedHostApis( PaHostApiTypeId *hostApiTypes, int countAvailable, int *count );
+
+/** Returns the type ids of all available host APIs in initialization order.
+
+ @param hostApiTypes (IN/OUT) An array that will be filled with
+ host API identifiers belonging to the PaHostApiTypeId enumeration.
+
+ @param count (OUT) The number of host APIs, returned even on error.
+
+ @param countAvailable The number of available elements in the hostApiTypes array.
+
+ @see Pa_SelectHostApis
+*/
+PaError Pa_GetAvailableHostApis( PaHostApiTypeId *hostApiTypes, int countAvailable, int *count );
+
+
/** A structure containing information about a particular host API. */
typedef struct PaHostApiInfo
}
-
static PaUtilHostApiRepresentation **hostApis_ = 0;
static int hostApisCount_ = 0;
static int defaultHostApiIndex_ = 0;
PaUtilStreamRepresentation *firstOpenStream_ = NULL;
-
#define PA_IS_INITIALISED_ (initializationCount_ != 0)
+/*
+ By default, selectedHostApiTypes_ == NULL and PortAudio initializes all
+ host APIs in the order that they are listed in paHostApiInitializers[].
+
+ If selectedHostApiTypes_ != NULL, then APIs are initialized in the
+ order specified in selectedHostApiTypes_.
+*/
+static PaHostApiTypeId *selectedHostApiTypes_ = NULL;
+static int selectedHostApiCount_ = 0;
static int CountHostApiInitializers( void )
{
int result = 0;
- while( paHostApiInitializers[ result ] != 0 )
+ while( paHostApiInitializers[ result ].initFunction != 0 )
++result;
return result;
}
+static const PaUtilHostApiInitializerEntry* FindHostApiInitializerEntry( PaHostApiTypeId hostApiType )
+{
+ int i = 0;
+
+ while( paHostApiInitializers[ i ].initFunction != 0 )
+ {
+ if( paHostApiInitializers[i].hostApiType == hostApiType )
+ return &paHostApiInitializers[i];
+ ++i;
+ }
+
+ return NULL;
+}
+
+static int CountSelectedHostApis()
+{
+ if( selectedHostApiTypes_ == NULL )
+ return CountHostApiInitializers();
+ else
+ return selectedHostApiCount_;
+}
+
+static const PaUtilHostApiInitializerEntry* GetSelectedHostApi( int index )
+{
+ if( selectedHostApiTypes_ == NULL )
+ return &paHostApiInitializers[index];
+ else
+ return FindHostApiInitializerEntry( selectedHostApiTypes_[index] );
+}
+
+PaError Pa_SelectHostApis( const PaHostApiTypeId *hostApiTypes, int count )
+{
+ int i, j;
+ PaHostApiTypeId *oldSelectedHostApiTypes = selectedHostApiTypes_;
+ PaHostApiTypeId *newSelectedHostApiTypes = NULL;
+
+ if( count == 0 )
+ {
+ /* revert to default state */
+ if( selectedHostApiTypes_ )
+ {
+ PaUtil_FreeMemory( selectedHostApiTypes_ );
+ selectedHostApiTypes_ = NULL;
+ selectedHostApiCount_ = 0;
+ }
+
+ return paNoError;
+ }
+
+ if( count < 0 )
+ return paInvalidHostApi;
+
+ if( hostApiTypes == NULL )
+ return paInvalidHostApi;
+
+ /* validation:
+ - verify that each hostApiTypes value is available (present in paHostApiInitializers)
+ - verify that hostApiTypes contains no duplicates
+ */
+ for( i=0; i < count; ++i )
+ {
+ if( FindHostApiInitializerEntry( hostApiTypes[i] ) == NULL )
+ return paHostApiNotFound;
+
+ for( j=i+1; j < count; ++j )
+ {
+ if (hostApiTypes[i] == hostApiTypes[j])
+ return paInvalidHostApi;
+ }
+ }
+
+ /* allocate a newSelectedHostApiTypes, copy ids into it */
+
+ newSelectedHostApiTypes = (PaHostApiTypeId*)PaUtil_AllocateMemory(
+ sizeof(PaHostApiTypeId) * count );
+ if( newSelectedHostApiTypes == NULL )
+ return paInsufficientMemory;
+
+ memcpy( newSelectedHostApiTypes, hostApiTypes, count*sizeof(PaHostApiTypeId) );
+
+ /* install new selectedHostApis and free old selectedHostApis_ */
+
+ selectedHostApiTypes_ = newSelectedHostApiTypes;
+ selectedHostApiCount_ = count;
+
+ if( oldSelectedHostApiTypes != NULL )
+ {
+ PaUtil_FreeMemory( oldSelectedHostApiTypes );
+ oldSelectedHostApiTypes = NULL;
+ }
+
+ return paNoError;
+}
+
+PaError Pa_GetSelectedHostApis( PaHostApiTypeId *hostApiTypes, int countAvailable, int *count )
+{
+ if( selectedHostApiTypes_ == NULL )
+ {
+ return Pa_GetAvailableHostApis( hostApiTypes, countAvailable, count );
+ }
+ else
+ {
+ *count = selectedHostApiCount_;
+ if( countAvailable >= selectedHostApiCount_ )
+ {
+ memcpy( hostApiTypes, selectedHostApiTypes_, selectedHostApiCount_*sizeof(PaHostApiTypeId) );
+ return paNoError;
+ }
+ else
+ {
+ return paInsufficientMemory;
+ }
+ }
+}
+
+PaError Pa_GetAvailableHostApis( PaHostApiTypeId *hostApiTypes, int countAvailable, int *count )
+{
+ int i;
+ int initializerCount = CountHostApiInitializers();
+
+ *count = initializerCount;
+ if( countAvailable >= initializerCount )
+ {
+ for( i=0; i < initializerCount; ++i )
+ hostApiTypes[i] = paHostApiInitializers[i].hostApiType;
+ }
+ else
+ {
+ return paInsufficientMemory;
+ }
+
+ return paNoError;
+}
+
static void TerminateHostApis( void )
{
{
PaError result = paNoError;
int i, initializerCount, baseDeviceIndex;
+ const PaUtilHostApiInitializerEntry *hostApiInitializer;
- initializerCount = CountHostApiInitializers();
+ initializerCount = CountSelectedHostApis();
hostApis_ = (PaUtilHostApiRepresentation**)PaUtil_AllocateMemory(
sizeof(PaUtilHostApiRepresentation*) * initializerCount );
PA_DEBUG(( "before paHostApiInitializers[%d].\n",i));
- result = paHostApiInitializers[i]( &hostApis_[hostApisCount_], hostApisCount_ );
+ hostApiInitializer = GetSelectedHostApi(i);
+ assert( hostApiInitializer != NULL );
+ result = hostApiInitializer->initFunction( &hostApis_[hostApisCount_], hostApisCount_ );
if( result != paNoError )
goto error;
*/
typedef PaError PaUtilHostApiInitializer( PaUtilHostApiRepresentation**, PaHostApiIndex );
+/** Associate a PaHostApiTypeId with each host API initialization function.
+
+*/
+typedef struct {
+ PaHostApiTypeId hostApiType;
+ PaUtilHostApiInitializer *initFunction;
+} PaUtilHostApiInitializerEntry;
+
/** paHostApiInitializers is a NULL-terminated array of host API initialization
- functions. These functions are called by pa_front.c to initialize the host APIs
- when the client calls Pa_Initialize().
+ entries, each containing an initialization function. The initialization
+ functions are called by pa_front.c to initialize the host APIs when the client
+ calls Pa_Initialize().
- The initialization functions are invoked in order.
+ By default initialization functions are invoked in order. The initialization
+ order may be modified by the client using Pa_SelectHostApis().
The first successfully initialized host API that has a default input *or* output
device is used as the default PortAudio host API. This is based on the logic that
There is a platform specific file that defines paHostApiInitializers for that
platform, pa_win/pa_win_hostapis.c contains the Win32 definitions for example.
*/
-extern PaUtilHostApiInitializer *paHostApiInitializers[];
+extern PaUtilHostApiInitializerEntry paHostApiInitializers[];
#ifdef __cplusplus
/** Note that on Linux, ALSA is placed before OSS so that the former is preferred over the latter.
*/
-PaUtilHostApiInitializer *paHostApiInitializers[] =
+PaUtilHostApiInitializerEntry paHostApiInitializers[] =
{
#ifdef __linux__
#if PA_USE_ALSA
- PaAlsa_Initialize,
+ { paALSA, PaAlsa_Initialize },
#endif
#if PA_USE_OSS
- PaOSS_Initialize,
+ { paOSS, PaOSS_Initialize },
#endif
#else /* __linux__ */
#if PA_USE_OSS
- PaOSS_Initialize,
+ { paOSS, PaOSS_Initialize },
#endif
#if PA_USE_ALSA
- PaAlsa_Initialize,
+ { paALSA, PaAlsa_Initialize },
#endif
#endif /* __linux__ */
#if PA_USE_JACK
- PaJack_Initialize,
+ { paJACK, PaJack_Initialize },
#endif
/* Added for IRIX, Pieter, oct 2, 2003: */
#if PA_USE_SGI
- PaSGI_Initialize,
+ { paAL, PaSGI_Initialize },
#endif
#if PA_USE_ASIHPI
- PaAsiHpi_Initialize,
+ { paAudioScienceHPI, PaAsiHpi_Initialize },
#endif
#if PA_USE_COREAUDIO
- PaMacCore_Initialize,
+ { paCoreAudio, PaMacCore_Initialize },
#endif
#if PA_USE_SKELETON
- PaSkeleton_Initialize,
+ /* just for testing. last in list so it isn't marked as default. */
+ { paInDevelopment, PaSkeleton_Initialize },
#endif
- 0 /* NULL terminated array */
+ { -1, 0 }, /* NULL terminated array */
};
#endif /* __cplusplus */
-PaUtilHostApiInitializer *paHostApiInitializers[] =
+PaUtilHostApiInitializerEntry paHostApiInitializers[] =
{
#if PA_USE_WMME
- PaWinMme_Initialize,
+ { paMME, PaWinMme_Initialize },
#endif
#if PA_USE_DS
- PaWinDs_Initialize,
+ { paDirectSound, PaWinDs_Initialize },
#endif
#if PA_USE_ASIO
- PaAsio_Initialize,
+ { paASIO, PaAsio_Initialize },
#endif
#if PA_USE_WASAPI
- PaWasapi_Initialize,
+ { paWASAPI, PaWasapi_Initialize },
#endif
#if PA_USE_WDMKS
- PaWinWdm_Initialize,
+ { paWDMKS, PaWinWdm_Initialize },
#endif
#if PA_USE_SKELETON
- PaSkeleton_Initialize, /* just for testing. last in list so it isn't marked as default. */
+ /* just for testing. last in list so it isn't marked as default. */
+ { paInDevelopment, PaSkeleton_Initialize },
#endif
- 0 /* NULL terminated array */
+ { -1, 0 }, /* NULL terminated array */
};
--- /dev/null
+/** @file patest_select_hostapis.c
+ @ingroup test_src
+ @brief Test of Pa_SelectHostApis
+ @author Ross Bencina <rossb@audiomulch.com>
+*/
+/*
+ * $Id$
+ *
+ * This program uses the PortAudio Portable Audio Library.
+ * For more information see: http://www.portaudio.com/
+ * Copyright (c) 1999-2016 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however,
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also
+ * requested that these non-binding requests be included along with the
+ * license above.
+ */
+#include <stdio.h>
+#include <assert.h>
+#include "portaudio.h"
+
+/*******************************************************************/
+int main(void);
+int main(void)
+{
+ int i, j, k;
+ int availableHostApiCount, scratchHostApiCount;
+#define MAX_HOST_API_COUNT 100
+ PaHostApiTypeId availableHostApis[MAX_HOST_API_COUNT];
+ PaHostApiTypeId scratchHostApis[MAX_HOST_API_COUNT];
+ PaError err;
+
+ availableHostApiCount = 0;
+ err = Pa_GetAvailableHostApis( availableHostApis, MAX_HOST_API_COUNT, &availableHostApiCount );
+ assert( err == paNoError );
+ assert( availableHostApiCount > 0 );
+
+ printf("available host api type ids:\n");
+ for (i = 0; i < availableHostApiCount; ++i )
+ {
+ printf("%d\n", availableHostApis[i]);
+ }
+
+ err = Pa_Initialize();
+ assert( err == paNoError );
+ Pa_Terminate();
+
+ /* excercise Pa_SelectHostApis and Pa_GetSelectedHostApis */
+
+ /* each API in turn */
+ for(i = 0; i < availableHostApiCount; ++i)
+ {
+ PaHostApiTypeId hostApiType = availableHostApis[i];
+
+ printf("selecting api type %d\n", hostApiType);
+
+ err = Pa_SelectHostApis(&hostApiType, 1);
+ assert( err == paNoError );
+
+ /* read back and verify selected apis*/
+ err = Pa_GetSelectedHostApis( scratchHostApis, MAX_HOST_API_COUNT, &scratchHostApiCount );
+ assert( err == paNoError );
+ assert( scratchHostApiCount == 1 );
+ assert( scratchHostApis[0] == hostApiType );
+
+ err = Pa_Initialize();
+ assert( err == paNoError );
+
+ /* verify that all devices match the selected API */
+
+ for(j = 0; j < Pa_GetDeviceCount(); ++j)
+ {
+ const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(j);
+ assert( deviceInfo != NULL );
+ assert( Pa_GetHostApiInfo(deviceInfo->hostApi)->type == hostApiType );
+ }
+
+ Pa_Terminate();
+ }
+
+ /* i counts 1 .. n simultaneously selected APIs */
+ for(i = 1; i < availableHostApiCount; ++i)
+ {
+ printf("selecting %d apis\n", i);
+
+ err = Pa_SelectHostApis(availableHostApis, i);
+ assert( err == paNoError );
+
+ /* read back and verify selected apis*/
+ err = Pa_GetSelectedHostApis( scratchHostApis, MAX_HOST_API_COUNT, &scratchHostApiCount );
+ assert( err == paNoError );
+ assert( scratchHostApiCount == i );
+ for( j = 0; j < i; ++j )
+ assert( scratchHostApis[j] == availableHostApis[j] );
+
+ err = Pa_Initialize();
+ assert( err == paNoError );
+
+ /* verify that all devices match one of the selected APIs */
+
+ for(j = 0; j < Pa_GetDeviceCount(); ++j)
+ {
+ const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(j);
+ assert( deviceInfo != NULL );
+
+ /* search for whether the device's host API is one of the selected host APIs */
+ err = paHostApiNotFound;
+ for(k = 0; k < i; ++k)
+ {
+ PaHostApiTypeId hostApiType = availableHostApis[k];
+ if( Pa_GetHostApiInfo(deviceInfo->hostApi)->type == hostApiType )
+ {
+ err = paNoError;
+ break;
+ }
+ }
+
+ assert( err != paHostApiNotFound );
+ }
+
+ Pa_Terminate();
+ }
+}