bin/patest_wire \
bin/patest_write_sine \
bin/patest_write_sine_nonint \
+ bin/patest_update_available_device_list \
bin/pa_devs \
bin/pa_fuzz \
bin/pa_minlat
src/hostapi/wdmks \
src/hostapi/wmme \
src/os/unix \
+ src/os/mac_osx \
src/os/win
SUBDIRS =
fi
SHARED_FLAGS="$LIBS -dynamiclib $mac_arches $mac_sysroot $mac_version_min"
CFLAGS="-std=c99 $CFLAGS $mac_arches $mac_sysroot $mac_version_min"
- OTHER_OBJS="src/os/unix/pa_unix_hostapis.o src/os/unix/pa_unix_util.o src/hostapi/coreaudio/pa_mac_core.o src/hostapi/coreaudio/pa_mac_core_utilities.o src/hostapi/coreaudio/pa_mac_core_blocking.o src/common/pa_ringbuffer.o"
+ OTHER_OBJS="src/os/unix/pa_unix_hostapis.o src/os/unix/pa_unix_util.o src/hostapi/coreaudio/pa_mac_core.o src/hostapi/coreaudio/pa_mac_core_utilities.o src/hostapi/coreaudio/pa_mac_core_blocking.o src/common/pa_ringbuffer.o src/os/mac_osx/pa_osx_hotplug.o"
PADLL="libportaudio.dylib"
;;
if [[ "x$with_directx" = "xyes" ]]; then
DXDIR="$with_dxdir"
- add_objects src/hostapi/dsound/pa_win_ds.o src/hostapi/dsound/pa_win_ds_dynlink.o src/os/win/pa_win_hostapis.o src/os/win/pa_win_util.o src/os/win/pa_win_waveformat.o
+ add_objects src/hostapi/dsound/pa_win_ds.o src/hostapi/dsound/pa_win_ds_dynlink.o src/os/win/pa_win_hostapis.o src/os/win/pa_win_util.o src/os/win/pa_win_waveformat.o src/os/win/pa_win_hotplug.o
LIBS="-lwinmm -lm -ldsound -lole32"
DLL_LIBS="${DLL_LIBS} -lwinmm -lm -L$DXDIR/lib -ldsound -lole32"
#VC98="\"/c/Program Files/Microsoft Visual Studio/VC98/Include\""
if [[ "x$with_wdmks" = "xyes" ]]; then
DXDIR="$with_dxdir"
- add_objects src/hostapi/wdmks/pa_win_wdmks.o src/os/win/pa_win_hostapis.o src/os/win/pa_win_util.o
+ add_objects src/hostapi/wdmks/pa_win_wdmks.o src/os/win/pa_win_hostapis.o src/os/win/pa_win_util.o src/os/win/pa_win_wdmks_utils.o
LIBS="-lwinmm -lm -luuid -lsetupapi -lole32"
DLL_LIBS="${DLL_LIBS} -lwinmm -lm -L$DXDIR/lib -luuid -lsetupapi -lole32"
#VC98="\"/c/Program Files/Microsoft Visual Studio/VC98/Include\""
if [[ "$have_alsa" = "yes" ] && [ "$with_alsa" != "no" ]] ; then
DLL_LIBS="$DLL_LIBS -lasound"
LIBS="$LIBS -lasound"
- OTHER_OBJS="$OTHER_OBJS src/hostapi/alsa/pa_linux_alsa.o"
+ OTHER_OBJS="$OTHER_OBJS src/hostapi/alsa/pa_linux_alsa.o src/os/unix/pa_linux_hotplug.o"
INCLUDES="$INCLUDES pa_linux_alsa.h"
AC_DEFINE(PA_USE_ALSA)
fi
for( i = 0 ; i < paInternalInfo_.hostApisCount_ ; ++i )
{
PaUtilHostApiRepresentation *hostApi = paInternalInfo_.hostApis_[i];
+ PA_DEBUG(( "Scanning new device list for host api %d.\n",i));
if( hostApi->ScanDeviceInfos == NULL )
continue;
- PA_DEBUG(( "Scanning new device list for host api %d.\n",i));
if( hostApi->ScanDeviceInfos( hostApi, i, &scanResults[ i ], &deviceCounts[ i ] ) != paNoError )
break;
-
}
/* Check the result of the scan operation */
}
PaAlsaDeviceInfo;
+/* used for tranferring device infos during scanning / rescanning */
+typedef struct PaLinuxScanDeviceInfosResults
+{
+ PaDeviceInfo **deviceInfos;
+ PaDeviceIndex defaultInputDevice;
+ PaDeviceIndex defaultOutputDevice;
+ int deviceCount;
+} PaLinuxScanDeviceInfosResults;
+
/* prototypes for functions declared in this file */
static void Terminate( struct PaUtilHostApiRepresentation *hostApi );
static PaError IsStreamActive( PaStream *stream );
static PaTime GetStreamTime( PaStream *stream );
static double GetStreamCpuLoad( PaStream* stream );
-static PaError BuildDeviceList( PaAlsaHostApiRepresentation *hostApi );
+static PaError BuildDeviceList( PaAlsaHostApiRepresentation *hostApi, void** scanResults, int* deviceCount );
static int SetApproximateSampleRate( snd_pcm_t *pcm, snd_pcm_hw_params_t *hwParams, double sampleRate );
static int GetExactSampleRate( snd_pcm_hw_params_t *hwParams, double *sampleRate );
+static PaError ScanDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index,
+ void **newDeviceInfos, int *newDeviceCount );
+static PaError CommitDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index,
+ void *deviceInfos, int deviceCount);
+static PaError DisposeDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, void *deviceInfos,
+ int deviceCount );
+
/* Callback prototypes */
static void *CallbackThreadFunc( void *userData );
{
PaError result = paNoError;
PaAlsaHostApiRepresentation *alsaHostApi = NULL;
+ void* scanResults = NULL;
+ int deviceCount = 0;
/* Try loading Alsa library. */
if (!PaAlsa_LoadLibrary())
alsaHostApi->hostApiIndex = hostApiIndex;
*hostApi = (PaUtilHostApiRepresentation*)alsaHostApi;
+ (*hostApi)->deviceInfos = NULL;
(*hostApi)->info.structVersion = 1;
(*hostApi)->info.type = paALSA;
(*hostApi)->info.name = "ALSA";
+ (*hostApi)->ScanDeviceInfos = NULL;
+ (*hostApi)->CommitDeviceInfos = NULL;
+ (*hostApi)->DisposeDeviceInfos = NULL;
(*hostApi)->Terminate = Terminate;
(*hostApi)->OpenStream = OpenStream;
(*hostApi)->IsFormatSupported = IsFormatSupported;
+ (*hostApi)->ScanDeviceInfos = ScanDeviceInfos;
+ (*hostApi)->CommitDeviceInfos = CommitDeviceInfos;
+ (*hostApi)->DisposeDeviceInfos = DisposeDeviceInfos;
/** If AlsaErrorHandler is to be used, do not forget to unregister callback pointer in
Terminate function.
*/
/*ENSURE_( snd_lib_error_set_handler(AlsaErrorHandler), paUnanticipatedHostError );*/
- PA_ENSURE( BuildDeviceList( alsaHostApi ) );
+ ScanDeviceInfos(&alsaHostApi->baseHostApiRep, hostApiIndex, &scanResults,
+ &deviceCount);
+ CommitDeviceInfos(&alsaHostApi->baseHostApiRep, hostApiIndex, scanResults, deviceCount);
PaUtil_InitializeStreamInterface( &alsaHostApi->callbackStreamInterface,
CloseStream, StartStream,
}
PaUtil_FreeMemory( alsaHostApi );
- alsa_snd_config_update_free_global();
+// damencho, removed fo compability with pulseaudio versions before 0.9.16
+// segfault application:
+// bugtrack alsa: 0002124: snd_config_update_free_global kills applications using user space alsa plugins
+// snd_config_update_free_global();
+// alsa_snd_config_update_free_global();
/* Close Alsa library. */
PaAlsa_CloseLibrary();
}
static PaError FillInDevInfo( PaAlsaHostApiRepresentation *alsaApi, HwDevInfo* deviceName, int blocking,
- PaAlsaDeviceInfo* devInfo, int* devIdx )
+ PaAlsaDeviceInfo* devInfo, int* devIdx, PaLinuxScanDeviceInfosResults* out )
{
PaError result = 0;
PaDeviceInfo *baseDeviceInfo = &devInfo->baseDeviceInfo;
if( baseDeviceInfo->maxInputChannels > 0 || baseDeviceInfo->maxOutputChannels > 0 )
{
/* Make device default if there isn't already one or it is the ALSA "default" device */
- if( (baseApi->info.defaultInputDevice == paNoDevice || !strcmp(deviceName->alsaName,
+ if( (out->defaultInputDevice == paNoDevice || !strcmp(deviceName->alsaName,
"default" )) && baseDeviceInfo->maxInputChannels > 0 )
{
- baseApi->info.defaultInputDevice = *devIdx;
+ out->defaultInputDevice = *devIdx;
PA_DEBUG(("Default input device: %s\n", deviceName->name));
}
- if( (baseApi->info.defaultOutputDevice == paNoDevice || !strcmp(deviceName->alsaName,
+ if( (out->defaultOutputDevice == paNoDevice || !strcmp(deviceName->alsaName,
"default" )) && baseDeviceInfo->maxOutputChannels > 0 )
{
- baseApi->info.defaultOutputDevice = *devIdx;
+ out->defaultOutputDevice = *devIdx;
PA_DEBUG(("Default output device: %s\n", deviceName->name));
}
PA_DEBUG(("%s: Adding device %s: %d\n", __FUNCTION__, deviceName->name, *devIdx));
- baseApi->deviceInfos[*devIdx] = (PaDeviceInfo *) devInfo;
+ out->deviceInfos[*devIdx] = (PaDeviceInfo *) devInfo;
(*devIdx) += 1;
}
else
}
/* Build PaDeviceInfo list, ignore devices for which we cannot determine capabilities (possibly busy, sigh) */
-static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi )
+static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi, void** scanResults, int* count)
{
PaUtilHostApiRepresentation *baseApi = &alsaApi->baseHostApiRep;
+ PaLinuxScanDeviceInfosResults *outArgument = NULL;
PaAlsaDeviceInfo *deviceInfoArray;
int cardIdx = -1, devIdx = 0;
snd_ctl_card_info_t *cardInfo;
#ifdef PA_ENABLE_DEBUG_OUTPUT
PaTime startTime = PaUtil_GetTime();
#endif
+ PaLinuxScanDeviceInfosResults* out = NULL;
if( getenv( "PA_ALSA_INITIALIZE_BLOCK" ) && atoi( getenv( "PA_ALSA_INITIALIZE_BLOCK" ) ) )
blocking = 0;
- /* These two will be set to the first working input and output device, respectively */
- baseApi->info.defaultInputDevice = paNoDevice;
- baseApi->info.defaultOutputDevice = paNoDevice;
/* Gather info about hw devices
else
PA_DEBUG(( "%s: Iterating over ALSA plugins failed: %s\n", __FUNCTION__, alsa_snd_strerror( res ) ));
+ out = (PaLinuxScanDeviceInfosResults *) PaUtil_GroupAllocateMemory(
+ alsaApi->allocations, sizeof(PaLinuxScanDeviceInfosResults) );
+
+ out->defaultInputDevice = paNoDevice;
+ out->defaultOutputDevice = paNoDevice;
+
/* allocate deviceInfo memory based on the number of devices */
- PA_UNLESS( baseApi->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
+ PA_UNLESS( out->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
alsaApi->allocations, sizeof(PaDeviceInfo*) * (numDeviceNames) ), paInsufficientMemory );
/* allocate all device info structs in a contiguous block */
continue;
}
- PA_ENSURE( FillInDevInfo( alsaApi, hwInfo, blocking, devInfo, &devIdx ) );
+ PA_ENSURE( FillInDevInfo( alsaApi, hwInfo, blocking, devInfo, &devIdx, out ) );
}
assert( devIdx < numDeviceNames );
/* Now inspect 'dmix' and 'default' plugins */
}
PA_ENSURE( FillInDevInfo( alsaApi, hwInfo, blocking, devInfo,
- &devIdx ) );
+ &devIdx, out ) );
}
free( hwDevInfos );
- baseApi->info.deviceCount = devIdx; /* Number of successfully queried devices */
+ out->deviceCount = devIdx; /* Number of successfully queried devices */
+ *scanResults = out;
+ *count = out->deviceCount;
#ifdef PA_ENABLE_DEBUG_OUTPUT
PA_DEBUG(( "%s: Building device list took %f seconds\n", __FUNCTION__, PaUtil_GetTime() - startTime ));
ENSURE_( alsa_snd_pcm_sw_params_set_avail_min( self->pcm, swParams, self->framesPerBuffer ), paUnanticipatedHostError );
ENSURE_( alsa_snd_pcm_sw_params_set_xfer_align( self->pcm, swParams, 1 ), paUnanticipatedHostError );
- ENSURE_( alsa_snd_pcm_sw_params_set_tstamp_mode( self->pcm, swParams, SND_PCM_TSTAMP_ENABLE ), paUnanticipatedHostError );
+ ENSURE_( alsa_snd_pcm_sw_params_set_tstamp_mode( self->pcm, swParams, SND_PCM_TSTAMP_MMAP ), paUnanticipatedHostError );
/* Set the parameters! */
ENSURE_( alsa_snd_pcm_sw_params( self->pcm, swParams ), paUnanticipatedHostError );
snd_pcm_sframes_t framesAvail = alsa_snd_pcm_avail_update( self->pcm );
*xrunOccurred = 0;
- if( -EPIPE == framesAvail )
- {
+ /* Get pcm_state and check for xrun condition. On playback I often see
+ * xrun but avail_update does not return -EPIPE but framesAvail larger
+ * than bufferSize. In case of xrun status set xrun flag, leave framesize
+ * as reported by avail_update, will be fixed below. In case avail_update
+ * returns -EPIPE process as usual. wd-xxx
+ */
+ snd_pcm_state_t state = snd_pcm_state( self->pcm ); /* wd-xxx */
+ if (state == SND_PCM_STATE_XRUN) {
+ // printf("xrun, fav %d\n", framesAvail); fflush(stdout); // DEBUG-WD
+ *xrunOccurred = 1;
+ }
+ if( -EPIPE == framesAvail) {
+ // printf("xrun-1, fav %d\n", framesAvail); fflush(stdout); // DEBUG-WD
*xrunOccurred = 1;
framesAvail = 0;
}
ENSURE_( framesAvail, paUnanticipatedHostError );
}
+ /* Fix frames avail, should not be bigger than bufferSize wd-xxx */
+ if (framesAvail > self->bufferSize) {
+ // printf("xrun-2, fav %d\n", framesAvail); fflush(stdout); // DEBUG-WD
+ framesAvail = self->bufferSize;
+ }
*numFrames = framesAvail;
error:
*shouldPoll = 0;
}
+ else
+ {
+ // not actually used
+ unsigned long framesAvail = 0;
+ // now check for xrun
+ PaAlsaStreamComponent_GetAvailableFrames(self, &framesAvail, xrun );
+ }
error:
return result;
framesAvail, &xrun ) );
if( xrun )
{
+ if(*framesAvail == 0)
+ {
+ result = paInternalError;
+ }
goto end;
}
Pa_Sleep( 1 ); /* avoid hot loop */
continue;
}
+ result = paInternalError;
/* TODO: Add macro for checking system calls */
PA_ENSURE( paInternalError );
xrun = 1; /* try recovering device */
PA_DEBUG(( "%s: poll timed out\n", __FUNCTION__, timeouts ));
+ result = paTimedOut;
goto end;/*PA_ENSURE( paTimedOut );*/
}
}
while( frames > 0 )
{
int xrun = 0;
- PA_ENSURE( PaAlsaStream_WaitForFrames( stream, &framesAvail, &xrun ) );
- framesGot = PA_MIN( framesAvail, frames );
+ PA_ENSURE( PaAlsaStream_WaitForFrames( stream, &framesAvail, &xrun ) );
+ /*
+ * In case of overrun WaitForFrames leaves the capture stream in STATE_PREPARED
+ * most of the time. handleXrun() restarts the ALSA stream only in case
+ * snd_pcm_recover() fails, which usually does not happen.
+ * Here we start the pcm stream again and go for another try. Another
+ * option is: set result to paOverrun and return to caller. Then
+ * the caller needs to call ReadStream again. This takes more time and
+ * we lose even more frames.
+ */
+ if (xrun) { /* wd-xxx */
+ if( snd_pcm_state( stream->capture.pcm ) == SND_PCM_STATE_PREPARED ) {
+ ENSURE_( snd_pcm_start( stream->capture.pcm ), paUnanticipatedHostError );
+ }
+ continue;
+ }
+ framesGot = PA_MIN( framesAvail, frames );
PA_ENSURE( PaAlsaStream_SetUpBuffers( stream, &framesGot, &xrun ) );
if( framesGot > 0 )
{
busyRetries_ = retries;
return paNoError;
}
+
+static PaError ScanDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex hostApiIndex,
+ void **scanResults, int *newDeviceCount)
+{
+ PaAlsaHostApiRepresentation* alsaHostApi = (PaAlsaHostApiRepresentation*)hostApi;
+ PaError result = paNoError;
+ PA_ENSURE(BuildDeviceList( alsaHostApi, scanResults, newDeviceCount ));
+
+ return paNoError;
+
+error:
+ return result;
+}
+
+static PaError CommitDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index,
+ void *scanResults, int deviceCount)
+{
+ PaAlsaHostApiRepresentation* alsaHostApi = (PaAlsaHostApiRepresentation*)hostApi;
+ PaError result = paNoError;
+
+ /* These two will be set to the first working input and output device, respectively */
+ hostApi->info.defaultInputDevice = paNoDevice;
+ hostApi->info.defaultOutputDevice = paNoDevice;
+
+ /* Free any old memory which might be in the device info */
+ if( hostApi->deviceInfos )
+ {
+ /* all device info structs are allocated in a block so we can destroy them here */
+ PaUtil_GroupFreeMemory( alsaHostApi->allocations, hostApi->deviceInfos[0] );
+ PaUtil_GroupFreeMemory( alsaHostApi->allocations, hostApi->deviceInfos );
+ hostApi->deviceInfos = NULL;
+ }
+
+ if( scanResults != NULL )
+ {
+ PaLinuxScanDeviceInfosResults *scanDeviceInfosResults = ( PaLinuxScanDeviceInfosResults * ) scanResults;
+
+ if( deviceCount > 0 )
+ {
+ /* use the array allocated in ScanDeviceInfos() as our deviceInfos */
+ hostApi->deviceInfos = scanDeviceInfosResults->deviceInfos;
+ hostApi->info.defaultInputDevice = scanDeviceInfosResults->defaultInputDevice;
+ hostApi->info.defaultOutputDevice = scanDeviceInfosResults->defaultOutputDevice;
+ hostApi->info.deviceCount = deviceCount;
+ }
+
+ PaUtil_GroupFreeMemory( alsaHostApi->allocations, scanDeviceInfosResults );
+ }
+
+ return result;
+}
+
+static PaError DisposeDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, void *scanResults, int deviceCount)
+{
+ PaAlsaHostApiRepresentation *alsaHostApi = (PaAlsaHostApiRepresentation*)hostApi;
+
+ if( scanResults != NULL )
+ {
+ PaLinuxScanDeviceInfosResults *scanDeviceInfosResults = ( PaLinuxScanDeviceInfosResults * ) scanResults;
+ if( scanDeviceInfosResults->deviceInfos )
+ {
+ /* all device info structs are allocated in a block so we can destroy them here */
+ PaUtil_GroupFreeMemory( alsaHostApi->allocations, scanDeviceInfosResults->deviceInfos[0] );
+ PaUtil_GroupFreeMemory( alsaHostApi->allocations, scanDeviceInfosResults->deviceInfos );
+ }
+
+ PaUtil_GroupFreeMemory(alsaHostApi->allocations, scanDeviceInfosResults );
+ }
+
+ return paNoError;
+}
+
/*
- * $Id$
+ * $Id: pa_asio.cpp 1661 2011-04-28 18:54:46Z rob_bielik $
* Portable Audio I/O Library for ASIO Drivers
*
* Author: Stephane Letz
}
+ (*hostApi)->ScanDeviceInfos = NULL;
+ (*hostApi)->CommitDeviceInfos = NULL;
+ (*hostApi)->DisposeDeviceInfos = NULL;
(*hostApi)->Terminate = Terminate;
(*hostApi)->OpenStream = OpenStream;
(*hostApi)->IsFormatSupported = IsFormatSupported;
/* prototypes for functions declared in this file */
PaError PaMacCore_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
+static PaError ScanDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index,
+ void **newDeviceInfos, int *newDeviceCount );
+static PaError CommitDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index,
+ void *deviceInfos, int deviceCount);
+static PaError DisposeDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, void *deviceInfos,
+ int deviceCount );
+
+/* structures */
+
+/* used for tranferring device infos during scanning / rescanning */
+typedef struct PaMacScanDeviceInfosResults
+{
+ PaDeviceInfo **deviceInfos;
+ PaDeviceIndex defaultInputDevice;
+ PaDeviceIndex defaultOutputDevice;
+
+ AudioDeviceID* devIds;
+ int devCount;
+ AudioDeviceID devInputDevice;
+ AudioDeviceID devOutputDevice;
+} PaMacScanDeviceInfosResults;
/*
* Function declared in pa_mac_core.h. Sets up a PaMacCoreStreamInfoStruct
return NULL;
PaMacAUHAL *macCoreHostApi = (PaMacAUHAL*)hostApi;
AudioDeviceID hostApiDevice = macCoreHostApi->devIds[device];
-
UInt32 size = 0;
error = AudioDeviceGetPropertyInfo( hostApiDevice,
}
-/*currently, this is only used in initialization, but it might be modified
- to be used when the list of devices changes.*/
-static PaError gatherDeviceInfo(PaMacAUHAL *auhalHostApi)
+//static PaError gatherDeviceInfo(PaMacAUHAL *auhalHostApi)
+static PaError gatherDeviceInfo(PaMacAUHAL* auhalHostApi, void** scanResults, int* count)
{
- UInt32 size;
- UInt32 propsize;
- VVDBUG(("gatherDeviceInfo()\n"));
- /* -- free any previous allocations -- */
- if( auhalHostApi->devIds )
- PaUtil_GroupFreeMemory(auhalHostApi->allocations, auhalHostApi->devIds);
- auhalHostApi->devIds = NULL;
+ UInt32 propsize = 0;
+ UInt32 size = sizeof(AudioDeviceID);
+ PaMacScanDeviceInfosResults *outArgument = NULL;
+ PaError result = paNoError;
+ VVDBUG(("gatherDeviceInfo()\n"));
/* -- figure out how many devices there are -- */
AudioHardwareGetPropertyInfo( kAudioHardwarePropertyDevices,
&propsize,
NULL );
- auhalHostApi->devCount = propsize / sizeof( AudioDeviceID );
+ *count = (propsize / sizeof(AudioDeviceID));
- VDBUG( ( "Found %ld device(s).\n", auhalHostApi->devCount ) );
+ VDBUG( ( "Found %ld device(s).\n", *count ) );
+
+ if(*count == 0)
+ return paNoError;
+
+ /* Allocate the out param for all the info we need */
+ outArgument = (PaMacScanDeviceInfosResults *) PaUtil_GroupAllocateMemory(
+ auhalHostApi->allocations, sizeof(PaMacScanDeviceInfosResults) );
+
+ if( !outArgument )
+ {
+ result = paInsufficientMemory;
+ return result;
+ }
+
+ outArgument->devCount = *count;
/* -- copy the device IDs -- */
- auhalHostApi->devIds = (AudioDeviceID *)PaUtil_GroupAllocateMemory(
+ outArgument->devIds = (AudioDeviceID *)PaUtil_GroupAllocateMemory(
auhalHostApi->allocations,
propsize );
- if( !auhalHostApi->devIds )
+ if( !outArgument->devIds )
return paInsufficientMemory;
AudioHardwareGetProperty( kAudioHardwarePropertyDevices,
&propsize,
- auhalHostApi->devIds );
+ outArgument->devIds );
#ifdef MAC_CORE_VERBOSE_DEBUG
{
int i;
- for( i=0; i<auhalHostApi->devCount; ++i )
- printf( "Device %d\t: %ld\n", i, auhalHostApi->devIds[i] );
+ for( i=0; i<outArgument->devCount; ++i )
+ printf( "Device %d\t: %ld\n", i, outArgument->devIds[i] );
}
#endif
- size = sizeof(AudioDeviceID);
- auhalHostApi->defaultIn = kAudioDeviceUnknown;
- auhalHostApi->defaultOut = kAudioDeviceUnknown;
+ outArgument->devInputDevice = kAudioDeviceUnknown;
+ outArgument->devOutputDevice = kAudioDeviceUnknown;
/* determine the default device. */
/* I am not sure how these calls to AudioHardwareGetProperty()
device as the default. */
if( 0 != AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice,
&size,
- &auhalHostApi->defaultIn) ) {
+ &outArgument->devInputDevice) ) {
int i;
- auhalHostApi->defaultIn = kAudioDeviceUnknown;
+ outArgument->devInputDevice = kAudioDeviceUnknown;
VDBUG(("Failed to get default input device from OS."));
VDBUG((" I will substitute the first available input Device."));
- for( i=0; i<auhalHostApi->devCount; ++i ) {
+
+ for( i=0; i< outArgument->devCount; ++i ) {
PaDeviceInfo devInfo;
if( 0 != GetChannelInfo( auhalHostApi, &devInfo,
- auhalHostApi->devIds[i], TRUE ) )
+ outArgument->devIds[i], TRUE ) )
if( devInfo.maxInputChannels ) {
- auhalHostApi->defaultIn = auhalHostApi->devIds[i];
+ outArgument->devInputDevice = outArgument->devIds[i];
break;
}
}
}
if( 0 != AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
&size,
- &auhalHostApi->defaultOut) ) {
+ &outArgument->devOutputDevice) ) {
int i;
- auhalHostApi->defaultIn = kAudioDeviceUnknown;
+ outArgument->devOutputDevice = kAudioDeviceUnknown;
VDBUG(("Failed to get default output device from OS."));
VDBUG((" I will substitute the first available output Device."));
- for( i=0; i<auhalHostApi->devCount; ++i ) {
+ for( i=0; i<outArgument->devCount; ++i ) {
PaDeviceInfo devInfo;
if( 0 != GetChannelInfo( auhalHostApi, &devInfo,
- auhalHostApi->devIds[i], FALSE ) )
+ outArgument->devIds[i], FALSE ) )
if( devInfo.maxOutputChannels ) {
- auhalHostApi->defaultOut = auhalHostApi->devIds[i];
+ outArgument->devOutputDevice = outArgument->devIds[i];
break;
}
}
}
- VDBUG( ( "Default in : %ld\n", auhalHostApi->defaultIn ) );
- VDBUG( ( "Default out: %ld\n", auhalHostApi->defaultOut ) );
+ VDBUG( ( "Default in : %ld\n", outArgument->devInputDevice ) );
+ VDBUG( ( "Default out: %ld\n", outArgument->devOutputDevice ) );
+ *scanResults = outArgument;
return paNoError;
}
AudioDeviceID macCoreDeviceId,
int isInput)
{
- UInt32 propSize;
+ UInt32 propSize = 0;
PaError err = paNoError;
- UInt32 i;
+ UInt32 i = 0;
int numChannels = 0;
AudioBufferList *buflist = NULL;
UInt32 frameLatency;
PaError PaMacCore_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
{
PaError result = paNoError;
- int i;
PaMacAUHAL *auhalHostApi = NULL;
- PaDeviceInfo *deviceInfoArray;
int unixErr;
+ void* scanResults = NULL;
+ int deviceCount = 0;
VVDBUG(("PaMacCore_Initialize(): hostApiIndex=%d\n", hostApiIndex));
auhalHostApi->devIds = NULL;
auhalHostApi->devCount = 0;
- /* get the info we need about the devices */
- result = gatherDeviceInfo( auhalHostApi );
- if( result != paNoError )
- goto error;
-
*hostApi = &auhalHostApi->inheritedHostApiRep;
(*hostApi)->info.structVersion = 1;
(*hostApi)->info.type = paCoreAudio;
(*hostApi)->info.name = "Core Audio";
-
+
+ (*hostApi)->deviceInfos = NULL;
+
(*hostApi)->info.defaultInputDevice = paNoDevice;
(*hostApi)->info.defaultOutputDevice = paNoDevice;
-
(*hostApi)->info.deviceCount = 0;
- if( auhalHostApi->devCount > 0 )
- {
- (*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
- auhalHostApi->allocations, sizeof(PaDeviceInfo*) * auhalHostApi->devCount);
- if( !(*hostApi)->deviceInfos )
- {
- result = paInsufficientMemory;
- goto error;
- }
+ (*hostApi)->ScanDeviceInfos = ScanDeviceInfos;
+ (*hostApi)->CommitDeviceInfos = CommitDeviceInfos;
+ (*hostApi)->DisposeDeviceInfos = DisposeDeviceInfos;
- /* allocate all device info structs in a contiguous block */
- deviceInfoArray = (PaDeviceInfo*)PaUtil_GroupAllocateMemory(
- auhalHostApi->allocations, sizeof(PaDeviceInfo) * auhalHostApi->devCount );
- if( !deviceInfoArray )
- {
- result = paInsufficientMemory;
- goto error;
- }
+ result = ScanDeviceInfos(&auhalHostApi->inheritedHostApiRep, hostApiIndex, &scanResults,
+ &deviceCount);
- for( i=0; i < auhalHostApi->devCount; ++i )
- {
- int err;
- err = InitializeDeviceInfo( auhalHostApi, &deviceInfoArray[i],
- auhalHostApi->devIds[i],
- hostApiIndex );
- if (err == paNoError)
- { /* copy some info and set the defaults */
- (*hostApi)->deviceInfos[(*hostApi)->info.deviceCount] = &deviceInfoArray[i];
- if (auhalHostApi->devIds[i] == auhalHostApi->defaultIn)
- (*hostApi)->info.defaultInputDevice = (*hostApi)->info.deviceCount;
- if (auhalHostApi->devIds[i] == auhalHostApi->defaultOut)
- (*hostApi)->info.defaultOutputDevice = (*hostApi)->info.deviceCount;
- (*hostApi)->info.deviceCount++;
- }
- else
- { /* there was an error. we need to shift the devices down, so we ignore this one */
- int j;
- auhalHostApi->devCount--;
- for( j=i; j<auhalHostApi->devCount; ++j )
- auhalHostApi->devIds[j] = auhalHostApi->devIds[j+1];
- i--;
- }
- }
- }
+ if(result != paNoError)
+ goto error;
+
+ /* FIXME for now we ignore the result of CommitDeviceInfos(), it should probably be an atomic non-failing operation */
+ CommitDeviceInfos( &auhalHostApi->inheritedHostApiRep, hostApiIndex, scanResults, deviceCount );
(*hostApi)->Terminate = Terminate;
(*hostApi)->OpenStream = OpenStream;
return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
}
+
+static PaError ScanDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex hostApiIndex,
+ void **scanResults, int *newDeviceCount)
+{
+ PaMacAUHAL* auhalHostApi = (PaMacAUHAL*)hostApi;
+ PaDeviceInfo *deviceInfoArray = NULL;
+ PaError result = paNoError;
+ int i = 0;
+ PaMacScanDeviceInfosResults* out = NULL;
+
+ /* get the info we need about the devices */
+ result = gatherDeviceInfo( auhalHostApi, scanResults, newDeviceCount );
+
+ if( result != paNoError )
+ return result;
+
+ out = (PaMacScanDeviceInfosResults*)*scanResults;
+
+ if( out->devCount > 0 )
+ {
+ int count = 0;
+
+ /* allocate array for pointers to PaDeviceInfo structs */
+ out->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
+ auhalHostApi->allocations, sizeof(PaDeviceInfo*) * out->devCount);
+ if( !out->deviceInfos )
+ {
+ result = paInsufficientMemory;
+ return result;
+ }
+
+ /* allocate all device info structs in a contiguous block */
+ deviceInfoArray = (PaDeviceInfo*)PaUtil_GroupAllocateMemory(
+ auhalHostApi->allocations, sizeof(PaDeviceInfo) * out->devCount );
+ if( !deviceInfoArray )
+ {
+ result = paInsufficientMemory;
+ return result;
+ }
+
+ for( i=0; i < out->devCount; ++i )
+ {
+ int err;
+ err = InitializeDeviceInfo( auhalHostApi, &deviceInfoArray[i],
+ out->devIds[i],
+ hostApiIndex );
+ if (err == paNoError)
+ {
+ /* copy some info and set the defaults */
+ out->deviceInfos[count] = &deviceInfoArray[i];
+
+ if (out->devIds[i] == out->devInputDevice)
+ {
+ out->defaultInputDevice = count;
+ }
+ if (out->devIds[i] == out->devOutputDevice)
+ {
+ out->defaultOutputDevice = count;
+ }
+ count++;
+ }
+ else
+ {
+ /* there was an error. we need to shift the devices down, so we ignore this one */
+ int j;
+ out->devCount--;
+ for( j=i; j<out->devCount; ++j )
+ out->devIds[j] = out->devIds[j+1];
+ i--;
+ }
+ }
+ }
+ *newDeviceCount = out->devCount;
+
+ return paNoError;
+}
+
+static PaError CommitDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index,
+ void *scanResults, int deviceCount)
+{
+ PaMacAUHAL* auhalHostApi = (PaMacAUHAL*)hostApi;
+ PaError result = paNoError;
+
+ hostApi->info.deviceCount = 0;
+ hostApi->info.defaultInputDevice = paNoDevice;
+ hostApi->info.defaultOutputDevice = paNoDevice;
+
+ /* -- free any previous allocations -- */
+ if( auhalHostApi->devIds )
+ {
+ PaUtil_GroupFreeMemory(auhalHostApi->allocations, auhalHostApi->devIds);
+ }
+ auhalHostApi->devIds = NULL;
+
+ /* Free any old memory which might be in the device info */
+ if( hostApi->deviceInfos )
+ {
+ PaUtil_GroupFreeMemory( auhalHostApi->allocations, hostApi->deviceInfos[0] );
+ PaUtil_GroupFreeMemory( auhalHostApi->allocations, hostApi->deviceInfos );
+ hostApi->deviceInfos = NULL;
+ }
+
+ if( scanResults != NULL )
+ {
+ PaMacScanDeviceInfosResults *scanDeviceInfosResults = ( PaMacScanDeviceInfosResults * ) scanResults;
+
+ if( deviceCount > 0 )
+ {
+ /* use the array allocated in ScanDeviceInfos() as our deviceInfos */
+ hostApi->deviceInfos = scanDeviceInfosResults->deviceInfos;
+ hostApi->info.defaultInputDevice = scanDeviceInfosResults->defaultInputDevice;
+ hostApi->info.defaultOutputDevice = scanDeviceInfosResults->defaultOutputDevice;
+ hostApi->info.deviceCount = deviceCount;
+ auhalHostApi->devIds = scanDeviceInfosResults->devIds;
+ auhalHostApi->devCount = scanDeviceInfosResults->devCount;
+ auhalHostApi->defaultIn = scanDeviceInfosResults->devInputDevice;
+ auhalHostApi->defaultOut = scanDeviceInfosResults->devOutputDevice;
+ }
+
+ PaUtil_GroupFreeMemory( auhalHostApi->allocations, scanDeviceInfosResults );
+ }
+
+ return result;
+}
+
+static PaError DisposeDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, void *scanResults, int deviceCount)
+{
+ PaMacAUHAL *auhalHostApi = (PaMacAUHAL*)hostApi;
+
+ if( scanResults != NULL )
+ {
+ PaMacScanDeviceInfosResults *scanDeviceInfosResults = ( PaMacScanDeviceInfosResults * ) scanResults;
+ if( scanDeviceInfosResults->deviceInfos )
+ {
+ /* all device info structs are allocated in a block so we can destroy them here */
+ PaUtil_GroupFreeMemory( auhalHostApi->allocations, scanDeviceInfosResults->deviceInfos[0] );
+ PaUtil_GroupFreeMemory( auhalHostApi->allocations, scanDeviceInfosResults->deviceInfos );
+ }
+
+ PaUtil_GroupFreeMemory(auhalHostApi->allocations, scanDeviceInfosResults );
+ }
+
+ return paNoError;
+}
+
/*
- * $Id$
+ * $Id: pa_jack.c 1661 2011-04-28 18:54:46Z rob_bielik $
* PortAudio Portable Real-Time Audio Library
* Latest Version at: http://www.portaudio.com
* JACK Implementation by Joshua Haberman
/* Register functions */
+ (*hostApi)->ScanDeviceInfos = NULL;
+ (*hostApi)->CommitDeviceInfos = NULL;
+ (*hostApi)->DisposeDeviceInfos = NULL;
(*hostApi)->Terminate = Terminate;
(*hostApi)->OpenStream = OpenStream;
(*hostApi)->IsFormatSupported = IsFormatSupported;
minimum_buffer_frames = jackHostApi->jack_buffer_size * 3;
/* setup blocking API data structures (FIXME: can fail) */
- BlockingBegin( stream, minimum_buffer_frames );
+ BlockingBegin( stream, minimum_buffer_frames );
/* install our own callback for the blocking API */
streamCallback = BlockingCallback;
/*
- * $Id$
+ * $Id: pa_unix_oss.c 1661 2011-04-28 18:54:46Z rob_bielik $
* PortAudio Portable Real-Time Audio Library
* Latest Version at: http://www.portaudio.com
* OSS implementation by:
(*hostApi)->Terminate = Terminate;
(*hostApi)->OpenStream = OpenStream;
(*hostApi)->IsFormatSupported = IsFormatSupported;
+ (*hostApi)->ScanDeviceInfos = NULL;
+ (*hostApi)->CommitDeviceInfos = NULL;
+ (*hostApi)->DisposeDeviceInfos = NULL;
PA_ENSURE( BuildDeviceList( ossHostApi ) );
/*
- * $Id$
+ * $Id: pa_hostapi_skeleton.c 1661 2011-04-28 18:54:46Z rob_bielik $
* Portable Audio I/O Library skeleton implementation
* demonstrates how to use the common functions to implement support
* for a host API
}
}
+ (*hostApi)->ScanDeviceInfos = NULL;
+ (*hostApi)->CommitDeviceInfos = NULL;
+ (*hostApi)->DisposeDeviceInfos = NULL;
(*hostApi)->Terminate = Terminate;
(*hostApi)->OpenStream = OpenStream;
(*hostApi)->IsFormatSupported = IsFormatSupported;
+ (*hostApi)->ScanDeviceInfos = NULL;
+ (*hostApi)->CommitDeviceInfos = NULL;
+ (*hostApi)->DisposeDeviceInfos = NULL;
PaUtil_InitializeStreamInterface( &skeletonHostApi->callbackStreamInterface, CloseStream, StartStream,
StopStream, AbortStream, IsStreamStopped, IsStreamActive,
}\r
}\r
\r
+ (*hostApi)->ScanDeviceInfos = NULL;\r
+ (*hostApi)->CommitDeviceInfos = NULL;\r
+ (*hostApi)->DisposeDeviceInfos = NULL;\r
(*hostApi)->Terminate = Terminate;\r
(*hostApi)->OpenStream = OpenStream;\r
(*hostApi)->IsFormatSupported = IsFormatSupported;\r
/*
- * $Id$
+ * $Id: pa_win_wdmks.c 1661 2011-04-28 18:54:46Z rob_bielik $
* PortAudio Windows WDM-KS interface
*
* Author: Andrew Baldwin
(*hostApi)->info.deviceCount = deviceCount;
+ (*hostApi)->ScanDeviceInfos = NULL;
+ (*hostApi)->CommitDeviceInfos = NULL;
+ (*hostApi)->DisposeDeviceInfos = NULL;
(*hostApi)->Terminate = Terminate;
(*hostApi)->OpenStream = OpenStream;
(*hostApi)->IsFormatSupported = IsFormatSupported;
/* IMPLEMENT ME, see portaudio.h for required behavior*/
PA_LOGL_;
return 0;
-}
\ No newline at end of file
+}
--- /dev/null
+
+#include "pa_util.h"
+#include "pa_debugprint.h"
+#include "pa_allocation.h"
+
+#include <stdio.h>
+
+#include <AudioUnit/AudioUnit.h>
+#include <AudioToolbox/AudioToolbox.h>
+
+/* Implemented in pa_front.c
+ @param first 0 = unknown, 1 = insertion, 2 = removal
+ @param second Host specific device change info (in windows it is the (unicode) device path)
+*/
+extern void PaUtil_DevicesChanged(unsigned, void*);
+
+/* Callback for audio hardware property changes. */
+static OSStatus audioPropertyCallback(AudioHardwarePropertyID inPropertyID,
+ void *refCon)
+{
+ (void)refCon;
+ switch (inPropertyID)
+ {
+ /*
+ * These are the other types of notifications we might receive, however, they are beyond
+ * the scope of this sample and we ignore them.
+ */
+ case kAudioHardwarePropertyDefaultInputDevice:
+ PA_DEBUG(("audioPropertyCallback: default input device changed\n"));
+ break;
+ case kAudioHardwarePropertyDefaultOutputDevice:
+ PA_DEBUG(("audioPropertyCallback: default output device changed\n"));
+ break;
+ case kAudioHardwarePropertyDefaultSystemOutputDevice:
+ PA_DEBUG(("audioPropertyCallback: default system output device changed\n"));
+ break;
+ case kAudioHardwarePropertyDevices:
+ PA_DEBUG(("audioPropertyCallback: device list changed\n"));
+ PaUtil_DevicesChanged(1, NULL);
+ break;
+ default:
+ PA_DEBUG(("audioPropertyCallback: unknown message id=%08lx\n", inPropertyID));
+ break;
+ }
+
+ return noErr;
+}
+
+void PaUtil_InitializeHotPlug()
+{
+ AudioHardwareAddPropertyListener(kAudioHardwarePropertyDevices,
+ audioPropertyCallback, NULL);
+ AudioHardwareAddPropertyListener(kAudioHardwarePropertyDefaultInputDevice,
+ audioPropertyCallback, NULL);
+ AudioHardwareAddPropertyListener(kAudioHardwarePropertyDefaultOutputDevice,
+ audioPropertyCallback, NULL);
+}
+
+void PaUtil_TerminateHotPlug()
+{
+ AudioHardwareRemovePropertyListener(kAudioHardwarePropertyDevices,
+ audioPropertyCallback);
+ AudioHardwareRemovePropertyListener(kAudioHardwarePropertyDefaultInputDevice,
+ audioPropertyCallback);
+ AudioHardwareRemovePropertyListener(kAudioHardwarePropertyDefaultOutputDevice,
+ audioPropertyCallback);
+}
+
+void PaUtil_LockHotPlug()
+{
+}
+
+void PaUtil_UnlockHotPlug()
+{
+}
+
--- /dev/null
+
+#include "pa_util.h"
+#include "pa_debugprint.h"
+#include "pa_allocation.h"
+#include "pa_linux_alsa.h"
+#include "pa_hostapi.h"
+
+#include <alsa/asoundlib.h>
+
+#include <stdio.h>
+#include <signal.h>
+#include <pthread.h>
+
+/* Implemented in pa_front.c
+ @param first 0 = unknown, 1 = insertion, 2 = removal
+ @param second Host specific device change info (in windows it is the (unicode) device path)
+*/
+extern void PaUtil_DevicesChanged(unsigned, void*);
+
+static pthread_t g_thread_id;
+static pthread_mutex_t g_mutex;
+static volatile sig_atomic_t g_run = 0;
+
+static int device_list_size(void)
+{
+ snd_ctl_t *handle;
+ int card, err, dev, idx;
+ int nb = 0;
+ snd_ctl_card_info_t *info;
+ snd_pcm_info_t *pcminfo;
+ snd_ctl_card_info_alloca(&info);
+ snd_pcm_info_alloca(&pcminfo);
+
+ card = -1;
+ if (snd_card_next(&card) < 0 || card < 0)
+ {
+ return nb;
+ }
+
+ while (card >= 0)
+ {
+ char name[32];
+
+ sprintf(name, "hw:%d", card);
+ if ((err = snd_ctl_open(&handle, name, 0)) < 0)
+ {
+ goto next_card;
+ }
+ if ((err = snd_ctl_card_info(handle, info)) < 0)
+ {
+ snd_ctl_close(handle);
+ goto next_card;
+ }
+ dev = -1;
+ while (1)
+ {
+ unsigned int count;
+ int hasPlayback = 0;
+ int hasCapture = 0;
+
+ snd_ctl_pcm_next_device(handle, &dev);
+
+ if (dev < 0)
+ break;
+ snd_pcm_info_set_device(pcminfo, dev);
+ snd_pcm_info_set_subdevice(pcminfo, 0);
+ snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE);
+ if ((err = snd_ctl_pcm_info(handle, pcminfo)) >= 0)
+ {
+ hasCapture = 1;
+ }
+
+ snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK);
+ if ((err = snd_ctl_pcm_info(handle, pcminfo)) >= 0)
+ {
+ hasPlayback = 1;
+
+ count = snd_pcm_info_get_subdevices_count(pcminfo);
+ }
+
+ if(hasPlayback == 0 && hasCapture == 0)
+ continue;
+
+ nb++;
+ }
+ snd_ctl_close(handle);
+next_card:
+ if (snd_card_next(&card) < 0)
+ {
+ break;
+ }
+ }
+ return nb;
+}
+
+static void* thread_fcn(void* data)
+{
+ int currentDevices = 0;
+
+ currentDevices = device_list_size();
+
+ while(g_run)
+ {
+ int count = 0;
+
+ sleep(1);
+ count = device_list_size();
+ if(count != currentDevices)
+ {
+ /* 1 = add device, 2 = remove device */
+ int add = (count > currentDevices) ? 1 : 2;
+
+ currentDevices = count;
+
+ PaUtil_DevicesChanged(add, NULL);
+ }
+ }
+
+ return NULL;
+}
+
+void PaUtil_InitializeHotPlug()
+{
+ pthread_mutex_init(&g_mutex, NULL);
+ g_run = 1;
+ pthread_create(&g_thread_id, NULL, thread_fcn, NULL);
+}
+
+void PaUtil_TerminateHotPlug()
+{
+ void* ret = NULL;
+
+ g_run = 0;
+ pthread_join(g_thread_id, &ret);
+ pthread_mutex_destroy(&g_mutex);
+}
+
+void PaUtil_LockHotPlug()
+{
+ pthread_mutex_lock(&g_mutex);
+}
+
+void PaUtil_UnlockHotPlug()
+{
+ pthread_mutex_unlock(&g_mutex);
+}
+
/*
- * $Id$
+ * $Id: pa_win_hostapis.c 1661 2011-04-28 18:54:46Z rob_bielik $
* Portable Audio I/O Library Windows initialization table
*
* Based on the Open Source API proposed by Ross Bencina
#endif
#if PA_USE_WDMKS
- PaWinWdm_Initialize,
+ //PaWinWdm_Initialize,
#endif
#if PA_USE_SKELETON
{
PA_DEBUG(("Device inserted : %S\n", ptr->dbcc_name));
InsertDeviceIntoCache(pInfo, ptr->dbcc_name);
+ /* yield some seconds because added device may not be completely configured */
+ Sleep(2000);
PaUtil_DevicesChanged(1, ptr->dbcc_name);
}
}
if (RemoveDeviceFromCache(pInfo, ptr->dbcc_name))
{
PA_DEBUG(("Device removed : %S\n", ptr->dbcc_name));
+ Sleep(2000);
PaUtil_DevicesChanged(2, ptr->dbcc_name);
}
}
#include <stdio.h>
#include <assert.h>
+#include <unistd.h>
#include "portaudio.h"
for(;;){
printDevices();
-
+
printf( "press [enter] to update the device list. or q + [enter] to quit.\n" );
- if( getchar() == 'q' )
+ char ch = getchar();
+ if( ch == 'q' )
break;
Pa_UpdateAvailableDeviceList();