From: dmitrykos Date: Sat, 30 Jun 2018 09:21:59 +0000 (+0300) Subject: wasapi: new PaWasapi_GetAudioClient() API to get pointer to IAudioClient from PaStrea... X-Git-Tag: v19.7.0~139^2 X-Git-Url: https://andrewgundersen.net/repos?a=commitdiff_plain;h=a802290e831cd8959801fcb1e634a5d28c0ea30d;p=portaudio 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()) --- diff --git a/include/pa_win_wasapi.h b/include/pa_win_wasapi.h index a863706..c7bfde2 100644 --- a/include/pa_win_wasapi.h +++ b/include/pa_win_wasapi.h @@ -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 ); /* diff --git a/src/hostapi/wasapi/pa_win_wasapi.c b/src/hostapi/wasapi/pa_win_wasapi.c index d1d0278..3c35816 100644 --- a/src/hostapi/wasapi/pa_win_wasapi.c +++ b/src/hostapi/wasapi/pa_win_wasapi.c @@ -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; + + #define NTSTATUS_SUCCESS ((NTSTATUS)0x00000000L) + + // 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) + { + OSVERSIONINFOW ver = { sizeof(OSVERSIONINFOW), 0, 0, 0, {0} }; + + PRINT(("WASAPI: getting Windows version with RtlGetVersion()\n")); + + if (fnRtlGetVersion(&ver) == NTSTATUS_SUCCESS) + { + dwMajorVersion = ver.dwMajorVersion; + dwMinorVersion = ver.dwMinorVersion; + dwBuild = ver.dwBuildNumber; + } + } - typedef DWORD (WINAPI *LPFN_GETVERSION)(VOID); - LPFN_GETVERSION fnGetVersion; + #undef NTSTATUS_SUCCESS - fnGetVersion = (LPFN_GETVERSION)GetProcAddress(GetModuleHandleA("kernel32"), "GetVersion"); - if (fnGetVersion != NULL) + // fallback to GetVersion if RtlGetVersion is missing + if (dwMajorVersion == 0xFFFFFFFFU) { - PRINT(("WASAPI: getting Windows version with GetVersion()\n")); + typedef DWORD (WINAPI *LPFN_GETVERSION)(VOID); + LPFN_GETVERSION fnGetVersion; + + if ((fnGetVersion = (LPFN_GETVERSION)GetProcAddress(GetModuleHandleA("kernel32"), "GetVersion")) != NULL) + { + DWORD dwVersion; - dwVersion = fnGetVersion(); + PRINT(("WASAPI: getting Windows version with GetVersion()\n")); - // Get the Windows version - dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); - dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); + dwVersion = fnGetVersion(); - // Get the build number - if (dwVersion < 0x80000000) - dwBuild = (DWORD)(HIWORD(dwVersion)); + 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) {