Merge branch 'winrt' into 'master'

WASAPI: new API PaWasapi_SetStreamStateHandler(), header cleanup and minor fix

Merged-on: https://assembla.com/code/portaudio/git/merge_requests/7129721
This commit is contained in:
Dmitry Kostjuchenko 2018-12-24 12:22:35 +00:00
commit b7870b08f7
3 changed files with 362 additions and 203 deletions

View file

@ -1,9 +1,10 @@
/*
* Portable Audio I/O Library WASAPI implementation
* Copyright (c) 2006-2010 David Viens, Dmitry Kostjuchenko
* Copyright (c) 2006-2010 David Viens
* Copyright (c) 2010-2018 Dmitry Kostjuchenko
*
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 1999-2002 Ross Bencina, Phil Burk
* Copyright (c) 1999-2018 Ross Bencina, Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
@ -292,6 +293,10 @@ PA_THREAD_FUNC ProcThreadPoll(void *param);
#define MAX_STR_LEN 512
#ifdef PA_WINRT
#define PA_WASAPI_DEVICE_ID_LEN 4096
#endif
enum { S_INPUT = 0, S_OUTPUT = 1, S_COUNT = 2, S_FULLDUPLEX = 0 };
// Number of packets which compose single contignous buffer. With trial and error it was calculated
@ -339,12 +344,6 @@ FAvRevertMmThreadCharacteristics pAvRevertMmThreadCharacteristics = NULL;
FAvSetMmThreadPriority pAvSetMmThreadPriority = NULL;
#endif
#ifdef PA_WINRT
#define PA_WASAPI_DEVICE_ID_LEN 4096
static OLECHAR g_DefaultRenderId[PA_WASAPI_DEVICE_ID_LEN] = { 0 };
static OLECHAR g_DefaultCaptureId[PA_WASAPI_DEVICE_ID_LEN] = { 0 };
#endif
#define _GetProc(fun, type, name) { \
fun = (type) GetProcAddress(hDInputDLL,name); \
if (fun == NULL) { \
@ -452,15 +451,15 @@ typedef struct
PaWinUtilComInitializationResult comInitializationResult;
//this is the REAL number of devices, whether they are usefull to PA or not!
// this is the REAL number of devices, whether they are usefull to PA or not!
UINT32 deviceCount;
WCHAR defaultRenderer [MAX_STR_LEN];
WCHAR defaultCapturer [MAX_STR_LEN];
WCHAR defaultRenderer[MAX_STR_LEN];
WCHAR defaultCapturer[MAX_STR_LEN];
PaWasapiDeviceInfo *devInfo;
// Is true when WOW64 Vista/7 Workaround is needed
// is TRUE when WOW64 Vista/7 Workaround is needed
BOOL useWOW64Workaround;
}
PaWasapiHostApiRepresentation;
@ -584,6 +583,10 @@ typedef struct PaWasapiStream
// Thread priority level
PaWasapiThreadPriority nThreadPriority;
// State handler
PaWasapiStreamStateCallback fnStateHandler;
void *pStateHandlerUserData;
}
PaWasapiStream;
@ -606,6 +609,10 @@ static void PaWasapi_FreeMemory(void *ptr);
static PaSampleFormat WaveToPaFormat(const WAVEFORMATEXTENSIBLE *fmtext);
// Local statics
#ifdef PA_WINRT
static OLECHAR g_DefaultRenderId[PA_WASAPI_DEVICE_ID_LEN] = { 0 };
static OLECHAR g_DefaultCaptureId[PA_WASAPI_DEVICE_ID_LEN] = { 0 };
#endif
// ------------------------------------------------------------------------------------------
#define LogHostError(HRES) __LogHostError(HRES, __FUNCTION__, __FILE__, __LINE__)
@ -851,7 +858,7 @@ static UINT32 ALIGN_FWD(UINT32 v, UINT32 align)
// ------------------------------------------------------------------------------------------
// Get next value power of 2
UINT32 ALIGN_NEXT_POW2(UINT32 v)
static UINT32 ALIGN_NEXT_POW2(UINT32 v)
{
UINT32 v2 = 1;
while (v > (v2 <<= 1)) { }
@ -1583,6 +1590,18 @@ static DWORD SignalObjectAndWait(HANDLE hObjectToSignal, HANDLE hObjectToWaitOn,
#endif
#endif
// ------------------------------------------------------------------------------------------
static void NotifyStateChanged(PaWasapiStream *stream, UINT32 flags, HRESULT hr)
{
if (stream->fnStateHandler == NULL)
return;
if (FAILED(hr))
flags |= paWasapiStreamStateError;
stream->fnStateHandler((PaStream *)stream, flags, hr, stream->pStateHandlerUserData);
}
// ------------------------------------------------------------------------------------------
static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostApiIndex hostApiIndex)
{
@ -1684,7 +1703,8 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
}
#endif
paWasapi->devInfo = (PaWasapiDeviceInfo *)PaUtil_AllocateMemory(sizeof(PaWasapiDeviceInfo) * paWasapi->deviceCount);
paWasapi->devInfo = (PaWasapiDeviceInfo *)PaUtil_GroupAllocateMemory(
paWasapi->allocations, sizeof(PaWasapiDeviceInfo) * paWasapi->deviceCount);
if (paWasapi->devInfo == NULL)
{
result = paInsufficientMemory;
@ -2013,7 +2033,7 @@ error:
// ------------------------------------------------------------------------------------------
PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
{
PaError result = paInternalError;
PaError result;
PaWasapiHostApiRepresentation *paWasapi;
#ifndef PA_WINRT
@ -2032,10 +2052,12 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
}
memset(paWasapi, 0, sizeof(PaWasapiHostApiRepresentation)); /* ensure all fields are zeroed. especially paWasapi->allocations */
// Initialize COM subsystem
result = PaWinUtil_CoInitialize(paWASAPI, &paWasapi->comInitializationResult);
if (result != paNoError)
goto error;
// Create memory group
paWasapi->allocations = PaUtil_CreateAllocationGroup();
if (paWasapi->allocations == NULL)
{
@ -2091,15 +2113,20 @@ static void ReleaseWasapiDeviceInfoList( PaWasapiHostApiRepresentation *paWasapi
{
UINT32 i;
// Release device info bound objects and device info itself
// Release device info bound objects
for (i = 0; i < paWasapi->deviceCount; ++i)
{
#ifndef PA_WINRT
SAFE_RELEASE(paWasapi->devInfo[i].device);
#endif
}
PaUtil_FreeMemory(paWasapi->devInfo);
// Free device info
if (paWasapi->allocations != NULL)
PaUtil_GroupFreeMemory(paWasapi->allocations, paWasapi->devInfo);
// Be ready for a device list reinitialization and if its creation is failed pointers must not be dangling
paWasapi->devInfo = NULL;
paWasapi->deviceCount = 0;
}
@ -2110,16 +2137,20 @@ static void Terminate( PaUtilHostApiRepresentation *hostApi )
if (paWasapi == NULL)
return;
// Release device list
ReleaseWasapiDeviceInfoList(paWasapi);
// Free allocations and memory group itself
if (paWasapi->allocations != NULL)
{
PaUtil_FreeAllAllocations(paWasapi->allocations);
PaUtil_DestroyAllocationGroup(paWasapi->allocations);
}
PaWinUtil_CoUninitialize( paWASAPI, &paWasapi->comInitializationResult );
// Release COM subsystem
PaWinUtil_CoUninitialize(paWASAPI, &paWasapi->comInitializationResult);
// Free API representation
PaUtil_FreeMemory(paWasapi);
// Close AVRT
@ -2127,18 +2158,19 @@ static void Terminate( PaUtilHostApiRepresentation *hostApi )
}
// ------------------------------------------------------------------------------------------
static PaWasapiHostApiRepresentation *_GetHostApi(PaError *_error)
static PaWasapiHostApiRepresentation *_GetHostApi(PaError *ret)
{
PaError error;
PaUtilHostApiRepresentation *pApi;
if ((error = PaUtil_GetHostApiRepresentation(&pApi, paWASAPI)) != paNoError)
{
if (_error != NULL)
(*_error) = error;
if (ret != NULL)
(*ret) = error;
return NULL;
}
return (PaWasapiHostApiRepresentation *)pApi;
}
@ -2153,7 +2185,11 @@ static PaError UpdateDeviceList()
// Get API
hostApi = (PaUtilHostApiRepresentation *)(paWasapi = _GetHostApi(&ret));
if (paWasapi == NULL)
return ret;
return paNotInitialized;
// Make sure initialized properly
if (paWasapi->allocations == NULL)
return paNotInitialized;
// Release WASAPI internal device info list
ReleaseWasapiDeviceInfoList(paWasapi);
@ -2168,6 +2204,8 @@ static PaError UpdateDeviceList()
PaUtil_GroupFreeMemory(paWasapi->allocations, hostApi->deviceInfos[0]);
PaUtil_GroupFreeMemory(paWasapi->allocations, hostApi->deviceInfos);
// Be ready for a device list reinitialization and if its creation is failed pointers must not be dangling
hostApi->deviceInfos = NULL;
hostApi->info.deviceCount = 0;
hostApi->info.defaultInputDevice = paNoDevice;
hostApi->info.defaultOutputDevice = paNoDevice;
@ -2189,7 +2227,7 @@ PaError PaWasapi_UpdateDeviceList()
#endif
// ------------------------------------------------------------------------------------------
int PaWasapi_GetDeviceCurrentFormat( PaStream *pStream, void *pFormat, unsigned int nFormatSize, int bOutput )
int PaWasapi_GetDeviceCurrentFormat( PaStream *pStream, void *pFormat, unsigned int formatSize, int bOutput )
{
UINT32 size;
WAVEFORMATEXTENSIBLE *format;
@ -2200,14 +2238,14 @@ int PaWasapi_GetDeviceCurrentFormat( PaStream *pStream, void *pFormat, unsigned
format = (bOutput == TRUE ? &stream->out.wavex : &stream->in.wavex);
size = min(nFormatSize, (UINT32)sizeof(*format));
size = min(formatSize, (UINT32)sizeof(*format));
memcpy(pFormat, format, size);
return size;
}
// ------------------------------------------------------------------------------------------
int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice )
int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int formatSize, PaDeviceIndex device )
{
PaError ret;
PaWasapiHostApiRepresentation *paWasapi;
@ -2216,7 +2254,7 @@ int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, Pa
if (pFormat == NULL)
return paBadBufferPtr;
if (nFormatSize <= 0)
if (formatSize <= 0)
return paBufferTooSmall;
// Get API
@ -2225,7 +2263,7 @@ int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, Pa
return ret;
// Get device index
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, nDevice, &paWasapi->inheritedHostApiRep);
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, device, &paWasapi->inheritedHostApiRep);
if (ret != paNoError)
return ret;
@ -2233,14 +2271,14 @@ int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, Pa
if ((UINT32)index >= paWasapi->deviceCount)
return paInvalidDevice;
size = min(nFormatSize, (UINT32)sizeof(paWasapi->devInfo[ index ].DefaultFormat));
size = min(formatSize, (UINT32)sizeof(paWasapi->devInfo[ index ].DefaultFormat));
memcpy(pFormat, &paWasapi->devInfo[ index ].DefaultFormat, size);
return size;
}
// ------------------------------------------------------------------------------------------
int PaWasapi_GetDeviceMixFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice )
int PaWasapi_GetDeviceMixFormat( void *pFormat, unsigned int formatSize, PaDeviceIndex device )
{
PaError ret;
PaWasapiHostApiRepresentation *paWasapi;
@ -2249,7 +2287,7 @@ int PaWasapi_GetDeviceMixFormat( void *pFormat, unsigned int nFormatSize, PaDevi
if (pFormat == NULL)
return paBadBufferPtr;
if (nFormatSize <= 0)
if (formatSize <= 0)
return paBufferTooSmall;
// Get API
@ -2258,7 +2296,7 @@ int PaWasapi_GetDeviceMixFormat( void *pFormat, unsigned int nFormatSize, PaDevi
return ret;
// Get device index
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, nDevice, &paWasapi->inheritedHostApiRep);
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, device, &paWasapi->inheritedHostApiRep);
if (ret != paNoError)
return ret;
@ -2266,14 +2304,14 @@ int PaWasapi_GetDeviceMixFormat( void *pFormat, unsigned int nFormatSize, PaDevi
if ((UINT32)index >= paWasapi->deviceCount)
return paInvalidDevice;
size = min(nFormatSize, (UINT32)sizeof(paWasapi->devInfo[ index ].MixFormat));
size = min(formatSize, (UINT32)sizeof(paWasapi->devInfo[ index ].MixFormat));
memcpy(pFormat, &paWasapi->devInfo[ index ].MixFormat, size);
return size;
}
// ------------------------------------------------------------------------------------------
int PaWasapi_GetDeviceRole( PaDeviceIndex nDevice )
int PaWasapi_GetDeviceRole( PaDeviceIndex device )
{
PaError ret;
PaDeviceIndex index;
@ -2284,7 +2322,7 @@ int PaWasapi_GetDeviceRole( PaDeviceIndex nDevice )
return paNotInitialized;
// Get device index
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, nDevice, &paWasapi->inheritedHostApiRep);
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, device, &paWasapi->inheritedHostApiRep);
if (ret != paNoError)
return ret;
@ -2296,17 +2334,17 @@ int PaWasapi_GetDeviceRole( PaDeviceIndex nDevice )
}
// ------------------------------------------------------------------------------------------
PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *nInput, unsigned int *nOutput )
PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *pInput, unsigned int *pOutput )
{
PaWasapiStream *stream = (PaWasapiStream *)pStream;
if (stream == NULL)
return paBadStreamPtr;
if (nInput != NULL)
(*nInput) = stream->in.framesPerHostCallback;
if (pInput != NULL)
(*pInput) = stream->in.framesPerHostCallback;
if (nOutput != NULL)
(*nOutput) = stream->out.framesPerHostCallback;
if (pOutput != NULL)
(*pOutput) = stream->out.framesPerHostCallback;
return paNoError;
}
@ -4849,19 +4887,19 @@ static void MMCSS_deactivate(HANDLE hTask)
#endif
// ------------------------------------------------------------------------------------------
PaError PaWasapi_ThreadPriorityBoost(void **hTask, PaWasapiThreadPriority nPriorityClass)
PaError PaWasapi_ThreadPriorityBoost(void **pTask, PaWasapiThreadPriority priorityClass)
{
HANDLE task;
PaError ret;
if (hTask == NULL)
if (pTask == NULL)
return paUnanticipatedHostError;
#ifndef PA_WINRT
if ((ret = MMCSS_activate(nPriorityClass, &task)) != paNoError)
if ((ret = MMCSS_activate(priorityClass, &task)) != paNoError)
return ret;
#else
switch (nPriorityClass)
switch (priorityClass)
{
case eThreadPriorityAudio:
case eThreadPriorityProAudio: {
@ -4885,21 +4923,21 @@ PaError PaWasapi_ThreadPriorityBoost(void **hTask, PaWasapiThreadPriority nPrior
}
#endif
(*hTask) = task;
(*pTask) = task;
return ret;
}
// ------------------------------------------------------------------------------------------
PaError PaWasapi_ThreadPriorityRevert(void *hTask)
PaError PaWasapi_ThreadPriorityRevert(void *pTask)
{
if (hTask == NULL)
if (pTask == NULL)
return paUnanticipatedHostError;
#ifndef PA_WINRT
MMCSS_deactivate((HANDLE)hTask);
MMCSS_deactivate((HANDLE)pTask);
#else
// Revert previous priority by removing 0x80000000 mask
if (SetThreadPriority(GetCurrentThread(), (int)((intptr_t)hTask & ~0x80000000)) == FALSE)
if (SetThreadPriority(GetCurrentThread(), (int)((intptr_t)pTask & ~0x80000000)) == FALSE)
return paUnanticipatedHostError;
#endif
@ -4910,7 +4948,7 @@ PaError PaWasapi_ThreadPriorityRevert(void *hTask)
// Described at:
// http://msdn.microsoft.com/en-us/library/dd371387(v=VS.85).aspx
PaError PaWasapi_GetJackCount(PaDeviceIndex nDevice, int *jcount)
PaError PaWasapi_GetJackCount(PaDeviceIndex device, int *pJackCount)
{
#ifndef PA_WINRT
PaError ret;
@ -4927,47 +4965,50 @@ PaError PaWasapi_GetJackCount(PaDeviceIndex nDevice, int *jcount)
if (paWasapi == NULL)
return paNotInitialized;
// Get device index.
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, nDevice, &paWasapi->inheritedHostApiRep);
if (pJackCount == NULL)
return paUnanticipatedHostError;
// Get device index
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, device, &paWasapi->inheritedHostApiRep);
if (ret != paNoError)
return ret;
// Validate index.
// Validate index
if ((UINT32)index >= paWasapi->deviceCount)
return paInvalidDevice;
// Get the endpoint device's IDeviceTopology interface.
// Get the endpoint device's IDeviceTopology interface
hr = IMMDevice_Activate(paWasapi->devInfo[index].device, &pa_IID_IDeviceTopology,
CLSCTX_INPROC_SERVER, NULL, (void**)&pDeviceTopology);
IF_FAILED_JUMP(hr, error);
// The device topology for an endpoint device always contains just one connector (connector number 0).
// The device topology for an endpoint device always contains just one connector (connector number 0)
hr = IDeviceTopology_GetConnector(pDeviceTopology, 0, &pConnFrom);
IF_FAILED_JUMP(hr, error);
// Step across the connection to the jack on the adapter.
// Step across the connection to the jack on the adapter
hr = IConnector_GetConnectedTo(pConnFrom, &pConnTo);
if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
{
// The adapter device is not currently active.
// The adapter device is not currently active
hr = E_NOINTERFACE;
}
IF_FAILED_JUMP(hr, error);
// Get the connector's IPart interface.
// Get the connector's IPart interface
hr = IConnector_QueryInterface(pConnTo, &pa_IID_IPart, (void**)&pPart);
IF_FAILED_JUMP(hr, error);
// Activate the connector's IKsJackDescription interface.
// Activate the connector's IKsJackDescription interface
hr = IPart_Activate(pPart, CLSCTX_INPROC_SERVER, &pa_IID_IKsJackDescription, (void**)&pJackDesc);
IF_FAILED_JUMP(hr, error);
// Return jack count for this device.
// Return jack count for this device
hr = IKsJackDescription_GetJackCount(pJackDesc, &jackCount);
IF_FAILED_JUMP(hr, error);
// Set.
(*jcount) = jackCount;
(*pJackCount) = jackCount;
// Ok.
ret = paNoError;
@ -4983,8 +5024,8 @@ error:
LogHostError(hr);
return paNoError;
#else
(void)nDevice;
(void)jcount;
(void)device;
(void)pJackCount;
return paUnanticipatedHostError;
#endif
}
@ -5082,7 +5123,7 @@ static PaWasapiJackPortConnection _ConvertJackPortConnectionWASAPIToPA(int portC
// Described at:
// http://msdn.microsoft.com/en-us/library/dd371387(v=VS.85).aspx
PaError PaWasapi_GetJackDescription(PaDeviceIndex nDevice, int jindex, PaWasapiJackDescription *pJackDescription)
PaError PaWasapi_GetJackDescription(PaDeviceIndex device, int jackIndex, PaWasapiJackDescription *pJackDescription)
{
#ifndef PA_WINRT
PaError ret;
@ -5099,46 +5140,46 @@ PaError PaWasapi_GetJackDescription(PaDeviceIndex nDevice, int jindex, PaWasapiJ
if (paWasapi == NULL)
return paNotInitialized;
// Get device index.
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, nDevice, &paWasapi->inheritedHostApiRep);
// Get device index
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, device, &paWasapi->inheritedHostApiRep);
if (ret != paNoError)
return ret;
// Validate index.
// Validate index
if ((UINT32)index >= paWasapi->deviceCount)
return paInvalidDevice;
// Get the endpoint device's IDeviceTopology interface.
// Get the endpoint device's IDeviceTopology interface
hr = IMMDevice_Activate(paWasapi->devInfo[index].device, &pa_IID_IDeviceTopology,
CLSCTX_INPROC_SERVER, NULL, (void**)&pDeviceTopology);
IF_FAILED_JUMP(hr, error);
// The device topology for an endpoint device always contains just one connector (connector number 0).
// The device topology for an endpoint device always contains just one connector (connector number 0)
hr = IDeviceTopology_GetConnector(pDeviceTopology, 0, &pConnFrom);
IF_FAILED_JUMP(hr, error);
// Step across the connection to the jack on the adapter.
// Step across the connection to the jack on the adapter
hr = IConnector_GetConnectedTo(pConnFrom, &pConnTo);
if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
{
// The adapter device is not currently active.
// The adapter device is not currently active
hr = E_NOINTERFACE;
}
IF_FAILED_JUMP(hr, error);
// Get the connector's IPart interface.
// Get the connector's IPart interface
hr = IConnector_QueryInterface(pConnTo, &pa_IID_IPart, (void**)&pPart);
IF_FAILED_JUMP(hr, error);
// Activate the connector's IKsJackDescription interface.
// Activate the connector's IKsJackDescription interface
hr = IPart_Activate(pPart, CLSCTX_INPROC_SERVER, &pa_IID_IKsJackDescription, (void**)&pJackDesc);
IF_FAILED_JUMP(hr, error);
// Test to return jack description struct for index 0.
hr = IKsJackDescription_GetJackDescription(pJackDesc, jindex, &jack);
// Test to return jack description struct for index 0
hr = IKsJackDescription_GetJackDescription(pJackDesc, jackIndex, &jack);
IF_FAILED_JUMP(hr, error);
// Convert WASAPI values to PA format.
// Convert WASAPI values to PA format
pJackDescription->channelMapping = jack.ChannelMapping;
pJackDescription->color = jack.Color;
pJackDescription->connectionType = _ConvertJackConnectionTypeWASAPIToPA(jack.ConnectionType);
@ -5147,7 +5188,7 @@ PaError PaWasapi_GetJackDescription(PaDeviceIndex nDevice, int jindex, PaWasapiJ
pJackDescription->isConnected = jack.IsConnected;
pJackDescription->portConnection = _ConvertJackPortConnectionWASAPIToPA(jack.PortConnection);
// Ok.
// Ok
ret = paNoError;
error:
@ -5162,8 +5203,8 @@ error:
return ret;
#else
(void)nDevice;
(void)jindex;
(void)device;
(void)jackIndex;
(void)pJackDescription;
return paUnanticipatedHostError;
#endif
@ -5188,11 +5229,12 @@ PaError PaWasapi_GetAudioClient(PaStream *pStream, void **pAudioClient, int bOut
PaError PaWasapi_SetDefaultInterfaceId( unsigned short *pId, int bOutput )
{
#ifdef PA_WINRT
int i;
// Validate Id length
if (pId != NULL)
{
for (int i = 0; pId[i] != 0; ++i)
for (i = 0; pId[i] != 0; ++i)
{
if (i >= PA_WASAPI_DEVICE_ID_LEN)
return paBufferTooBig;
@ -5205,7 +5247,7 @@ PaError PaWasapi_SetDefaultInterfaceId( unsigned short *pId, int bOutput )
memset(g_DefaultRenderId, 0, sizeof(g_DefaultRenderId));
if (pId != NULL)
{
for (int i = 0; (pId[i] != 0) && (i < STATIC_ARRAY_SIZE(g_DefaultRenderId)); ++i)
for (i = 0; (pId[i] != 0) && (i < STATIC_ARRAY_SIZE(g_DefaultRenderId)); ++i)
g_DefaultRenderId[i] = pId[i];
}
}
@ -5214,7 +5256,7 @@ PaError PaWasapi_SetDefaultInterfaceId( unsigned short *pId, int bOutput )
memset(g_DefaultCaptureId, 0, sizeof(g_DefaultCaptureId));
if (pId != NULL)
{
for (int i = 0; (pId[i] != 0) && (i < STATIC_ARRAY_SIZE(g_DefaultCaptureId)); ++i)
for (i = 0; (pId[i] != 0) && (i < STATIC_ARRAY_SIZE(g_DefaultCaptureId)); ++i)
g_DefaultCaptureId[i] = pId[i];
}
}
@ -5226,6 +5268,19 @@ PaError PaWasapi_SetDefaultInterfaceId( unsigned short *pId, int bOutput )
#endif
}
// ------------------------------------------------------------------------------------------
PaError PaWasapi_SetStreamStateHandler( PaStream *pStream, PaWasapiStreamStateCallback fnStateHandler, void *pUserData )
{
PaWasapiStream *stream = (PaWasapiStream *)pStream;
if (stream == NULL)
return paBadStreamPtr;
stream->fnStateHandler = fnStateHandler;
stream->pStateHandlerUserData = pUserData;
return paNoError;
}
// ------------------------------------------------------------------------------------------
HRESULT _PollGetOutputFramesAvailable(PaWasapiStream *stream, UINT32 *available)
{
@ -5453,6 +5508,9 @@ PA_THREAD_FUNC ProcThreadEvent(void *param)
BOOL bWaitAllEvents = FALSE;
BOOL bThreadComInitialized = FALSE;
// Notify: state
NotifyStateChanged(stream, paWasapiStreamStateThreadPrepare, ERROR_SUCCESS);
/*
If COM is already initialized CoInitialize will either return
FALSE, or RPC_E_CHANGED_MODE if it was initialized in a different
@ -5565,6 +5623,9 @@ PA_THREAD_FUNC ProcThreadEvent(void *param)
// Notify: thread started
SetEvent(stream->hThreadStart);
// Notify: state
NotifyStateChanged(stream, paWasapiStreamStateThreadStart, ERROR_SUCCESS);
// Processing Loop
for (;;)
{
@ -5632,6 +5693,9 @@ thread_end:
// Notify: thread exited
SetEvent(stream->hThreadExit);
// Notify: state
NotifyStateChanged(stream, paWasapiStreamStateThreadStop, hr);
return 0;
thread_error:
@ -5660,6 +5724,9 @@ PA_THREAD_FUNC ProcThreadPoll(void *param)
BOOL bThreadComInitialized = FALSE;
// Notify: state
NotifyStateChanged(stream, paWasapiStreamStateThreadPrepare, ERROR_SUCCESS);
/*
If COM is already initialized CoInitialize will either return
FALSE, or RPC_E_CHANGED_MODE if it was initialized in a different
@ -5802,6 +5869,9 @@ PA_THREAD_FUNC ProcThreadPoll(void *param)
// Notify: thread started
SetEvent(stream->hThreadStart);
// Notify: state
NotifyStateChanged(stream, paWasapiStreamStateThreadStart, ERROR_SUCCESS);
if (!PA_WASAPI__IS_FULLDUPLEX(stream))
{
// Processing Loop
@ -6157,6 +6227,9 @@ thread_end:
// Notify: thread exited
SetEvent(stream->hThreadExit);
// Notify: state
NotifyStateChanged(stream, paWasapiStreamStateThreadStop, hr);
return 0;
thread_error: