Merge branch 'winrt' into 'master'

New PaWasapi_GetAudioClient() API and workaround to get real Windows version and thus use correct AudioClient interface version.

Merged-on: https://assembla.com/code/portaudio/git/merge_requests/6574173
This commit is contained in:
Dmitry Kostjuchenko 2018-07-01 10:04:03 +00:00
commit 64ad96ea3c
2 changed files with 73 additions and 18 deletions

View file

@ -291,6 +291,17 @@ typedef struct PaWasapiStreamInfo
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. /** Update device list.
This function is available if PA_WASAPI_MAX_CONST_DEVICE_COUNT is defined during compile time 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). 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 @return Error code indicating success or failure
@see PaWasapi_GetJackDescription @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 /** 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 @return Error code indicating success or failure
@see PaWasapi_GetJackCount @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) if (version == WINDOWS_UNKNOWN)
{ {
DWORD dwVersion = 0; DWORD dwMajorVersion = 0xFFFFFFFFU, dwMinorVersion = 0, dwBuild = 0;
DWORD dwMajorVersion = 0;
DWORD dwMinorVersion = 0; // RTL_OSVERSIONINFOW equals OSVERSIONINFOW but it is missing inb MinGW winnt.h header,
DWORD dwBuild = 0; // thus use OSVERSIONINFOW for greater portability
typedef NTSTATUS (WINAPI *LPFN_RTLGETVERSION)(POSVERSIONINFOW lpVersionInformation);
LPFN_RTLGETVERSION fnRtlGetVersion;
typedef DWORD (WINAPI *LPFN_GETVERSION)(VOID); #define NTSTATUS_SUCCESS ((NTSTATUS)0x00000000L)
LPFN_GETVERSION fnGetVersion;
fnGetVersion = (LPFN_GETVERSION)GetProcAddress(GetModuleHandleA("kernel32"), "GetVersion"); // RtlGetVersion must be able to provide true Windows version (Windows 10 may be reported as Windows 8
if (fnGetVersion != NULL) // 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 if (fnRtlGetVersion(&ver) == NTSTATUS_SUCCESS)
dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); {
dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); dwMajorVersion = ver.dwMajorVersion;
dwMinorVersion = ver.dwMinorVersion;
dwBuild = ver.dwBuildNumber;
}
}
// Get the build number #undef NTSTATUS_SUCCESS
if (dwVersion < 0x80000000)
dwBuild = (DWORD)(HIWORD(dwVersion));
// 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) switch (dwMajorVersion)
{ {
case 0: case 0:
@ -1042,6 +1070,7 @@ static EWindowsVersion GetWindowsVersion()
break; break;
} }
} }
// fallback to VerifyVersionInfo if RtlGetVersion and GetVersion are missing
else else
{ {
PRINT(("WASAPI: getting Windows version with VerifyVersionInfo()\n")); PRINT(("WASAPI: getting Windows version with VerifyVersionInfo()\n"));
@ -4883,6 +4912,21 @@ error:
#endif #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) HRESULT _PollGetOutputFramesAvailable(PaWasapiStream *stream, UINT32 *available)
{ {