StopStream
CloseStream
ReadStream
WriteStream
    
155a156,158
> #define DRV_QUERYFUNCTIONINSTANCEID     (DRV_RESERVED + 17)
> #define DRV_QUERYFUNCTIONINSTANCEIDSIZE (DRV_RESERVED + 18)
> 
180c183
< 
---
> #define PA_MME_MAX_TIMEOUT_MSEC_        (2000)
244a248,250
> 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 );
379a386,471
> /**
>  * Sets the <tt>transportType</tt> of a specific <tt>PaDeviceInfo</tt>.
>  *
>  * @param winMmeDeviceId
>  * @param deviceInfo the <tt>PaDeviceInfo</tt> to set the <tt>transportType</tt>
>  * of
>  */
> static void
> SetDeviceInfoTransportType(UINT winMmeDeviceId, PaDeviceInfo *deviceInfo)
> {
>     deviceInfo->transportType = NULL;
> 
> #ifdef PAWIN_USE_WDMKS_DEVICE_INFO
>     if (!(deviceInfo->transportType))
>     {
>         DWORD deviceInterfaceSize;
>         LPWSTR deviceInterface = NULL;
> 
>         if (deviceInfo->maxInputChannels > 0)
>         {
>             if (waveInMessage(
>                         (HWAVEIN)winMmeDeviceId,
>                         DRV_QUERYDEVICEINTERFACESIZE,
>                         (DWORD_PTR)&deviceInterfaceSize,
>                         0)
>                     == MMSYSERR_NOERROR)
>             {
>                 deviceInterface = PaUtil_AllocateMemory(deviceInterfaceSize);
>                 if (deviceInterface
>                         && (waveInMessage(
>                                     (HWAVEIN)winMmeDeviceId,
>                                     DRV_QUERYDEVICEINTERFACE,
>                                     (DWORD_PTR)deviceInterface,
>                                     deviceInterfaceSize)
>                                 != MMSYSERR_NOERROR))
>                 {
>                     PaUtil_FreeMemory(deviceInterface);
>                     deviceInterface = NULL;
>                 }
>             }
>         }
>         else if (deviceInfo->maxOutputChannels > 0)
>         {
>             if (waveOutMessage(
>                         (HWAVEOUT)winMmeDeviceId,
>                         DRV_QUERYDEVICEINTERFACESIZE,
>                         (DWORD_PTR)&deviceInterfaceSize,
>                         0)
>                     == MMSYSERR_NOERROR)
>             {
>                 deviceInterface = PaUtil_AllocateMemory(deviceInterfaceSize);
>                 if (deviceInterface
>                         && (waveOutMessage(
>                                     (HWAVEOUT)winMmeDeviceId,
>                                     DRV_QUERYDEVICEINTERFACE,
>                                     (DWORD_PTR)deviceInterface,
>                                     deviceInterfaceSize)
>                                 != MMSYSERR_NOERROR))
>                 {
>                     PaUtil_FreeMemory(deviceInterface);
>                     deviceInterface = NULL;
>                 }
>             }
>         }
>         if (deviceInterface)
>         {
>             if (wcsstr(deviceInterface, L"\\usb#")
>                     || wcsstr(deviceInterface, L"\\USB#"))
>                 deviceInfo->transportType = "USB";
>             PaUtil_FreeMemory(deviceInterface);
>         }
>     }
> #endif /* #ifdef PAWIN_USE_WDMKS_DEVICE_INFO */
> 
>     /*
>      * As a last resort, attempt to make a decision about the transportType
>      * based on the name of the specified deviceInfo.
>      */
>     if (!(deviceInfo->transportType))
>     {
>         const char *s = deviceInfo->name;
> 
>         if (s && (s = strrchr(s,'(')) && (s = strstr(s,"USB")) && strchr(s,')'))
>             deviceInfo->transportType = "USB";
>     }
> }
398a491,492
> 
>     //char comWasInitialized;
411a506,513
> typedef struct PaWinMmeScanDeviceInfosResults{ /* used for tranferring device infos during scanning / rescanning */
>     PaDeviceInfo **deviceInfos;
>     PaDeviceIndex defaultInputDevice;
>     PaDeviceIndex defaultOutputDevice;
> 
>     int inputDeviceCount, outputDeviceCount;
> 
> } PaWinMmeScanDeviceInfosResults;
667a770
>     char *deviceUID;
673a777,782
>     /* We do not want Microsoft's Sound Mapper because it is a virtual device
>      * and we want the real (hardware) devices only.
>      */
>     if (WAVE_MAPPER == winMmeInputDeviceId)
>         return paNoError;
> 
739a849,893
>     /* transportType */
>     SetDeviceInfoTransportType(winMmeInputDeviceId, deviceInfo);
> 
>     MMRESULT mmr;
>     size_t cbEndpointIdSize;
>     // Get the size (including the terminating null) of
>     // the endpoint ID string of the waveOut device.
>     mmr = waveInMessage(
>         winMmeInputDeviceId,
>         DRV_QUERYFUNCTIONINSTANCEIDSIZE,
>         (DWORD_PTR)&cbEndpointIdSize, NULL);
> 
>     if (mmr == MMSYSERR_NOERROR)  // do sizes match?
>     {
>         WCHAR *pstrEndpointId = NULL;
>         pstrEndpointId = (WCHAR *)PaUtil_GroupAllocateMemory(winMmeHostApi->allocations, cbEndpointIdSize);
> 
>         // Get the endpoint ID string for this waveOut device.
>         mmr = waveInMessage(
>             winMmeInputDeviceId,
>             DRV_QUERYFUNCTIONINSTANCEID,
>             (DWORD_PTR)pstrEndpointId,
>             cbEndpointIdSize);
> 
>         if (mmr == MMSYSERR_NOERROR)
>         {
>             deviceUID = (char *)PaUtil_GroupAllocateMemory(winMmeHostApi->allocations, wcslen(pstrEndpointId));
>             if( !deviceUID )
>             {
>                 result = paInsufficientMemory;
>                 goto error;
>             }
>             wcstombs(deviceUID, pstrEndpointId, sizeof(deviceUID));
>             WideCharToMultiByte( CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,\
>                     pstrEndpointId, -1, deviceUID, wcslen(pstrEndpointId), NULL, NULL );
>             deviceInfo->deviceUID = deviceUID;
>         }
>         /*else
>         {
>             char mmeErrorText[ MAXERRORLENGTH ];
>             waveOutGetErrorText( mmr, mmeErrorText, MAXERRORLENGTH );  
>             PA_DEBUG(("Error %i: %s\n", mmr ,mmeErrorText));
>         }*/
>     }
> 
790a945
>     char *deviceUID;
797a953,958
>     /* We do not want Microsoft's Sound Mapper because it is a virtual device
>      * and we want the real (hardware) devices only.
>      */
>     if (WAVE_MAPPER == winMmeOutputDeviceId)
>         return paNoError;
> 
865a1027,1072
>     /* transportType */
>     SetDeviceInfoTransportType(winMmeOutputDeviceId, deviceInfo);
> 
>     MMRESULT mmr;
>     size_t cbEndpointIdSize;
>     // Get the size (including the terminating null) of
>     // the endpoint ID string of the waveOut device.
>     mmr = waveOutMessage(
>         winMmeOutputDeviceId,
>         DRV_QUERYFUNCTIONINSTANCEIDSIZE,
>         (DWORD_PTR)&cbEndpointIdSize, NULL);
> 
>     if (mmr == MMSYSERR_NOERROR)  // do sizes match?
>     {
>         WCHAR *pstrEndpointId = NULL;
>         pstrEndpointId = (WCHAR *)PaUtil_GroupAllocateMemory(winMmeHostApi->allocations, cbEndpointIdSize);
> 
>         // Get the endpoint ID string for this waveOut device.
>         mmr = waveOutMessage(
>             winMmeOutputDeviceId,
>             DRV_QUERYFUNCTIONINSTANCEID,
>             (DWORD_PTR)pstrEndpointId,
>             cbEndpointIdSize);
> 
>         if (mmr == MMSYSERR_NOERROR)
>         {
>             deviceUID = (char *)PaUtil_GroupAllocateMemory(winMmeHostApi->allocations, wcslen(pstrEndpointId));
>             if( !deviceUID )
>             {
>                 result = paInsufficientMemory;
>                 goto error;
>             }
>             wcstombs(deviceUID, pstrEndpointId, sizeof(deviceUID));
> 
>             WideCharToMultiByte( CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,\
>                     pstrEndpointId, -1, deviceUID, wcslen(pstrEndpointId), NULL, NULL );
>             deviceInfo->deviceUID = deviceUID;
>         }
>         /*else
>         {
>             char mmeErrorText[ MAXERRORLENGTH ];
>             waveOutGetErrorText( mmr, mmeErrorText, MAXERRORLENGTH );  
>             PA_DEBUG(("Error %i: %s\n", mmr ,mmeErrorText));
>         }*/
>     }
> 
905c1112
<     int i;
---
>     int deviceCount;
907,912c1114,1115
<     int inputDeviceCount, outputDeviceCount, maximumPossibleDeviceCount;
<     PaWinMmeDeviceInfo *deviceInfoArray;
<     int deviceInfoInitializationSucceeded;
<     PaTime defaultLowLatency, defaultHighLatency;
<     DWORD waveInPreferredDevice, waveOutPreferredDevice;
<     DWORD preferredDeviceStatusFlags;
---
>     //char comWasInitialized = 1;
>     void *scanResults = 0;
920a1124,1125
>     //winMmeHostApi->comWasInitialized = comWasInitialized;
> 
933d1137
<     
937a1142
>     /* these are all updated by CommitDeviceInfos() */
944,1082c1149,1152
< #if !defined(DRVM_MAPPER_PREFERRED_GET)
< /* DRVM_MAPPER_PREFERRED_GET is defined in mmddk.h but we avoid a dependency on the DDK by defining it here */
< #define DRVM_MAPPER_PREFERRED_GET    (0x2000+21)
< #endif
< 
<     /* the following calls assume that if wave*Message fails the preferred device parameter won't be modified */
<     preferredDeviceStatusFlags = 0;
<     waveInPreferredDevice = -1;
<     waveInMessage( (HWAVEIN)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR)&waveInPreferredDevice, (DWORD_PTR)&preferredDeviceStatusFlags );
< 
<     preferredDeviceStatusFlags = 0;
<     waveOutPreferredDevice = -1;
<     waveOutMessage( (HWAVEOUT)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR)&waveOutPreferredDevice, (DWORD_PTR)&preferredDeviceStatusFlags );
< 
<     maximumPossibleDeviceCount = 0;
< 
<     inputDeviceCount = waveInGetNumDevs();
<     if( inputDeviceCount > 0 )
<     	maximumPossibleDeviceCount += inputDeviceCount + 1;	/* assume there is a WAVE_MAPPER */
< 
<     outputDeviceCount = waveOutGetNumDevs();
<     if( outputDeviceCount > 0 )
< 	    maximumPossibleDeviceCount += outputDeviceCount + 1;	/* assume there is a WAVE_MAPPER */
< 
< 
<     if( maximumPossibleDeviceCount > 0 ){
< 
<         (*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
<                 winMmeHostApi->allocations, sizeof(PaDeviceInfo*) * maximumPossibleDeviceCount );
<         if( !(*hostApi)->deviceInfos )
<         {
<             result = paInsufficientMemory;
<             goto error;
<         }
< 
<         /* allocate all device info structs in a contiguous block */
<         deviceInfoArray = (PaWinMmeDeviceInfo*)PaUtil_GroupAllocateMemory(
<                 winMmeHostApi->allocations, sizeof(PaWinMmeDeviceInfo) * maximumPossibleDeviceCount );
<         if( !deviceInfoArray )
<         {
<             result = paInsufficientMemory;
<             goto error;
<         }
< 
<         winMmeHostApi->winMmeDeviceIds = (UINT*)PaUtil_GroupAllocateMemory(
<                 winMmeHostApi->allocations, sizeof(int) * maximumPossibleDeviceCount );
<         if( !winMmeHostApi->winMmeDeviceIds )
<         {
<             result = paInsufficientMemory;
<             goto error;
<         }
< 
<         GetDefaultLatencies( &defaultLowLatency, &defaultHighLatency );
< 
<         if( inputDeviceCount > 0 ){
<             /* -1 is the WAVE_MAPPER */
<             for( i = -1; i < inputDeviceCount; ++i ){
<                 UINT winMmeDeviceId = (UINT)((i==-1) ? WAVE_MAPPER : i);
<                 PaWinMmeDeviceInfo *wmmeDeviceInfo = &deviceInfoArray[ (*hostApi)->info.deviceCount ];
<                 PaDeviceInfo *deviceInfo = &wmmeDeviceInfo->inheritedDeviceInfo;
<                 deviceInfo->structVersion = 2;
<                 deviceInfo->hostApi = hostApiIndex;
< 
<                 deviceInfo->maxInputChannels = 0;
<                 wmmeDeviceInfo->deviceInputChannelCountIsKnown = 1;
<                 deviceInfo->maxOutputChannels = 0;
<                 wmmeDeviceInfo->deviceOutputChannelCountIsKnown = 1;
< 
<                 deviceInfo->defaultLowInputLatency = defaultLowLatency;
<                 deviceInfo->defaultLowOutputLatency = defaultLowLatency;
<                 deviceInfo->defaultHighInputLatency = defaultHighLatency;
<                 deviceInfo->defaultHighOutputLatency = defaultHighLatency;
< 
<                 result = InitializeInputDeviceInfo( winMmeHostApi, wmmeDeviceInfo,
<                         winMmeDeviceId, &deviceInfoInitializationSucceeded );
<                 if( result != paNoError )
<                     goto error;
< 
<                 if( deviceInfoInitializationSucceeded ){
<                     if( (*hostApi)->info.defaultInputDevice == paNoDevice ){
<                         /* if there is currently no default device, use the first one available */
<                         (*hostApi)->info.defaultInputDevice = (*hostApi)->info.deviceCount;
<                     
<                     }else if( winMmeDeviceId == waveInPreferredDevice ){
<                         /* set the default device to the system preferred device */
<                         (*hostApi)->info.defaultInputDevice = (*hostApi)->info.deviceCount;
<                     }
< 
<                     winMmeHostApi->winMmeDeviceIds[ (*hostApi)->info.deviceCount ] = winMmeDeviceId;
<                     (*hostApi)->deviceInfos[ (*hostApi)->info.deviceCount ] = deviceInfo;
< 
<                     winMmeHostApi->inputDeviceCount++;
<                     (*hostApi)->info.deviceCount++;
<                 }
<             }
<         }
< 
<         if( outputDeviceCount > 0 ){
<             /* -1 is the WAVE_MAPPER */
<             for( i = -1; i < outputDeviceCount; ++i ){
<                 UINT winMmeDeviceId = (UINT)((i==-1) ? WAVE_MAPPER : i);
<                 PaWinMmeDeviceInfo *wmmeDeviceInfo = &deviceInfoArray[ (*hostApi)->info.deviceCount ];
<                 PaDeviceInfo *deviceInfo = &wmmeDeviceInfo->inheritedDeviceInfo;
<                 deviceInfo->structVersion = 2;
<                 deviceInfo->hostApi = hostApiIndex;
< 
<                 deviceInfo->maxInputChannels = 0;
<                 wmmeDeviceInfo->deviceInputChannelCountIsKnown = 1;
<                 deviceInfo->maxOutputChannels = 0;
<                 wmmeDeviceInfo->deviceOutputChannelCountIsKnown = 1;
< 
<                 deviceInfo->defaultLowInputLatency = defaultLowLatency;
<                 deviceInfo->defaultLowOutputLatency = defaultLowLatency;
<                 deviceInfo->defaultHighInputLatency = defaultHighLatency;
<                 deviceInfo->defaultHighOutputLatency = defaultHighLatency; 
< 
<                 result = InitializeOutputDeviceInfo( winMmeHostApi, wmmeDeviceInfo,
<                         winMmeDeviceId, &deviceInfoInitializationSucceeded );
<                 if( result != paNoError )
<                     goto error;
< 
<                 if( deviceInfoInitializationSucceeded ){
<                     if( (*hostApi)->info.defaultOutputDevice == paNoDevice ){
<                         /* if there is currently no default device, use the first one available */
<                         (*hostApi)->info.defaultOutputDevice = (*hostApi)->info.deviceCount;
< 
<                     }else if( winMmeDeviceId == waveOutPreferredDevice ){
<                         /* set the default device to the system preferred device */
<                         (*hostApi)->info.defaultOutputDevice = (*hostApi)->info.deviceCount;
<                     }
< 
<                     winMmeHostApi->winMmeDeviceIds[ (*hostApi)->info.deviceCount ] = winMmeDeviceId;
<                     (*hostApi)->deviceInfos[ (*hostApi)->info.deviceCount ] = deviceInfo;
< 
<                     winMmeHostApi->outputDeviceCount++;
<                     (*hostApi)->info.deviceCount++;
<                 }
<             }
<         }
---
>     result = ScanDeviceInfos( &winMmeHostApi->inheritedHostApiRep, hostApiIndex, &scanResults, &deviceCount );
>     if( result != paNoError )
>     {
>         goto error;
1084,1085c1154,1156
<     
<     InitializeDefaultDeviceIdsFromEnv( winMmeHostApi );
---
> 
>     /* FIXME for now we ignore the result of CommitDeviceInfos(), it should probably be an atomic non-failing operation */
>     CommitDeviceInfos( &winMmeHostApi->inheritedHostApiRep, hostApiIndex, scanResults, deviceCount );
1090,1092c1161,1163
<     (*hostApi)->ScanDeviceInfos = 0;
<     (*hostApi)->CommitDeviceInfos = 0;
<     (*hostApi)->DisposeDeviceInfos = 0;
---
>     (*hostApi)->ScanDeviceInfos = ScanDeviceInfos;
>     (*hostApi)->CommitDeviceInfos = CommitDeviceInfos;
>     (*hostApi)->DisposeDeviceInfos = DisposeDeviceInfos;
1289c1360
<                 
---
> 
1328a1400,1689
> /***********************************************************************************/
> static PaError ScanDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex hostApiIndex, void **scanResults, int *newDeviceCount )
> {
>     PaWinMmeHostApiRepresentation *winMmeHostApi = (PaWinMmeHostApiRepresentation*)hostApi;
>     PaWinMmeDeviceInfo *deviceInfoArray;
>     //char comWasInitialized = winMmeHostApi->comWasInitialized;
>     PaError result = paNoError;
>     PaWinMmeScanDeviceInfosResults *outArgument = 0;
>     //DSDeviceNamesAndGUIDs deviceNamesAndGUIDs;
>     int i = 0;
>     int maximumPossibleDeviceCount = 0;
> 
>     int inputDeviceCount, outputDeviceCount;
>     int deviceInfoInitializationSucceeded;
>     PaTime defaultLowLatency, defaultHighLatency;
> 
>     DWORD waveInPreferredDevice, waveOutPreferredDevice;
>     DWORD preferredDeviceStatusFlags;
> 
>     // Check preconditions
>     if( /*!comWasInitialized ||*/ scanResults == NULL || newDeviceCount == NULL )
>        return paInternalError;
> 
>     /* initialize the out params */
>     *scanResults = NULL;
>     *newDeviceCount = 0;
> 
> #if !defined(DRVM_MAPPER_PREFERRED_GET)
> /* DRVM_MAPPER_PREFERRED_GET is defined in mmddk.h but we avoid a dependency on the DDK by defining it here */
> #define DRVM_MAPPER_PREFERRED_GET    (0x2000+21)
> #endif
> 
>     /* the following calls assume that if wave*Message fails the preferred device parameter won't be modified */
>     preferredDeviceStatusFlags = 0;
>     waveInPreferredDevice = -1;
>     waveInMessage( (HWAVEIN)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR)&waveInPreferredDevice, (DWORD_PTR)&preferredDeviceStatusFlags );
> 
>     preferredDeviceStatusFlags = 0;
>     waveOutPreferredDevice = -1;
>     waveOutMessage( (HWAVEOUT)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR)&waveOutPreferredDevice, (DWORD_PTR)&preferredDeviceStatusFlags );
> 
>     maximumPossibleDeviceCount = 0;
> 
>     inputDeviceCount = waveInGetNumDevs();
>     if( inputDeviceCount > 0 )
>         maximumPossibleDeviceCount += inputDeviceCount + 1; // assume there is a WAVE_MAPPER
> 
>     outputDeviceCount = waveOutGetNumDevs();
>     if( outputDeviceCount > 0 )
>         maximumPossibleDeviceCount += outputDeviceCount + 1;// assume there is a WAVE_MAPPER
> 
>     if( maximumPossibleDeviceCount > 0 )
>     {
>         /* Allocate the out param for all the info we need */
>         outArgument = (PaWinMmeScanDeviceInfosResults *) PaUtil_GroupAllocateMemory(
>                         winMmeHostApi->allocations, sizeof(PaWinMmeScanDeviceInfosResults) );
>         if( !outArgument )
>         {
>             result = paInsufficientMemory;
>             goto error;
>         }
> 
>         /* allocate array for pointers to PaDeviceInfo structs */
>         outArgument->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
>                 winMmeHostApi->allocations, sizeof(PaDeviceInfo*) * maximumPossibleDeviceCount );
>         if( !outArgument->deviceInfos )
>         {
>             result = paInsufficientMemory;
>             goto error;
>         }
> 
>         // allocate all device info structs in a contiguous block
>         deviceInfoArray = (PaWinMmeDeviceInfo*)PaUtil_GroupAllocateMemory(
>                 winMmeHostApi->allocations, sizeof(PaWinMmeDeviceInfo) * maximumPossibleDeviceCount );
>         if( !deviceInfoArray )
>         {
>             result = paInsufficientMemory;
>             goto error;
>         }
> 
>         winMmeHostApi->winMmeDeviceIds = (UINT*)PaUtil_GroupAllocateMemory(
>                 winMmeHostApi->allocations, sizeof(int) * maximumPossibleDeviceCount );
>         if( !winMmeHostApi->winMmeDeviceIds )
>         {
>             result = paInsufficientMemory;
>             goto error;
>         }
> 
>         for( i = 0 ; i < maximumPossibleDeviceCount; ++i )
>         {
>             PaWinMmeDeviceInfo *wmmeDeviceInfo = &deviceInfoArray[i];
>             PaDeviceInfo *deviceInfo  = &wmmeDeviceInfo->inheritedDeviceInfo;
> 
>             deviceInfo->structVersion     = 3;
>             deviceInfo->hostApi           = hostApiIndex;
>             deviceInfo->name              = 0;
>             /*
>              * The fields maxInputChannels and maxOutputChannels used to be
>              * initialized in each of the loops bellow to the effect of the
>              * second loop overwriting/throwing away the results of the first
>              * loop. In order to resolve the described issue, the initialization
>              * of the two fields in question has been moved here.
>              */
>             deviceInfo->maxInputChannels  = 0;
>             deviceInfo->maxOutputChannels = 0;
>             /*
>              * The fields defaultLowInputLatency, defaultLowOutputLatency,
>              * defaultHighInputLatency and defaultHighOutputLatency used to be
>              * initialized in each of the loops bellow. For the sake of clarity,
>              * their initialization has been moved here.
>              */
>             deviceInfo->defaultLowInputLatency = defaultLowLatency;
>             deviceInfo->defaultLowOutputLatency = defaultLowLatency;
>             deviceInfo->defaultHighInputLatency = defaultHighLatency;
>             deviceInfo->defaultHighOutputLatency = defaultHighLatency;
> 
>             /*
>              * The fields deviceInputChannelCountIsKnown and
>              * deviceOutputChannelCountIsKnown used to be initialized in each of
>              * the loops bellow to the effect of the second loop
>              * overwriting/throwing away the results of the first loop. In order
>              * to resolve the described issue, the initialization of the two
>              * fields in question has been moved here.
>              */
>             wmmeDeviceInfo->deviceInputChannelCountIsKnown  = 0;
>             wmmeDeviceInfo->deviceOutputChannelCountIsKnown = 0;
> 
>             outArgument->deviceInfos[ i ] = deviceInfo;
>         }
>         outArgument->inputDeviceCount = 0;
>         outArgument->outputDeviceCount = 0;
> 
>         GetDefaultLatencies( &defaultLowLatency, &defaultHighLatency );
> 
>         if( inputDeviceCount > 0 )
>         {
>             // -1 is the WAVE_MAPPER
>             for( i = -1; i < inputDeviceCount; ++i )
>             {
>                 UINT winMmeDeviceId = (UINT)((i==-1) ? WAVE_MAPPER : i);
>                 PaWinMmeDeviceInfo *wmmeDeviceInfo = (PaWinMmeDeviceInfo*)outArgument->deviceInfos[*newDeviceCount];
>                 PaDeviceInfo *deviceInfo = &wmmeDeviceInfo->inheritedDeviceInfo;
> 
>                 result = InitializeInputDeviceInfo( winMmeHostApi, wmmeDeviceInfo,
>                         winMmeDeviceId, &deviceInfoInitializationSucceeded );
>                 /* ignore error results here and just skip the device */
>                 if( result != paNoError )
>                     continue;
> 
>                 if( deviceInfoInitializationSucceeded )
>                 {
>                     if( outArgument->defaultInputDevice == paNoDevice )
>                     {
>                         // if there is currently no default device, use the first one available
>                         outArgument->defaultInputDevice = *newDeviceCount;
> 
>                     }
>                     else if( winMmeDeviceId == waveInPreferredDevice )
>                     {
>                         // set the default device to the system preferred device
>                         outArgument->defaultInputDevice = *newDeviceCount;
>                     }
> 
>                     winMmeHostApi->winMmeDeviceIds[ *newDeviceCount ] = winMmeDeviceId;
>                     outArgument->inputDeviceCount++;
>                     (*newDeviceCount)++;
>                 }
>             }
>         }
> 
>         if( outputDeviceCount > 0 )
>         {
>             // -1 is the WAVE_MAPPER
>             for( i = -1; i < outputDeviceCount; ++i )
>             {
>                 UINT winMmeDeviceId = (UINT)((i==-1) ? WAVE_MAPPER : i);
>                 PaWinMmeDeviceInfo *wmmeDeviceInfo = (PaWinMmeDeviceInfo*)outArgument->deviceInfos[*newDeviceCount];
>                 PaDeviceInfo *deviceInfo = &wmmeDeviceInfo->inheritedDeviceInfo;
> 
>                 result = InitializeOutputDeviceInfo( winMmeHostApi, wmmeDeviceInfo,
>                         winMmeDeviceId, &deviceInfoInitializationSucceeded );
>                 /* ignore error results here and just skip the device */
>                 if( result != paNoError )
>                     continue;
> 
>                 if( deviceInfoInitializationSucceeded )
>                 {
>                     if( outArgument->defaultOutputDevice == paNoDevice )
>                     {
>                         // if there is currently no default device, use the first one available
>                         outArgument->defaultOutputDevice = *newDeviceCount;
> 
>                     }
>                     else if( winMmeDeviceId == waveOutPreferredDevice )
>                     {
>                         // set the default device to the system preferred device
>                         outArgument->defaultOutputDevice = *newDeviceCount;
>                     }
> 
>                     winMmeHostApi->winMmeDeviceIds[ *newDeviceCount ] = winMmeDeviceId;
>                     outArgument->outputDeviceCount++;
>                     (*newDeviceCount)++;
>                 }
>             }
>         }
>     }
> 
>     InitializeDefaultDeviceIdsFromEnv( winMmeHostApi );
>     *scanResults = outArgument;
> 
>     return result;
> error:
> 
>     if( outArgument )
>     {
>         if( outArgument->deviceInfos )
>         {
>             if( outArgument->deviceInfos[0] )
>             {
>                 PaUtil_GroupFreeMemory( winMmeHostApi->allocations, outArgument->deviceInfos[0] );
>             }
> 
>             PaUtil_GroupFreeMemory( winMmeHostApi->allocations, outArgument->deviceInfos );
>         }
>     }
> 
>     return result;
> }
> 
> static PaError CommitDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index, void *scanResults, int deviceCount )
> {
>     PaWinMmeHostApiRepresentation *winMmeHostApi = (PaWinMmeHostApiRepresentation*)hostApi;
>     PaError result = paNoError;
>     int i = 0;
> 
>     hostApi->info.deviceCount = 0;
>     hostApi->info.defaultInputDevice = paNoDevice;
>     hostApi->info.defaultOutputDevice = paNoDevice;
> 
>     /* Free any old memory which might be in the device info */
>     if( hostApi->deviceInfos )
>     {
>         PaUtil_GroupFreeMemory( winMmeHostApi->allocations, hostApi->deviceInfos[0] );
>         PaUtil_GroupFreeMemory( winMmeHostApi->allocations, hostApi->deviceInfos );
>         hostApi->deviceInfos = NULL;
>     }
> 
>     if( scanResults != NULL )
>     {
>         PaWinMmeScanDeviceInfosResults *scanDeviceInfosResults = ( PaWinMmeScanDeviceInfosResults * ) 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;
> 
>             winMmeHostApi->inputDeviceCount  = scanDeviceInfosResults->inputDeviceCount;
>             winMmeHostApi->outputDeviceCount  = scanDeviceInfosResults->outputDeviceCount;
>         }
> 
>         PaUtil_GroupFreeMemory( winMmeHostApi->allocations, scanDeviceInfosResults );
>     }
> 
>     return result;
> }
> 
> static PaError DisposeDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, void *scanResults, int deviceCount )
> {
>     PaWinMmeHostApiRepresentation *winMmeHostApi = (PaWinMmeHostApiRepresentation*)hostApi;
> 
>     if( scanResults != NULL )
>     {
>         PaWinMmeScanDeviceInfosResults *scanDeviceInfosResults = ( PaWinMmeScanDeviceInfosResults * ) scanResults;
> 
>         if( scanDeviceInfosResults->deviceInfos )
>         {
>             PaUtil_GroupFreeMemory( winMmeHostApi->allocations, scanDeviceInfosResults->deviceInfos[0] ); // all device info structs are allocated in a block so we can destroy them here 
>             PaUtil_GroupFreeMemory( winMmeHostApi->allocations, scanDeviceInfosResults->deviceInfos );
>         }
> 
>         PaUtil_GroupFreeMemory( winMmeHostApi->allocations, scanDeviceInfosResults );
>     }
> 
>     return paNoError;
> }
1329a1691
> /***********************************************************************************/
3397c3759
<     int timeout;
---
>     DWORD timeout;
3418c3780
<         timeout = (int)(stream->allBuffersDurationMs * 1.5);
---
>         timeout = (DWORD)(stream->allBuffersDurationMs * 1.5);
3446a3809,3814
>             /* If WaitForSingleObject starts repetitively and consecutively
>                returning WAIT_TIMEOUT, do eventually give up. Otherwise, the
>                method may never return.
>             */
>             DWORD totalTimeout;
> 
3486a3855
>             totalTimeout = 0;
3497c3866,3875
<                     /* keep waiting */
---
>                     /* Keep waiting. However, testing has shown that it is
>                        possible to unplug a device and to wait here forever. In
>                        order to prevent such a scenario, do eventually given up.
>                     */
>                     totalTimeout += timeout;
>                     if( PA_MME_MAX_TIMEOUT_MSEC_ <= totalTimeout)
>                     {
>                         result = paTimedOut;
>                         break;
>                     }
3498a3877,3878
>                 else
>                     totalTimeout = 0;
3673a4054,4059
>         /* If WaitForSingleObject starts repetitively and consecutively
>            returning WAIT_TIMEOUT, do eventually give up in order to allow the
>            caller to handle such cases.
>         */
>         DWORD totalTimeout = 0;
> 
3693a4080,4081
>                 totalTimeout = 0;
> 
3747,3748c4135,4138
<                     /* if a timeout is encountered, continue,
<                         perhaps we should give up eventually
---
>                     /* If a timeout is encountered, continue. However, testing
>                        has shown that it is possible to unplug a device and to
>                        wait here forever. In order to allow the caller to handle
>                        such cases of repeated timeouts, do eventually given up.
3749a4140,4145
>                     totalTimeout += timeout;
>                     if( PA_MME_MAX_TIMEOUT_MSEC_ <= totalTimeout)
>                     {
>                         result = paTimedOut;
>                         break;
>                     }
3779a4176,4181
>         /* If WaitForSingleObject starts repetitively and consecutively
>            returning WAIT_TIMEOUT, do eventually give up in order to allow the
>            caller to handle such cases.
>         */
>         DWORD totalTimeout = 0;
> 
3799a4202,4203
>                 totalTimeout = 0;
> 
3855,3856c4259,4262
<                     /* if a timeout is encountered, continue,
<                         perhaps we should give up eventually
---
>                     /* If a timeout is encountered, continue. However, testing
>                        has shown that it is possible to unplug a device and to
>                        wait here forever. In order to allow the caller to handle
>                        such cases of repeated timeouts, do eventually given up.
3857a4264,4269
>                     totalTimeout += timeout;
>                     if( PA_MME_MAX_TIMEOUT_MSEC_ <= totalTimeout)
>                     {
>                         result = paTimedOut;
>                         break;
>                     }
