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; - 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) {