wasapi: new PaWasapi_GetAudioClient() API to get pointer to IAudioClient from PaStream, workaround to get real Windows version in order to be able to create correct version of IAudioClient interface (Windows 10 was reported as Windows 8 when using just GetVersion())

This commit is contained in:
dmitrykos 2018-06-30 12:21:59 +03:00
commit a802290e83
2 changed files with 73 additions and 18 deletions

View file

@ -291,6 +291,17 @@ typedef struct PaWasapiStreamInfo
PaWasapiStreamInfo;
/** Returns pointer to WASAPI's IAudioClient object of the stream.
@param pStream Pointer to PaStream.
@param pAudioClient Pointer to pointer of IAudioClient.
@param bOutput TRUE (1) for output stream, FALSE (0) for input stream.
@return Error code indicating success or failure.
*/
PaError PaWasapi_GetAudioClient( PaStream *pStream, void **pAudioClient, int bOutput );
/** Update device list.
This function is available if PA_WASAPI_MAX_CONST_DEVICE_COUNT is defined during compile time
with maximum constant WASAPI device count (recommended value - 32).
@ -374,7 +385,7 @@ PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *nInput
@return Error code indicating success or failure
@see PaWasapi_GetJackDescription
*/
PaError PaWasapi_GetJackCount(PaDeviceIndex nDevice, int *jcount);
PaError PaWasapi_GetJackCount( PaDeviceIndex nDevice, int *jcount );
/** Get the jack description associated with a WASAPI device and jack number
@ -389,7 +400,7 @@ PaError PaWasapi_GetJackCount(PaDeviceIndex nDevice, int *jcount);
@return Error code indicating success or failure
@see PaWasapi_GetJackCount
*/
PaError PaWasapi_GetJackDescription(PaDeviceIndex nDevice, int jindex, PaWasapiJackDescription *pJackDescription);
PaError PaWasapi_GetJackDescription( PaDeviceIndex nDevice, int jindex, PaWasapiJackDescription *pJackDescription );
/*

View file

@ -988,29 +988,57 @@ static EWindowsVersion GetWindowsVersion()
if (version == WINDOWS_UNKNOWN)
{
DWORD dwVersion = 0;
DWORD dwMajorVersion = 0;
DWORD dwMinorVersion = 0;
DWORD dwBuild = 0;
DWORD dwMajorVersion = 0xFFFFFFFFU, dwMinorVersion = 0, dwBuild = 0;
// RTL_OSVERSIONINFOW equals OSVERSIONINFOW but it is missing inb MinGW winnt.h header,
// thus use OSVERSIONINFOW for greater portability
typedef NTSTATUS (WINAPI *LPFN_RTLGETVERSION)(POSVERSIONINFOW lpVersionInformation);
LPFN_RTLGETVERSION fnRtlGetVersion;
typedef DWORD (WINAPI *LPFN_GETVERSION)(VOID);
LPFN_GETVERSION fnGetVersion;
#define NTSTATUS_SUCCESS ((NTSTATUS)0x00000000L)
fnGetVersion = (LPFN_GETVERSION)GetProcAddress(GetModuleHandleA("kernel32"), "GetVersion");
if (fnGetVersion != NULL)
// RtlGetVersion must be able to provide true Windows version (Windows 10 may be reported as Windows 8
// by GetVersion API)
if ((fnRtlGetVersion = (LPFN_RTLGETVERSION)GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion")) != NULL)
{
PRINT(("WASAPI: getting Windows version with GetVersion()\n"));
OSVERSIONINFOW ver = { sizeof(OSVERSIONINFOW), 0, 0, 0, {0} };
dwVersion = fnGetVersion();
PRINT(("WASAPI: getting Windows version with RtlGetVersion()\n"));
// Get the Windows version
dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
if (fnRtlGetVersion(&ver) == NTSTATUS_SUCCESS)
{
dwMajorVersion = ver.dwMajorVersion;
dwMinorVersion = ver.dwMinorVersion;
dwBuild = ver.dwBuildNumber;
}
}
// Get the build number
if (dwVersion < 0x80000000)
dwBuild = (DWORD)(HIWORD(dwVersion));
#undef NTSTATUS_SUCCESS
// fallback to GetVersion if RtlGetVersion is missing
if (dwMajorVersion == 0xFFFFFFFFU)
{
typedef DWORD (WINAPI *LPFN_GETVERSION)(VOID);
LPFN_GETVERSION fnGetVersion;
if ((fnGetVersion = (LPFN_GETVERSION)GetProcAddress(GetModuleHandleA("kernel32"), "GetVersion")) != NULL)
{
DWORD dwVersion;
PRINT(("WASAPI: getting Windows version with GetVersion()\n"));
dwVersion = fnGetVersion();
dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
if (dwVersion < 0x80000000)
dwBuild = (DWORD)(HIWORD(dwVersion));
}
}
if (dwMajorVersion != 0xFFFFFFFFU)
{
switch (dwMajorVersion)
{
case 0:
@ -1042,6 +1070,7 @@ static EWindowsVersion GetWindowsVersion()
break;
}
}
// fallback to VerifyVersionInfo if RtlGetVersion and GetVersion are missing
else
{
PRINT(("WASAPI: getting Windows version with VerifyVersionInfo()\n"));
@ -4883,6 +4912,21 @@ error:
#endif
}
// ------------------------------------------------------------------------------------------
PaError PaWasapi_GetAudioClient(PaStream *pStream, void **pAudioClient, int bOutput)
{
if (pAudioClient == NULL)
return paUnanticipatedHostError;
PaWasapiStream *stream = (PaWasapiStream *)pStream;
if (stream == NULL)
return paBadStreamPtr;
(*pAudioClient) = (bOutput == TRUE ? stream->out.clientParent : stream->in.clientParent);
return paNoError;
}
// ------------------------------------------------------------------------------------------
HRESULT _PollGetOutputFramesAvailable(PaWasapiStream *stream, UINT32 *available)
{