Merge branch 'winrt' into 'master'
WinRT: fixed failure to initialize WASAPI when Capture device is not provided by OS, and additional minor corrections. Merged-on: https://assembla.com/code/portaudio/git/merge_requests/5913713
This commit is contained in:
commit
9923e1dc31
2 changed files with 234 additions and 110 deletions
|
|
@ -291,6 +291,18 @@ typedef struct PaWasapiStreamInfo
|
|||
PaWasapiStreamInfo;
|
||||
|
||||
|
||||
/** Update device list.
|
||||
This function will be available if PA_WASAPI_MAX_CONST_DEVICE_COUNT is defined with maximum
|
||||
constant WASAPI device count (defined by default with value 32).
|
||||
If PA_WASAPI_MAX_CONST_DEVICE_COUNT is set to 0 during compile time the implementation will not
|
||||
define PaWasapi_UpdateDeviceList() and thus updating device list can only be possible by calling
|
||||
Pa_Terminate() and then Pa_Initialize().
|
||||
|
||||
@return Error code indicating success or failure.
|
||||
*/
|
||||
PaError PaWasapi_UpdateDeviceList();
|
||||
|
||||
|
||||
/** Returns default sound format for device. Format is represented by PaWinWaveFormat or
|
||||
WAVEFORMATEXTENSIBLE structure.
|
||||
|
||||
|
|
@ -356,6 +368,7 @@ PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *nInput
|
|||
/** Get number of jacks associated with a WASAPI device. Use this method to determine if
|
||||
there are any jacks associated with the provided WASAPI device. Not all audio devices
|
||||
will support this capability. This is valid for both input and output devices.
|
||||
|
||||
@param nDevice device index.
|
||||
@param jcount Number of jacks is returned in this variable
|
||||
@return Error code indicating success or failure
|
||||
|
|
@ -369,6 +382,7 @@ PaError PaWasapi_GetJackCount(PaDeviceIndex nDevice, int *jcount);
|
|||
number of jacks associated with device. If jcount is greater than zero, then
|
||||
each jack from 0 to jcount can be queried with this function to get the jack
|
||||
description.
|
||||
|
||||
@param nDevice device index.
|
||||
@param jindex Which jack to return information
|
||||
@param KSJACK_DESCRIPTION This structure filled in on success.
|
||||
|
|
|
|||
|
|
@ -47,6 +47,12 @@
|
|||
#include <process.h>
|
||||
#include <assert.h>
|
||||
|
||||
// Max device count (if defined) causes max constant device count in the device list that
|
||||
// enables PaWasapi_UpdateDeviceList() API and makes it possible to update WASAPI list dynamically
|
||||
#ifndef PA_WASAPI_MAX_CONST_DEVICE_COUNT
|
||||
#define PA_WASAPI_MAX_CONST_DEVICE_COUNT 32
|
||||
#endif
|
||||
|
||||
// WinRT
|
||||
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
|
||||
#define PA_WINRT
|
||||
|
|
@ -432,11 +438,6 @@ typedef struct
|
|||
|
||||
PaWinUtilComInitializationResult comInitializationResult;
|
||||
|
||||
//in case we later need the synch
|
||||
#ifndef PA_WINRT
|
||||
IMMDeviceEnumerator *enumerator;
|
||||
#endif
|
||||
|
||||
//this is the REAL number of devices, whether they are usefull to PA or not!
|
||||
UINT32 deviceCount;
|
||||
|
||||
|
|
@ -639,6 +640,9 @@ static HRESULT __LogHostError(HRESULT res, const char *func, const char *file, i
|
|||
text = "UNKNOWN ERROR";
|
||||
}
|
||||
PRINT(("WASAPI ERROR HRESULT: 0x%X : %s\n [FUNCTION: %s FILE: %s {LINE: %d}]\n", res, text, func, file, line));
|
||||
#ifndef PA_ENABLE_DEBUG_OUTPUT
|
||||
(void)func; (void)file; (void)line;
|
||||
#endif
|
||||
PA_SKELETON_SET_LAST_HOST_ERROR(res, text);
|
||||
return res;
|
||||
}
|
||||
|
|
@ -649,7 +653,11 @@ static PaError __LogPaError(PaError err, const char *func, const char *file, int
|
|||
{
|
||||
if (err == paNoError)
|
||||
return err;
|
||||
|
||||
PRINT(("WASAPI ERROR PAERROR: %i : %s\n [FUNCTION: %s FILE: %s {LINE: %d}]\n", err, Pa_GetErrorText(err), func, file, line));
|
||||
#ifndef PA_ENABLE_DEBUG_OUTPUT
|
||||
(void)func; (void)file; (void)line;
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -1344,7 +1352,7 @@ static IActivateAudioInterfaceCompletionHandler *CreateActivateAudioInterfaceCom
|
|||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
#ifdef PA_WINRT
|
||||
static HRESULT ActivateAudioInterface_WINRT(const PaWasapiDeviceInfo *deviceInfo, const IID *iid, void **obj)
|
||||
static HRESULT ActivateAudioInterface_WINRT(EDataFlow flow, const IID *iid, void **obj)
|
||||
{
|
||||
#define PA_WASAPI_DEVICE_PATH_LEN 64
|
||||
|
||||
|
|
@ -1356,7 +1364,7 @@ static HRESULT ActivateAudioInterface_WINRT(const PaWasapiDeviceInfo *deviceInfo
|
|||
OLECHAR devicePath[PA_WASAPI_DEVICE_PATH_LEN] = { 0 };
|
||||
|
||||
// Get device path in form L"{DEVICE_GUID}"
|
||||
switch (deviceInfo->flow)
|
||||
switch (flow)
|
||||
{
|
||||
case eRender:
|
||||
StringFromGUID2(&DEVINTERFACE_AUDIO_RENDER, devicePath, PA_WASAPI_DEVICE_PATH_LEN - 1);
|
||||
|
|
@ -1399,7 +1407,7 @@ static HRESULT ActivateAudioInterface(const PaWasapiDeviceInfo *deviceInfo, IAud
|
|||
#ifndef PA_WINRT
|
||||
return IMMDevice_Activate(deviceInfo->device, GetAudioClientIID(), CLSCTX_ALL, NULL, (void **)client);
|
||||
#else
|
||||
return ActivateAudioInterface_WINRT(deviceInfo, GetAudioClientIID(), (void **)client);
|
||||
return ActivateAudioInterface_WINRT(deviceInfo->flow, GetAudioClientIID(), (void **)client);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -1416,61 +1424,28 @@ static DWORD SignalObjectAndWait(HANDLE hObjectToSignal, HANDLE hObjectToWaitOn,
|
|||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
|
||||
static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostApiIndex hostApiIndex)
|
||||
{
|
||||
PaUtilHostApiRepresentation *hostApi = (PaUtilHostApiRepresentation *)paWasapi;
|
||||
PaError result = paNoError;
|
||||
PaWasapiHostApiRepresentation *paWasapi;
|
||||
PaDeviceInfo *deviceInfoArray;
|
||||
HRESULT hr = S_OK;
|
||||
UINT i;
|
||||
#ifndef PA_WINRT
|
||||
IMMDeviceCollection* pEndPoints = NULL;
|
||||
IMMDeviceEnumerator *pEnumerator = NULL;
|
||||
#else
|
||||
WAVEFORMATEX *mixFormat;
|
||||
#endif
|
||||
IAudioClient *tmpClient;
|
||||
|
||||
// Make sure device list empty
|
||||
if ((paWasapi->deviceCount != 0) || (hostApi->info.deviceCount != 0))
|
||||
return paInternalError;
|
||||
|
||||
#ifndef PA_WINRT
|
||||
if (!SetupAVRT())
|
||||
{
|
||||
PRINT(("WASAPI: No AVRT! (not VISTA?)"));
|
||||
return paNoError;
|
||||
}
|
||||
#endif
|
||||
|
||||
paWasapi = (PaWasapiHostApiRepresentation *)PaUtil_AllocateMemory( sizeof(PaWasapiHostApiRepresentation) );
|
||||
if (paWasapi == NULL)
|
||||
{
|
||||
result = paInsufficientMemory;
|
||||
goto error;
|
||||
}
|
||||
|
||||
memset( paWasapi, 0, sizeof(PaWasapiHostApiRepresentation) ); /* ensure all fields are zeroed. especially paWasapi->allocations */
|
||||
|
||||
result = PaWinUtil_CoInitialize( paWASAPI, &paWasapi->comInitializationResult );
|
||||
if( result != paNoError )
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
paWasapi->allocations = PaUtil_CreateAllocationGroup();
|
||||
if (paWasapi->allocations == NULL)
|
||||
{
|
||||
result = paInsufficientMemory;
|
||||
goto error;
|
||||
}
|
||||
|
||||
*hostApi = &paWasapi->inheritedHostApiRep;
|
||||
(*hostApi)->info.structVersion = 1;
|
||||
(*hostApi)->info.type = paWASAPI;
|
||||
(*hostApi)->info.name = "Windows WASAPI";
|
||||
(*hostApi)->info.deviceCount = 0;
|
||||
(*hostApi)->info.defaultInputDevice = paNoDevice;
|
||||
(*hostApi)->info.defaultOutputDevice = paNoDevice;
|
||||
|
||||
#ifndef PA_WINRT
|
||||
paWasapi->enumerator = NULL;
|
||||
hr = CoCreateInstance(&pa_CLSID_IMMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER,
|
||||
&pa_IID_IMMDeviceEnumerator, (void **)&paWasapi->enumerator);
|
||||
&pa_IID_IMMDeviceEnumerator, (void **)&pEnumerator);
|
||||
|
||||
// We need to set the result to a value otherwise we will return paNoError
|
||||
// [IF_FAILED_JUMP(hResult, error);]
|
||||
|
|
@ -1480,7 +1455,7 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
{
|
||||
{
|
||||
IMMDevice *defaultRenderer = NULL;
|
||||
hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(paWasapi->enumerator, eRender, eMultimedia, &defaultRenderer);
|
||||
hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(pEnumerator, eRender, eMultimedia, &defaultRenderer);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
if (hr != E_NOTFOUND) {
|
||||
|
|
@ -1504,7 +1479,7 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
|
||||
{
|
||||
IMMDevice *defaultCapturer = NULL;
|
||||
hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(paWasapi->enumerator, eCapture, eMultimedia, &defaultCapturer);
|
||||
hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(pEnumerator, eCapture, eMultimedia, &defaultCapturer);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
if (hr != E_NOTFOUND) {
|
||||
|
|
@ -1527,7 +1502,7 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
}
|
||||
}
|
||||
|
||||
hr = IMMDeviceEnumerator_EnumAudioEndpoints(paWasapi->enumerator, eAll, DEVICE_STATE_ACTIVE, &pEndPoints);
|
||||
hr = IMMDeviceEnumerator_EnumAudioEndpoints(pEnumerator, eAll, DEVICE_STATE_ACTIVE, &pEndPoints);
|
||||
// We need to set the result to a value otherwise we will return paNoError
|
||||
// [IF_FAILED_JUMP(hResult, error);]
|
||||
IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
|
||||
|
|
@ -1538,7 +1513,17 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
|
||||
|
||||
#else
|
||||
paWasapi->deviceCount = 2;
|
||||
// Determine number of available devices by activating AudioClient for render and capture data flows
|
||||
if (!FAILED(ActivateAudioInterface_WINRT(eRender, GetAudioClientIID(), &tmpClient)))
|
||||
{
|
||||
paWasapi->deviceCount++;
|
||||
SAFE_RELEASE(tmpClient);
|
||||
}
|
||||
if (!FAILED(ActivateAudioInterface_WINRT(eCapture, GetAudioClientIID(), &tmpClient)))
|
||||
{
|
||||
paWasapi->deviceCount++;
|
||||
SAFE_RELEASE(tmpClient);
|
||||
}
|
||||
#endif
|
||||
|
||||
paWasapi->devInfo = (PaWasapiDeviceInfo *)PaUtil_AllocateMemory(sizeof(PaWasapiDeviceInfo) * paWasapi->deviceCount);
|
||||
|
|
@ -1547,14 +1532,19 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
result = paInsufficientMemory;
|
||||
goto error;
|
||||
}
|
||||
for (i = 0; i < paWasapi->deviceCount; ++i)
|
||||
memset(&paWasapi->devInfo[i], 0, sizeof(PaWasapiDeviceInfo));
|
||||
memset(paWasapi->devInfo, 0, sizeof(PaWasapiDeviceInfo) * paWasapi->deviceCount);
|
||||
|
||||
if (paWasapi->deviceCount > 0)
|
||||
{
|
||||
(*hostApi)->deviceInfos = (PaDeviceInfo **)PaUtil_GroupAllocateMemory(
|
||||
paWasapi->allocations, sizeof(PaDeviceInfo *) * paWasapi->deviceCount);
|
||||
if ((*hostApi)->deviceInfos == NULL)
|
||||
UINT32 deviceCount = paWasapi->deviceCount;
|
||||
#if defined(PA_WASAPI_MAX_CONST_DEVICE_COUNT) && (PA_WASAPI_MAX_CONST_DEVICE_COUNT > 0)
|
||||
if (deviceCount < PA_WASAPI_MAX_CONST_DEVICE_COUNT)
|
||||
deviceCount = PA_WASAPI_MAX_CONST_DEVICE_COUNT;
|
||||
#endif
|
||||
|
||||
hostApi->deviceInfos = (PaDeviceInfo **)PaUtil_GroupAllocateMemory(
|
||||
paWasapi->allocations, sizeof(PaDeviceInfo *) * deviceCount);
|
||||
if (hostApi->deviceInfos == NULL)
|
||||
{
|
||||
result = paInsufficientMemory;
|
||||
goto error;
|
||||
|
|
@ -1562,12 +1552,13 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
|
||||
/* allocate all device info structs in a contiguous block */
|
||||
deviceInfoArray = (PaDeviceInfo *)PaUtil_GroupAllocateMemory(
|
||||
paWasapi->allocations, sizeof(PaDeviceInfo) * paWasapi->deviceCount);
|
||||
paWasapi->allocations, sizeof(PaDeviceInfo) * deviceCount);
|
||||
if (deviceInfoArray == NULL)
|
||||
{
|
||||
result = paInsufficientMemory;
|
||||
goto error;
|
||||
}
|
||||
memset(deviceInfoArray, 0, sizeof(PaDeviceInfo) * deviceCount);
|
||||
|
||||
for (i = 0; i < paWasapi->deviceCount; ++i)
|
||||
{
|
||||
|
|
@ -1596,11 +1587,11 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
|
||||
if (lstrcmpW(paWasapi->devInfo[i].szDeviceID, paWasapi->defaultCapturer) == 0)
|
||||
{// we found the default input!
|
||||
(*hostApi)->info.defaultInputDevice = (*hostApi)->info.deviceCount;
|
||||
hostApi->info.defaultInputDevice = hostApi->info.deviceCount;
|
||||
}
|
||||
if (lstrcmpW(paWasapi->devInfo[i].szDeviceID, paWasapi->defaultRenderer) == 0)
|
||||
{// we found the default output!
|
||||
(*hostApi)->info.defaultOutputDevice = (*hostApi)->info.deviceCount;
|
||||
hostApi->info.defaultOutputDevice = hostApi->info.deviceCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1623,25 +1614,21 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
|
||||
// "Friendly" Name
|
||||
{
|
||||
char *deviceName;
|
||||
PROPVARIANT value;
|
||||
PropVariantInit(&value);
|
||||
hr = IPropertyStore_GetValue(pProperty, &PKEY_Device_FriendlyName, &value);
|
||||
// We need to set the result to a value otherwise we will return paNoError
|
||||
// [IF_FAILED_JUMP(hResult, error);]
|
||||
IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
|
||||
deviceInfo->name = NULL;
|
||||
deviceName = (char *)PaUtil_GroupAllocateMemory(paWasapi->allocations, MAX_STR_LEN + 1);
|
||||
if (deviceName == NULL)
|
||||
if ((deviceInfo->name = (char *)PaUtil_GroupAllocateMemory(paWasapi->allocations, MAX_STR_LEN + 1)) == NULL)
|
||||
{
|
||||
result = paInsufficientMemory;
|
||||
goto error;
|
||||
}
|
||||
if (value.pwszVal)
|
||||
WideCharToMultiByte(CP_UTF8, 0, value.pwszVal, (int)wcslen(value.pwszVal), deviceName, MAX_STR_LEN - 1, 0, 0);
|
||||
WideCharToMultiByte(CP_UTF8, 0, value.pwszVal, (int)wcslen(value.pwszVal), (char *)deviceInfo->name, MAX_STR_LEN - 1, 0, 0);
|
||||
else
|
||||
_snprintf(deviceName, MAX_STR_LEN - 1, "baddev%d", i);
|
||||
deviceInfo->name = deviceName;
|
||||
_snprintf((char *)deviceInfo->name, MAX_STR_LEN - 1, "baddev%d", i);
|
||||
PropVariantClear(&value);
|
||||
PA_DEBUG(("WASAPI:%d| name[%s]\n", i, deviceInfo->name));
|
||||
}
|
||||
|
|
@ -1706,7 +1693,6 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
#endif
|
||||
|
||||
// Create temp Audio Client instance to query additional details
|
||||
IAudioClient *tmpClient = NULL;
|
||||
hr = ActivateAudioInterface(&paWasapi->devInfo[i], &tmpClient);
|
||||
// We need to set the result to a value otherwise we will return paNoError
|
||||
// [IF_FAILED_JUMP(hResult, error);]
|
||||
|
|
@ -1735,9 +1721,9 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
{
|
||||
// Default device
|
||||
if (i == 0)
|
||||
(*hostApi)->info.defaultOutputDevice = (*hostApi)->info.deviceCount;
|
||||
hostApi->info.defaultOutputDevice = hostApi->info.deviceCount;
|
||||
else
|
||||
(*hostApi)->info.defaultInputDevice = (*hostApi)->info.deviceCount;
|
||||
hostApi->info.defaultInputDevice = hostApi->info.deviceCount;
|
||||
|
||||
// State
|
||||
paWasapi->devInfo[i].state = DEVICE_STATE_ACTIVE;
|
||||
|
|
@ -1750,8 +1736,7 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
paWasapi->devInfo[i].formFactor = UnknownFormFactor;
|
||||
|
||||
// Name
|
||||
deviceInfo->name = (char *)PaUtil_GroupAllocateMemory(paWasapi->allocations, MAX_STR_LEN + 1);
|
||||
if (deviceInfo->name == NULL)
|
||||
if ((deviceInfo->name = (char *)PaUtil_GroupAllocateMemory(paWasapi->allocations, MAX_STR_LEN + 1)) == NULL)
|
||||
{
|
||||
SAFE_RELEASE(tmpClient);
|
||||
result = paInsufficientMemory;
|
||||
|
|
@ -1805,14 +1790,109 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
break;
|
||||
}
|
||||
|
||||
(*hostApi)->deviceInfos[i] = deviceInfo;
|
||||
++(*hostApi)->info.deviceCount;
|
||||
hostApi->deviceInfos[i] = deviceInfo;
|
||||
++hostApi->info.deviceCount;
|
||||
}
|
||||
|
||||
#if defined(PA_WASAPI_MAX_CONST_DEVICE_COUNT) && (PA_WASAPI_MAX_CONST_DEVICE_COUNT > 0)
|
||||
if (hostApi->info.deviceCount < PA_WASAPI_MAX_CONST_DEVICE_COUNT)
|
||||
{
|
||||
for (i = hostApi->info.deviceCount; i < PA_WASAPI_MAX_CONST_DEVICE_COUNT; ++i)
|
||||
{
|
||||
PaDeviceInfo *deviceInfo = &deviceInfoArray[i];
|
||||
deviceInfo->structVersion = 2;
|
||||
deviceInfo->hostApi = hostApiIndex;
|
||||
|
||||
if ((deviceInfo->name = (char *)PaUtil_GroupAllocateMemory(paWasapi->allocations, 1)) == NULL)
|
||||
{
|
||||
result = paInsufficientMemory;
|
||||
goto error;
|
||||
}
|
||||
((char *)deviceInfo->name)[0] = 0;
|
||||
|
||||
hostApi->deviceInfos[i] = deviceInfo;
|
||||
++hostApi->info.deviceCount;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
(*hostApi)->Terminate = Terminate;
|
||||
(*hostApi)->OpenStream = OpenStream;
|
||||
(*hostApi)->IsFormatSupported = IsFormatSupported;
|
||||
#ifndef PA_WINRT
|
||||
SAFE_RELEASE(pEndPoints);
|
||||
SAFE_RELEASE(pEnumerator);
|
||||
#endif
|
||||
|
||||
PRINT(("WASAPI: device list created ok\n"));
|
||||
|
||||
return paNoError;
|
||||
|
||||
error:
|
||||
|
||||
PRINT(("WASAPI: failed %s error[%d|%s]\n", __FUNCTION__, result, Pa_GetErrorText(result)));
|
||||
|
||||
#ifndef PA_WINRT
|
||||
SAFE_RELEASE(pEndPoints);
|
||||
SAFE_RELEASE(pEnumerator);
|
||||
#endif
|
||||
|
||||
// Safety if error was not set so that we do not think initialize was a success
|
||||
if (result == paNoError)
|
||||
result = paInternalError;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
|
||||
{
|
||||
PaError result = paInternalError;
|
||||
PaWasapiHostApiRepresentation *paWasapi;
|
||||
|
||||
#ifndef PA_WINRT
|
||||
if (!SetupAVRT())
|
||||
{
|
||||
PRINT(("WASAPI: No AVRT! (not VISTA?)"));
|
||||
return paNoError;
|
||||
}
|
||||
#endif
|
||||
|
||||
paWasapi = (PaWasapiHostApiRepresentation *)PaUtil_AllocateMemory(sizeof(PaWasapiHostApiRepresentation));
|
||||
if (paWasapi == NULL)
|
||||
{
|
||||
result = paInsufficientMemory;
|
||||
goto error;
|
||||
}
|
||||
memset(paWasapi, 0, sizeof(PaWasapiHostApiRepresentation)); /* ensure all fields are zeroed. especially paWasapi->allocations */
|
||||
|
||||
result = PaWinUtil_CoInitialize(paWASAPI, &paWasapi->comInitializationResult);
|
||||
if (result != paNoError)
|
||||
goto error;
|
||||
|
||||
paWasapi->allocations = PaUtil_CreateAllocationGroup();
|
||||
if (paWasapi->allocations == NULL)
|
||||
{
|
||||
result = paInsufficientMemory;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Fill basic interface info
|
||||
*hostApi = &paWasapi->inheritedHostApiRep;
|
||||
(*hostApi)->info.structVersion = 1;
|
||||
(*hostApi)->info.type = paWASAPI;
|
||||
(*hostApi)->info.name = "Windows WASAPI";
|
||||
(*hostApi)->info.deviceCount = 0;
|
||||
(*hostApi)->info.defaultInputDevice = paNoDevice;
|
||||
(*hostApi)->info.defaultOutputDevice = paNoDevice;
|
||||
(*hostApi)->Terminate = Terminate;
|
||||
(*hostApi)->OpenStream = OpenStream;
|
||||
(*hostApi)->IsFormatSupported = IsFormatSupported;
|
||||
|
||||
// Fill the device list
|
||||
if ((result = CreateDeviceList(paWasapi, hostApiIndex)) != paNoError)
|
||||
goto error;
|
||||
|
||||
// Detect if platform workaround is required
|
||||
paWasapi->useWOW64Workaround = UseWOW64Workaround();
|
||||
|
||||
PaUtil_InitializeStreamInterface( &paWasapi->callbackStreamInterface, CloseStream, StartStream,
|
||||
StopStream, AbortStream, IsStreamStopped, IsStreamActive,
|
||||
|
|
@ -1825,14 +1905,6 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
GetStreamTime, PaUtil_DummyGetCpuLoad,
|
||||
ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable );
|
||||
|
||||
|
||||
// findout if platform workaround is required
|
||||
paWasapi->useWOW64Workaround = UseWOW64Workaround();
|
||||
|
||||
#ifndef PA_WINRT
|
||||
SAFE_RELEASE(pEndPoints);
|
||||
#endif
|
||||
|
||||
PRINT(("WASAPI: initialized ok\n"));
|
||||
|
||||
return paNoError;
|
||||
|
|
@ -1841,46 +1913,38 @@ error:
|
|||
|
||||
PRINT(("WASAPI: failed %s error[%d|%s]\n", __FUNCTION__, result, Pa_GetErrorText(result)));
|
||||
|
||||
#ifndef PA_WINRT
|
||||
SAFE_RELEASE(pEndPoints);
|
||||
#endif
|
||||
|
||||
Terminate((PaUtilHostApiRepresentation *)paWasapi);
|
||||
|
||||
// Safety if error was not set so that we do not think initialize was a success
|
||||
if (result == paNoError) {
|
||||
result = paInternalError;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
static void Terminate( PaUtilHostApiRepresentation *hostApi )
|
||||
static void ReleaseWasapiDeviceInfoList( PaWasapiHostApiRepresentation *paWasapi )
|
||||
{
|
||||
UINT i;
|
||||
PaWasapiHostApiRepresentation *paWasapi = (PaWasapiHostApiRepresentation*)hostApi;
|
||||
if (paWasapi == NULL)
|
||||
return;
|
||||
|
||||
// Release IMMDeviceEnumerator
|
||||
#ifndef PA_WINRT
|
||||
SAFE_RELEASE(paWasapi->enumerator);
|
||||
#endif
|
||||
UINT32 i;
|
||||
|
||||
// Release device info bound objects and device info itself
|
||||
for (i = 0; i < paWasapi->deviceCount; ++i)
|
||||
{
|
||||
PaWasapiDeviceInfo *info = &paWasapi->devInfo[i];
|
||||
#ifndef PA_WINRT
|
||||
SAFE_RELEASE(info->device);
|
||||
#else
|
||||
(void)info;
|
||||
SAFE_RELEASE(paWasapi->devInfo[i].device);
|
||||
#endif
|
||||
}
|
||||
PaUtil_FreeMemory(paWasapi->devInfo);
|
||||
|
||||
if (paWasapi->allocations)
|
||||
paWasapi->deviceCount = 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
static void Terminate( PaUtilHostApiRepresentation *hostApi )
|
||||
{
|
||||
PaWasapiHostApiRepresentation *paWasapi = (PaWasapiHostApiRepresentation*)hostApi;
|
||||
if (paWasapi == NULL)
|
||||
return;
|
||||
|
||||
ReleaseWasapiDeviceInfoList(paWasapi);
|
||||
|
||||
if (paWasapi->allocations != NULL)
|
||||
{
|
||||
PaUtil_FreeAllAllocations(paWasapi->allocations);
|
||||
PaUtil_DestroyAllocationGroup(paWasapi->allocations);
|
||||
|
|
@ -1910,6 +1974,52 @@ static PaWasapiHostApiRepresentation *_GetHostApi(PaError *_error)
|
|||
return (PaWasapiHostApiRepresentation *)pApi;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
static PaError UpdateDeviceList()
|
||||
{
|
||||
int i;
|
||||
PaError ret;
|
||||
PaWasapiHostApiRepresentation *paWasapi;
|
||||
PaUtilHostApiRepresentation *hostApi;
|
||||
|
||||
// Get API
|
||||
hostApi = (PaUtilHostApiRepresentation *)(paWasapi = _GetHostApi(&ret));
|
||||
if (paWasapi == NULL)
|
||||
return ret;
|
||||
|
||||
// Release WASAPI internal device info list
|
||||
ReleaseWasapiDeviceInfoList(paWasapi);
|
||||
|
||||
// Release external device info list
|
||||
if (hostApi->deviceInfos != NULL)
|
||||
{
|
||||
for (i = 0; i < hostApi->info.deviceCount; ++i)
|
||||
{
|
||||
PaUtil_GroupFreeMemory(paWasapi->allocations, (void *)hostApi->deviceInfos[i]->name);
|
||||
}
|
||||
PaUtil_GroupFreeMemory(paWasapi->allocations, hostApi->deviceInfos[0]);
|
||||
PaUtil_GroupFreeMemory(paWasapi->allocations, hostApi->deviceInfos);
|
||||
|
||||
hostApi->info.deviceCount = 0;
|
||||
hostApi->info.defaultInputDevice = paNoDevice;
|
||||
hostApi->info.defaultOutputDevice = paNoDevice;
|
||||
}
|
||||
|
||||
// Fill possibly updated device list
|
||||
if ((ret = CreateDeviceList(paWasapi, Pa_HostApiTypeIdToHostApiIndex(paWASAPI))) != paNoError)
|
||||
return ret;
|
||||
|
||||
return paNoError;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
#if defined(PA_WASAPI_MAX_CONST_DEVICE_COUNT) && (PA_WASAPI_MAX_CONST_DEVICE_COUNT > 0)
|
||||
PaError PaWasapi_UpdateDeviceList()
|
||||
{
|
||||
return UpdateDeviceList();
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice )
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue