#include "pa_trace.h"
/************************************************* Constants ********/
+#define PA_TRACK_MEMORY (0)
+
#define PA_USE_TIMER_CALLBACK (0) /* Select between two options for background task. 0=thread, 1=timer */
#define PA_USE_HIGH_LATENCY (0) /* For debugging glitches. */
/* Switches for debugging. */
static int sPaHostError = 0;
static const char sMapperSuffixInput[] = " - Input";
static const char sMapperSuffixOutput[] = " - Output";
+static int sNumAllocations = 0;
+
/************************************************* Macros ********/
/* Convert external PA ID to an internal ID that includes WAVE_MAPPER */
#define PaDeviceIdToWinId(id) (((id) < sNumInputDevices) ? (id - 1) : (id - sNumInputDevices - 1))
static PaError PaHost_UpdateStreamTime( PaHostSoundControl *pahsc );
static PaError PaHost_BackgroundManager( internalPortAudioStream *past );
+static void *PaHost_AllocateTrackedMemory( long numBytes );
+static void PaHost_FreeTrackedMemory( void *addr );
+
/********************************* BEGIN CPU UTILIZATION MEASUREMENT ****/
static void Pa_StartUsageCalculation( internalPortAudioStream *past )
{
/* PLB20010402 - was allocating too much memory. */
/* numBytes = sNumDevices * sizeof(PaDeviceInfo); // PLB20010402 */
numBytes = sNumDevices * sizeof(PaDeviceInfo *); /* PLB20010402 */
- sDevicePtrs = (PaDeviceInfo **) GlobalAlloc( GPTR, numBytes ); /* MEM */
+ sDevicePtrs = (PaDeviceInfo **) PaHost_AllocateTrackedMemory( numBytes ); /* MEM */
if( sDevicePtrs == NULL ) return paInsufficientMemory;
return paNoError;
}
{
return sDevicePtrs[ id ];
}
- deviceInfo = (PaDeviceInfo *)GlobalAlloc( GPTR, sizeof(PaDeviceInfo) ); /* MEM */
+ deviceInfo = (PaDeviceInfo *)PaHost_AllocateTrackedMemory( sizeof(PaDeviceInfo) ); /* MEM */
if( deviceInfo == NULL ) return NULL;
deviceInfo->structVersion = 1;
deviceInfo->maxInputChannels = 0;
deviceInfo->maxOutputChannels = 0;
deviceInfo->numSampleRates = 0;
- sampleRates = (double*)GlobalAlloc( GPTR, MAX_NUMSAMPLINGRATES * sizeof(double) ); /* MEM */
+ sampleRates = (double*)PaHost_AllocateTrackedMemory( MAX_NUMSAMPLINGRATES * sizeof(double) ); /* MEM */
deviceInfo->sampleRates = sampleRates;
deviceInfo->nativeSampleFormats = paInt16; /* should query for higher bit depths below */
if( id < sNumInputDevices )
/* Append I/O suffix to WAVE_MAPPER device. */
if( inputMmID == WAVE_MAPPER )
{
- s = (char *) GlobalAlloc( GMEM_FIXED, strlen( wic.szPname ) + 1 + sizeof(sMapperSuffixInput) ); /* MEM */
+ s = (char *) PaHost_AllocateTrackedMemory( strlen( wic.szPname ) + 1 + sizeof(sMapperSuffixInput) ); /* MEM */
strcpy( s, wic.szPname );
strcat( s, sMapperSuffixInput );
}
else
{
- s = (char *) GlobalAlloc( GMEM_FIXED, strlen( wic.szPname ) + 1 ); /* MEM */
+ s = (char *) PaHost_AllocateTrackedMemory( strlen( wic.szPname ) + 1 ); /* MEM */
strcpy( s, wic.szPname );
}
deviceInfo->name = s;
/* Append I/O suffix to WAVE_MAPPER device. */
if( outputMmID == WAVE_MAPPER )
{
- s = (char *) GlobalAlloc( GMEM_FIXED, strlen( woc.szPname ) + 1 + sizeof(sMapperSuffixOutput) ); /* MEM */
+ s = (char *) PaHost_AllocateTrackedMemory( strlen( woc.szPname ) + 1 + sizeof(sMapperSuffixOutput) ); /* MEM */
strcpy( s, woc.szPname );
strcat( s, sMapperSuffixOutput );
}
else
{
- s = (char *) GlobalAlloc( GMEM_FIXED, strlen( woc.szPname ) + 1 ); /* MEM */
+ s = (char *) PaHost_AllocateTrackedMemory( strlen( woc.szPname ) + 1 ); /* MEM */
strcpy( s, woc.szPname );
}
deviceInfo->name = s;
sDevicePtrs[ id ] = deviceInfo;
return deviceInfo;
error:
- GlobalFree( sampleRates ); /* MEM */
- GlobalFree( deviceInfo ); /* MEM */
+ PaHost_FreeTrackedMemory( sampleRates ); /* MEM */
+ PaHost_FreeTrackedMemory( deviceInfo ); /* MEM */
return NULL;
}
*/
PaError PaHost_Init( void )
{
+
+#if PA_TRACK_MEMORY
+ PRINT(("PaHost_Init: sNumAllocations = %d\n", sNumAllocations ));
+#endif
+
#if PA_SIMULATE_UNDERFLOW
PRINT(("WARNING - Underflow Simulation Enabled - Expect a Big Glitch!!!\n"));
#endif
goto error;
}
/* Allocate an array to hold the buffer pointers. */
- pahsc->pahsc_InputBuffers = (WAVEHDR *) GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, sizeof(WAVEHDR)*pahsc->pahsc_NumHostBuffers ); /* MEM */
+ pahsc->pahsc_InputBuffers = (WAVEHDR *) PaHost_AllocateTrackedMemory( sizeof(WAVEHDR)*pahsc->pahsc_NumHostBuffers ); /* MEM */
if( pahsc->pahsc_InputBuffers == NULL )
{
result = paInsufficientMemory;
/* Allocate each buffer. */
for( i=0; i<pahsc->pahsc_NumHostBuffers; i++ )
{
- pahsc->pahsc_InputBuffers[i].lpData = (char *)GlobalAlloc( GMEM_FIXED, pahsc->pahsc_BytesPerHostInputBuffer ); /* MEM */
+ pahsc->pahsc_InputBuffers[i].lpData = (char *)PaHost_AllocateTrackedMemory( pahsc->pahsc_BytesPerHostInputBuffer ); /* MEM */
if( pahsc->pahsc_InputBuffers[i].lpData == NULL )
{
result = paInsufficientMemory;
goto error;
}
/* Allocate an array to hold the buffer pointers. */
- pahsc->pahsc_OutputBuffers = (WAVEHDR *) GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, sizeof(WAVEHDR)*pahsc->pahsc_NumHostBuffers ); /* MEM */
+ pahsc->pahsc_OutputBuffers = (WAVEHDR *) PaHost_AllocateTrackedMemory( sizeof(WAVEHDR)*pahsc->pahsc_NumHostBuffers ); /* MEM */
if( pahsc->pahsc_OutputBuffers == NULL )
{
result = paInsufficientMemory;
/* Allocate each buffer. */
for( i=0; i<pahsc->pahsc_NumHostBuffers; i++ )
{
- pahsc->pahsc_OutputBuffers[i].lpData = (char *) GlobalAlloc( GMEM_FIXED, pahsc->pahsc_BytesPerHostOutputBuffer ); /* MEM */
+ pahsc->pahsc_OutputBuffers[i].lpData = (char *) PaHost_AllocateTrackedMemory( pahsc->pahsc_BytesPerHostOutputBuffer ); /* MEM */
if( pahsc->pahsc_OutputBuffers[i].lpData == NULL )
{
result = paInsufficientMemory;
for( i=0; i<pahsc->pahsc_NumHostBuffers; i++ )
{
waveOutUnprepareHeader( pahsc->pahsc_HWaveOut, &pahsc->pahsc_OutputBuffers[i], sizeof(WAVEHDR) );
- GlobalFree( pahsc->pahsc_OutputBuffers[i].lpData ); /* MEM */
+ PaHost_FreeTrackedMemory( pahsc->pahsc_OutputBuffers[i].lpData ); /* MEM */
}
- GlobalFree( pahsc->pahsc_OutputBuffers ); /* MEM */
+ PaHost_FreeTrackedMemory( pahsc->pahsc_OutputBuffers ); /* MEM */
}
waveOutClose( pahsc->pahsc_HWaveOut );
}
for( i=0; i<pahsc->pahsc_NumHostBuffers; i++ )
{
waveInUnprepareHeader( pahsc->pahsc_HWaveIn, &pahsc->pahsc_InputBuffers[i], sizeof(WAVEHDR) );
- GlobalFree( pahsc->pahsc_InputBuffers[i].lpData ); /* MEM */
+ PaHost_FreeTrackedMemory( pahsc->pahsc_InputBuffers[i].lpData ); /* MEM */
}
- GlobalFree( pahsc->pahsc_InputBuffers ); /* MEM */
+ PaHost_FreeTrackedMemory( pahsc->pahsc_InputBuffers ); /* MEM */
}
waveInClose( pahsc->pahsc_HWaveIn );
}
{
if( sDevicePtrs[i] != NULL )
{
- GlobalFree( (char*)sDevicePtrs[i]->name ); /* MEM */
- GlobalFree( (void*)sDevicePtrs[i]->sampleRates ); /* MEM */
- GlobalFree( sDevicePtrs[i] ); /* MEM */
+ PaHost_FreeTrackedMemory( (char*)sDevicePtrs[i]->name ); /* MEM */
+ PaHost_FreeTrackedMemory( (void*)sDevicePtrs[i]->sampleRates ); /* MEM */
+ PaHost_FreeTrackedMemory( sDevicePtrs[i] ); /* MEM */
}
}
- GlobalFree( sDevicePtrs ); /* MEM */
+ PaHost_FreeTrackedMemory( sDevicePtrs ); /* MEM */
sDevicePtrs = NULL;
}
sNumDevices = 0;
}
+
+#if PA_TRACK_MEMORY
+ PRINT(("PaHost_Term: sNumAllocations = %d\n", sNumAllocations ));
+#endif
+
return paNoError;
}
/*************************************************************************/
*/
void *PaHost_AllocateFastMemory( long numBytes )
{
- void *addr = GlobalAlloc( GPTR, numBytes ); /* FIXME - do we need physical memory? Use VirtualLock() */ /* MEM */
- return addr;
+ return PaHost_AllocateTrackedMemory( numBytes ); /* FIXME - do we need physical memory? Use VirtualLock() */ /* MEM */
}
/*************************************************************************
* Free memory that could be accessed in real-time.
*/
void PaHost_FreeFastMemory( void *addr, long numBytes )
{
- if( addr != NULL ) GlobalFree( addr ); /* MEM */
+ PaHost_FreeTrackedMemory( addr ); /* MEM */
}
+
+/*************************************************************************
+ * Track memory allocations to avoid leaks.
+ */
+static void *PaHost_AllocateTrackedMemory( long numBytes )
+{
+ void *addr = GlobalAlloc( GPTR, numBytes ); /* MEM */
+#if PA_TRACK_MEMORY
+ if( addr != NULL ) sNumAllocations += 1;
+#endif
+ return addr;
+}
+
+static void PaHost_FreeTrackedMemory( void *addr )
+{
+ if( addr != NULL )
+ {
+ GlobalFree( addr ); /* MEM */
+#if PA_TRACK_MEMORY
+ sNumAllocations -= 1;
+#endif
+ }
+}
+
/***********************************************************************/
PaError PaHost_StreamActive( internalPortAudioStream *past )
{