method can only provide 15-20ms latency. */\r
paWinWasapiPolling = (1 << 3),\r
\r
- /* forces custom thread priority setting. must be used if PaWasapiStreamInfo::threadPriority \r
- is set to custom value. */\r
+ /* forces custom thread priority setting, must be used if PaWasapiStreamInfo::threadPriority \r
+ is set to a custom value */\r
paWinWasapiThreadPriority = (1 << 4)\r
}\r
PaWasapiFlags;\r
void *outputBuffer, long outputFrames,\r
void *userData);\r
\r
-/* Device role */\r
+/* Device role. */\r
typedef enum PaWasapiDeviceRole\r
{\r
eRoleRemoteNetworkDevice = 0,\r
PaWasapiDeviceRole;\r
\r
\r
-/* Jack connection type */\r
+/* Jack connection type. */\r
typedef enum PaWasapiJackConnectionType\r
{\r
eJackConnTypeUnknown,\r
PaWasapiJackConnectionType;\r
\r
\r
-/* Jack geometric location */\r
+/* Jack geometric location. */\r
typedef enum PaWasapiJackGeoLocation\r
{\r
- eJackGeoLocUnk = 0,\r
+ eJackGeoLocUnk = 0,\r
eJackGeoLocRear = 0x1, /* matches EPcxGeoLocation::eGeoLocRear */\r
eJackGeoLocFront,\r
eJackGeoLocLeft,\r
PaWasapiJackGeoLocation;\r
\r
\r
-/* Jack general location */\r
+/* Jack general location. */\r
typedef enum PaWasapiJackGenLocation\r
{\r
eJackGenLocPrimaryBox = 0,\r
PaWasapiJackGenLocation;\r
\r
\r
-/* Jack's type of port */\r
+/* Jack's type of port. */\r
typedef enum PaWasapiJackPortConnection\r
{\r
eJackPortConnJack = 0,\r
PaWasapiJackPortConnection;\r
\r
\r
-/* Thread priority */\r
+/* Thread priority. */\r
typedef enum PaWasapiThreadPriority\r
{\r
eThreadPriorityNone = 0,\r
PaWasapiJackDescription;\r
\r
\r
+/* Stream category.\r
+ Note:\r
+ - values are equal to WASAPI AUDIO_STREAM_CATEGORY enum\r
+ - supported since Windows 8.0, noop on earler versions\r
+ - values 1,2 are deprecated on Windows 10 and not included into enumeration\r
+*/\r
+typedef enum PaWasapiStreamCategory\r
+{\r
+ eAudioCategoryOther = 0,\r
+ eAudioCategoryCommunications = 3,\r
+ eAudioCategoryAlerts = 4,\r
+ eAudioCategorySoundEffects = 5,\r
+ eAudioCategoryGameEffects = 6,\r
+ eAudioCategoryGameMedia = 7,\r
+ eAudioCategoryGameChat = 8,\r
+ eAudioCategorySpeech = 9,\r
+ eAudioCategoryMovie = 10,\r
+ eAudioCategoryMedia = 11\r
+}\r
+PaWasapiStreamCategory;\r
+\r
+\r
+/* Stream option.\r
+ Note:\r
+ - values are equal to WASAPI AUDCLNT_STREAMOPTIONS enum\r
+ - supported since Windows 8.1, noop on earler versions\r
+*/\r
+typedef enum PaWasapiStreamOption\r
+{\r
+ eStreamOptionNone = 0, //!< default\r
+ eStreamOptionRaw = 1, //!< bypass WASAPI Audio Engine DSP effects, supported since Windows 8.1\r
+ eStreamOptionMatchFormat = 2 //!< force WASAPI Audio Engine into a stream format, supported since Windows 10\r
+}\r
+PaWasapiStreamOption;\r
+\r
+\r
/* Stream descriptor. */\r
typedef struct PaWasapiStreamInfo \r
{\r
to setup thread priority.\r
*/\r
PaWasapiThreadPriority threadPriority;\r
+\r
+ /* Stream category. */\r
+ PaWasapiStreamCategory streamCategory;\r
+\r
+ /* Stream option. */\r
+ PaWasapiStreamOption streamOption;\r
} \r
PaWasapiStreamInfo;\r
\r
\r
/** Get number of jacks associated with a WASAPI device. Use this method to determine if\r
there are any jacks associated with the provided WASAPI device. Not all audio devices\r
- will support this capability. This is valid for both input and output devices.\r
+ will support this capability. This is valid for both input and output devices.\r
@param nDevice device index.\r
@param jcount Number of jacks is returned in this variable\r
@return Error code indicating success or failure\r
\r
/** Get the jack description associated with a WASAPI device and jack number\r
Before this function is called, use PaWasapi_GetJackCount to determine the\r
- number of jacks associated with device. If jcount is greater than zero, then\r
- each jack from 0 to jcount can be queried with this function to get the jack\r
- description.\r
+ number of jacks associated with device. If jcount is greater than zero, then\r
+ each jack from 0 to jcount can be queried with this function to get the jack\r
+ description.\r
@param nDevice device index.\r
@param jindex Which jack to return information\r
@param KSJACK_DESCRIPTION This structure filled in on success.\r
This is the most powerful WASAPI implementation which provides glitch-free\r
audio at around 3ms latency in Exclusive mode. Lowest possible latency for this mode is \r
3 ms for HD Audio class audio chips. For the Shared mode latency can not be \r
- lower than 20 ms.\r
+ lower than 20 ms.\r
\r
2) Poll-Driven:\r
Polling is another 2-nd method to operate with WASAPI. It is less efficient than Event-Driven\r
\r
// "1CB9AD4C-DBFA-4c32-B178-C2F568A703B2"\r
PA_DEFINE_IID(IAudioClient, 1cb9ad4c, dbfa, 4c32, b1, 78, c2, f5, 68, a7, 03, b2);\r
+// "726778CD-F60A-4EDA-82DE-E47610CD78AA"\r
+PA_DEFINE_IID(IAudioClient2, 726778cd, f60a, 4eda, 82, de, e4, 76, 10, cd, 78, aa);\r
// "1BE09788-6894-4089-8586-9A2A6C265AC5"\r
PA_DEFINE_IID(IMMEndpoint, 1be09788, 6894, 4089, 85, 86, 9a, 2a, 6c, 26, 5a, c5);\r
// "A95664D2-9614-4F35-A746-DE8DB63617E6"\r
__DEFINE_GUID(pa_KSDATAFORMAT_SUBTYPE_ADPCM, 0x00000002, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );\r
__DEFINE_GUID(pa_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );\r
\r
+#ifdef __IAudioClient2_INTERFACE_DEFINED__\r
+typedef enum _pa_AUDCLNT_STREAMOPTIONS { \r
+ pa_AUDCLNT_STREAMOPTIONS_NONE = 0x00,\r
+ pa_AUDCLNT_STREAMOPTIONS_RAW = 0x01,\r
+ pa_AUDCLNT_STREAMOPTIONS_MATCH_FORMAT = 0x02\r
+} pa_AUDCLNT_STREAMOPTIONS;\r
+typedef struct _pa_AudioClientProperties {\r
+ UINT32 cbSize;\r
+ BOOL bIsOffload;\r
+ AUDIO_STREAM_CATEGORY eCategory;\r
+ pa_AUDCLNT_STREAMOPTIONS Options;\r
+} pa_AudioClientProperties;\r
+#define PA_AUDIOCLIENTPROPERTIES_SIZE_CATEGORY (sizeof(pa_AudioClientProperties) - sizeof(pa_AUDCLNT_STREAMOPTIONS))\r
+#define PA_AUDIOCLIENTPROPERTIES_SIZE_OPTIONS sizeof(pa_AudioClientProperties)\r
+#endif // __IAudioClient2_INTERFACE_DEFINED__\r
+\r
/* use CreateThread for CYGWIN/Windows Mobile, _beginthreadex for all others */\r
#if !defined(__CYGWIN__) && !defined(_WIN32_WCE)\r
#define CREATE_THREAD(PROC) (HANDLE)_beginthreadex( NULL, 0, (PROC), stream, 0, &stream->dwThreadId )\r
}\r
PaWasapiStream;\r
\r
+// COM marshaling\r
+static HRESULT MarshalSubStreamComPointers(PaWasapiSubStream *substream);\r
+static HRESULT MarshalStreamComPointers(PaWasapiStream *stream);\r
+static HRESULT UnmarshalSubStreamComPointers(PaWasapiSubStream *substream);\r
+static HRESULT UnmarshalStreamComPointers(PaWasapiStream *stream);\r
+static void ReleaseUnmarshaledSubComPointers(PaWasapiSubStream *substream);\r
+static void ReleaseUnmarshaledComPointers(PaWasapiStream *stream);\r
+\r
// Local stream methods\r
-void _StreamOnStop(PaWasapiStream *stream);\r
-void _StreamFinish(PaWasapiStream *stream);\r
-void _StreamCleanup(PaWasapiStream *stream);\r
-HRESULT _PollGetOutputFramesAvailable(PaWasapiStream *stream, UINT32 *available);\r
-HRESULT _PollGetInputFramesAvailable(PaWasapiStream *stream, UINT32 *available);\r
-void *PaWasapi_ReallocateMemory(void *ptr, size_t size);\r
-void PaWasapi_FreeMemory(void *ptr);\r
+static void _StreamOnStop(PaWasapiStream *stream);\r
+static void _StreamFinish(PaWasapiStream *stream);\r
+static void _StreamCleanup(PaWasapiStream *stream);\r
+static HRESULT _PollGetOutputFramesAvailable(PaWasapiStream *stream, UINT32 *available);\r
+static HRESULT _PollGetInputFramesAvailable(PaWasapiStream *stream, UINT32 *available);\r
+static void *PaWasapi_ReallocateMemory(void *ptr, size_t size);\r
+static void PaWasapi_FreeMemory(void *ptr);\r
\r
// Local statics\r
\r
// ------------------------------------------------------------------------------------------\r
typedef enum EWindowsVersion\r
{\r
- WINDOWS_UNKNOWN = 0,\r
- WINDOWS_VISTA_SERVER2008 = (1 << 0),\r
- WINDOWS_7_SERVER2008R2 = (1 << 1),\r
- WINDOWS_FUTURE = (1 << 2)\r
+ WINDOWS_UNKNOWN = 0,\r
+ WINDOWS_VISTA_SERVER2008,\r
+ WINDOWS_7_SERVER2008R2,\r
+ WINDOWS_8_SERVER2012,\r
+ WINDOWS_8_1_SERVER2012R2,\r
+ WINDOWS_10_SERVER2016,\r
+ WINDOWS_FUTURE\r
}\r
EWindowsVersion;\r
-// Defines Windows 7/Windows Server 2008 R2 and up (future versions)\r
-#define WINDOWS_7_SERVER2008R2_AND_UP (WINDOWS_7_SERVER2008R2|WINDOWS_FUTURE)\r
-// The function is limited to Vista/7 mostly as we need just to find out Vista/WOW64 combination\r
-// in order to use WASAPI WOW64 workarounds.\r
-static UINT32 GetWindowsVersion()\r
+// Alternative way for checking Windows version (allows to check version on Windows 8.1 and up)\r
+static BOOL IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)\r
+{\r
+ typedef ULONGLONG (NTAPI *LPFN_VERSETCONDITIONMASK)(ULONGLONG ConditionMask, DWORD TypeMask, BYTE Condition);\r
+ typedef BOOL (WINAPI *LPFN_VERIFYVERSIONINFO)(LPOSVERSIONINFOEXA lpVersionInformation, DWORD dwTypeMask, DWORDLONG dwlConditionMask);\r
+\r
+ LPFN_VERSETCONDITIONMASK fnVerSetConditionMask;\r
+ LPFN_VERIFYVERSIONINFO fnVerifyVersionInfo;\r
+ OSVERSIONINFOEXA osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 };\r
+ DWORDLONG dwlConditionMask;\r
+\r
+ fnVerSetConditionMask = (LPFN_VERSETCONDITIONMASK)GetProcAddress(GetModuleHandleA("kernel32"), "VerSetConditionMask");\r
+ fnVerifyVersionInfo = (LPFN_VERIFYVERSIONINFO)GetProcAddress(GetModuleHandleA("kernel32"), "VerifyVersionInfoA");\r
+\r
+ if ((fnVerSetConditionMask == NULL) || (fnVerifyVersionInfo == NULL))\r
+ return FALSE;\r
+\r
+ dwlConditionMask = fnVerSetConditionMask(\r
+ fnVerSetConditionMask(\r
+ fnVerSetConditionMask(\r
+ 0, VER_MAJORVERSION, VER_GREATER_EQUAL),\r
+ VER_MINORVERSION, VER_GREATER_EQUAL),\r
+ VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);\r
+\r
+ osvi.dwMajorVersion = wMajorVersion;\r
+ osvi.dwMinorVersion = wMinorVersion;\r
+ osvi.wServicePackMajor = wServicePackMajor;\r
+\r
+ return (fnVerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE);\r
+}\r
+// Get Windows version\r
+static EWindowsVersion GetWindowsVersion()\r
{\r
- static UINT32 version = WINDOWS_UNKNOWN;\r
+ static EWindowsVersion version = WINDOWS_UNKNOWN;\r
\r
if (version == WINDOWS_UNKNOWN)\r
{\r
typedef DWORD (WINAPI *LPFN_GETVERSION)(VOID);\r
LPFN_GETVERSION fnGetVersion;\r
\r
- fnGetVersion = (LPFN_GETVERSION) GetProcAddress(GetModuleHandleA("kernel32"), "GetVersion");\r
- if (fnGetVersion == NULL)\r
- return WINDOWS_UNKNOWN;\r
+ fnGetVersion = (LPFN_GETVERSION)GetProcAddress(GetModuleHandleA("kernel32"), "GetVersion");\r
+ if (fnGetVersion != NULL)\r
+ {\r
+ PRINT(("WASAPI: getting Windows version with GetVersion()\n"));\r
\r
- dwVersion = fnGetVersion();\r
+ dwVersion = fnGetVersion();\r
\r
- // Get the Windows version\r
- dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));\r
- dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));\r
+ // Get the Windows version\r
+ dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));\r
+ dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));\r
\r
- // Get the build number\r
- if (dwVersion < 0x80000000)\r
- dwBuild = (DWORD)(HIWORD(dwVersion));\r
+ // Get the build number\r
+ if (dwVersion < 0x80000000)\r
+ dwBuild = (DWORD)(HIWORD(dwVersion));\r
\r
- switch (dwMajorVersion)\r
- {\r
- case 0:\r
- case 1:\r
- case 2:\r
- case 3:\r
- case 4:\r
- case 5:\r
- break; // skip lower\r
- case 6:\r
- switch (dwMinorVersion)\r
+ switch (dwMajorVersion)\r
{\r
case 0:\r
- version |= WINDOWS_VISTA_SERVER2008;\r
- break;\r
case 1:\r
- version |= WINDOWS_7_SERVER2008R2;\r
+ case 2:\r
+ case 3:\r
+ case 4:\r
+ case 5:\r
+ break; // skip lower\r
+ case 6:\r
+ switch (dwMinorVersion)\r
+ {\r
+ case 0: version = WINDOWS_VISTA_SERVER2008; break;\r
+ case 1: version = WINDOWS_7_SERVER2008R2; break;\r
+ case 2: version = WINDOWS_8_SERVER2012; break;\r
+ case 3: version = WINDOWS_8_1_SERVER2012R2; break;\r
+ default: version = WINDOWS_FUTURE; break;\r
+ }\r
+ break;\r
+ case 10:\r
+ switch (dwMinorVersion)\r
+ {\r
+ case 0: version = WINDOWS_10_SERVER2016; break;\r
+ default: version = WINDOWS_FUTURE; break;\r
+ }\r
break;\r
default:\r
- version |= WINDOWS_FUTURE;\r
+ version = WINDOWS_FUTURE;\r
+ break;\r
}\r
- break;\r
- default:\r
- version |= WINDOWS_FUTURE;\r
}\r
+ else\r
+ {\r
+ PRINT(("WASAPI: getting Windows version with VerifyVersionInfo()\n"));\r
+\r
+ if (IsWindowsVersionOrGreater(10, 0, 0))\r
+ version = WINDOWS_10_SERVER2016;\r
+ else\r
+ if (IsWindowsVersionOrGreater(6, 3, 0))\r
+ version = WINDOWS_8_1_SERVER2012R2;\r
+ else\r
+ if (IsWindowsVersionOrGreater(6, 2, 0))\r
+ version = WINDOWS_8_SERVER2012;\r
+ else\r
+ if (IsWindowsVersionOrGreater(6, 1, 0))\r
+ version = WINDOWS_7_SERVER2008R2;\r
+ else\r
+ if (IsWindowsVersionOrGreater(6, 0, 0))\r
+ version = WINDOWS_VISTA_SERVER2008;\r
+ else\r
+ version = WINDOWS_FUTURE;\r
+ }\r
+\r
+ PRINT(("WASAPI: Windows version = %d\n", version));\r
}\r
\r
return version;\r
// note: WOW64 bug is common to Windows Vista x64, thus we fall back to safe Poll-driven\r
// method. Windows 7 x64 seems has WOW64 bug fixed.\r
\r
- return (IsWow64() && (GetWindowsVersion() & WINDOWS_VISTA_SERVER2008));\r
+ return (IsWow64() && (GetWindowsVersion() == WINDOWS_VISTA_SERVER2008));\r
+}\r
+\r
+// ------------------------------------------------------------------------------------------\r
+static UINT32 GetAudioClientVersion()\r
+{\r
+ if (GetWindowsVersion() >= WINDOWS_10_SERVER2016)\r
+ return 3;\r
+ else\r
+ if (GetWindowsVersion() >= WINDOWS_8_SERVER2012)\r
+ return 2;\r
+\r
+ return 1;\r
+}\r
+\r
+// ------------------------------------------------------------------------------------------\r
+static const IID *GetAudioClientIID()\r
+{\r
+ static const IID *cli_iid = NULL;\r
+ if (cli_iid == NULL)\r
+ {\r
+ UINT32 cli_version = GetAudioClientVersion();\r
+ if (cli_version <= 1)\r
+ {\r
+ cli_iid = &pa_IID_IAudioClient;\r
+ }\r
+ else\r
+ {\r
+ switch (cli_version)\r
+ {\r
+ case 3: cli_iid = &pa_IID_IAudioClient2; cli_version = 2; break; // use IAudioClient2 for Windows 10+ until IAudioClient3 functions are required\r
+ default: cli_iid = &pa_IID_IAudioClient2; cli_version = 2; break;\r
+ }\r
+ }\r
+\r
+ PRINT(("WASAPI: IAudioClient version = %d\n", cli_version));\r
+ }\r
+\r
+ return cli_iid;\r
}\r
\r
// ------------------------------------------------------------------------------------------\r
{\r
IAudioClient *tmpClient = NULL;\r
\r
- hr = IMMDevice_Activate(paWasapi->devInfo[i].device, &pa_IID_IAudioClient,\r
+ hr = IMMDevice_Activate(paWasapi->devInfo[i].device, GetAudioClientIID(),\r
CLSCTX_INPROC_SERVER, NULL, (void **)&tmpClient);\r
// We need to set the result to a value otherwise we will return paNoError\r
// [IF_FAILED_JUMP(hResult, error);]\r
shareMode = AUDCLNT_SHAREMODE_EXCLUSIVE;\r
\r
hr = IMMDevice_Activate(paWasapi->devInfo[inputParameters->device].device,\r
- &pa_IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, (void **)&tmpClient);\r
+ GetAudioClientIID(), CLSCTX_INPROC_SERVER, NULL, (void **)&tmpClient);\r
if (hr != S_OK)\r
{\r
LogHostError(hr);\r
shareMode = AUDCLNT_SHAREMODE_EXCLUSIVE;\r
\r
hr = IMMDevice_Activate(paWasapi->devInfo[outputParameters->device].device,\r
- &pa_IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, (void **)&tmpClient);\r
+ GetAudioClientIID(), CLSCTX_INPROC_SERVER, NULL, (void **)&tmpClient);\r
if (hr != S_OK)\r
{\r
LogHostError(hr);\r
}\r
\r
// Get the audio client\r
- hr = IMMDevice_Activate(pInfo->device, &pa_IID_IAudioClient, CLSCTX_ALL, NULL, (void **)&audioClient);\r
+ hr = IMMDevice_Activate(pInfo->device, GetAudioClientIID(), CLSCTX_ALL, NULL, (void **)&audioClient);\r
if (hr != S_OK)\r
{\r
(*pa_error) = paInsufficientMemory;\r
}\r
}\r
\r
+ // Set Raw mode (applicable only to IAudioClient2)\r
+#ifdef __IAudioClient2_INTERFACE_DEFINED__\r
+ if (GetAudioClientVersion() >= 2)\r
+ {\r
+ pa_AudioClientProperties audioProps = { 0 };\r
+ audioProps.cbSize = sizeof(pa_AudioClientProperties);\r
+ audioProps.bIsOffload = FALSE;\r
+ audioProps.eCategory = (AUDIO_STREAM_CATEGORY)pSub->params.wasapi_params.streamCategory;\r
+ switch (pSub->params.wasapi_params.streamOption)\r
+ {\r
+ case eStreamOptionRaw:\r
+ if (GetWindowsVersion() >= WINDOWS_8_1_SERVER2012R2)\r
+ audioProps.Options = pa_AUDCLNT_STREAMOPTIONS_RAW;\r
+ break;\r
+ case eStreamOptionMatchFormat:\r
+ if (GetWindowsVersion() >= WINDOWS_10_SERVER2016)\r
+ audioProps.Options = pa_AUDCLNT_STREAMOPTIONS_MATCH_FORMAT;\r
+ break;\r
+ }\r
+\r
+ hr = IAudioClient2_SetClientProperties((IAudioClient2 *)audioClient, (AudioClientProperties *)&audioProps);\r
+ if (hr != S_OK)\r
+ {\r
+ PRINT(("WASAPI: IAudioClient2_SetClientProperties(Category = %d, Options = %d) failed with error = %08X\n", audioProps.eCategory, audioProps.Options, (UINT32)hr));\r
+ }\r
+ else\r
+ {\r
+ PRINT(("WASAPI: IAudioClient2 set properties: IsOffload = %d, Category = %d, Options = %d\n", audioProps.bIsOffload, audioProps.eCategory, audioProps.Options));\r
+ }\r
+ }\r
+#endif\r
+\r
// Open the stream and associate it with an audio session\r
hr = IAudioClient_Initialize(audioClient,\r
pSub->shareMode,\r
SAFE_RELEASE(audioClient);\r
\r
// Create a new audio client\r
- hr = IMMDevice_Activate(pInfo->device, &pa_IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&audioClient);\r
+ hr = IMMDevice_Activate(pInfo->device, GetAudioClientIID(), CLSCTX_ALL, NULL, (void**)&audioClient);\r
if (hr != S_OK)\r
{\r
(*pa_error) = paInsufficientMemory;\r
SAFE_RELEASE(audioClient);\r
\r
// Create a new audio client\r
- hr = IMMDevice_Activate(pInfo->device, &pa_IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&audioClient);\r
+ hr = IMMDevice_Activate(pInfo->device, GetAudioClientIID(), CLSCTX_ALL, NULL, (void**)&audioClient);\r
if (hr != S_OK)\r
{\r
(*pa_error) = paInsufficientMemory;\r
SAFE_RELEASE(audioClient);\r
\r
// Create a new audio client\r
- hr = IMMDevice_Activate(pInfo->device, &pa_IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&audioClient);\r
+ hr = IMMDevice_Activate(pInfo->device, GetAudioClientIID(), CLSCTX_ALL, NULL, (void**)&audioClient);\r
if (hr != S_OK)\r
{\r
(*pa_error) = paInsufficientMemory;\r
{\r
inputChannelCount = inputParameters->channelCount;\r
inputSampleFormat = inputParameters->sampleFormat;\r
- inputStreamInfo = (PaWasapiStreamInfo *)inputParameters->hostApiSpecificStreamInfo;\r
info = &paWasapi->devInfo[inputParameters->device];\r
- stream->in.flags = (inputStreamInfo ? inputStreamInfo->flags : 0);\r
\r
- // Select Exclusive/Shared mode\r
+ // default Shared Mode\r
stream->in.shareMode = AUDCLNT_SHAREMODE_SHARED;\r
- if ((inputStreamInfo != NULL) && (inputStreamInfo->flags & paWinWasapiExclusive))\r
- {\r
- // Boost thread priority\r
- stream->nThreadPriority = eThreadPriorityProAudio;\r
- // Make Exclusive\r
- stream->in.shareMode = AUDCLNT_SHAREMODE_EXCLUSIVE;\r
- }\r
\r
- // If user provided explicit thread priority level, use it\r
- if ((inputStreamInfo != NULL) && (inputStreamInfo->flags & paWinWasapiThreadPriority))\r
+ // PaWasapiStreamInfo\r
+ if (inputParameters->hostApiSpecificStreamInfo != NULL)\r
{\r
- if ((inputStreamInfo->threadPriority > eThreadPriorityNone) &&\r
- (inputStreamInfo->threadPriority <= eThreadPriorityWindowManager))\r
- stream->nThreadPriority = inputStreamInfo->threadPriority;\r
+ memcpy(&stream->in.params.wasapi_params, inputParameters->hostApiSpecificStreamInfo, min(sizeof(stream->in.params.wasapi_params), ((PaWasapiStreamInfo *)inputParameters->hostApiSpecificStreamInfo)->size));\r
+ stream->in.params.wasapi_params.size = sizeof(stream->in.params.wasapi_params);\r
+\r
+ stream->in.params.stream_params.hostApiSpecificStreamInfo = &stream->in.params.wasapi_params;\r
+ inputStreamInfo = &stream->in.params.wasapi_params;\r
+\r
+ stream->in.flags = inputStreamInfo->flags;\r
+\r
+ // Exclusive Mode\r
+ if (inputStreamInfo->flags & paWinWasapiExclusive)\r
+ {\r
+ // Boost thread priority\r
+ stream->nThreadPriority = eThreadPriorityProAudio;\r
+ // Make Exclusive\r
+ stream->in.shareMode = AUDCLNT_SHAREMODE_EXCLUSIVE;\r
+ }\r
+\r
+ // explicit thread priority level\r
+ if (inputStreamInfo->flags & paWinWasapiThreadPriority)\r
+ {\r
+ if ((inputStreamInfo->threadPriority > eThreadPriorityNone) &&\r
+ (inputStreamInfo->threadPriority <= eThreadPriorityWindowManager))\r
+ stream->nThreadPriority = inputStreamInfo->threadPriority;\r
+ }\r
}\r
\r
// Choose processing mode\r
// Fill parameters for Audio Client creation\r
stream->in.params.device_info = info;\r
stream->in.params.stream_params = (*inputParameters);\r
- if (inputStreamInfo != NULL)\r
- {\r
- stream->in.params.wasapi_params = (*inputStreamInfo);\r
- stream->in.params.stream_params.hostApiSpecificStreamInfo = &stream->in.params.wasapi_params;\r
- }\r
stream->in.params.frames_per_buffer = framesPerBuffer;\r
stream->in.params.sample_rate = sampleRate;\r
stream->in.params.blocking = (streamCallback == NULL);\r
{\r
outputChannelCount = outputParameters->channelCount;\r
outputSampleFormat = outputParameters->sampleFormat;\r
- outputStreamInfo = (PaWasapiStreamInfo *)outputParameters->hostApiSpecificStreamInfo;\r
info = &paWasapi->devInfo[outputParameters->device];\r
- stream->out.flags = (outputStreamInfo ? outputStreamInfo->flags : 0);\r
\r
- // Select Exclusive/Shared mode\r
+ // default Shared Mode\r
stream->out.shareMode = AUDCLNT_SHAREMODE_SHARED;\r
- if ((outputStreamInfo != NULL) && (outputStreamInfo->flags & paWinWasapiExclusive))\r
- {\r
- // Boost thread priority\r
- stream->nThreadPriority = eThreadPriorityProAudio;\r
- // Make Exclusive\r
- stream->out.shareMode = AUDCLNT_SHAREMODE_EXCLUSIVE;\r
- }\r
\r
- // If user provided explicit thread priority level, use it\r
- if ((outputStreamInfo != NULL) && (outputStreamInfo->flags & paWinWasapiThreadPriority))\r
+ // set PaWasapiStreamInfo\r
+ if (outputParameters->hostApiSpecificStreamInfo != NULL)\r
{\r
- if ((outputStreamInfo->threadPriority > eThreadPriorityNone) &&\r
- (outputStreamInfo->threadPriority <= eThreadPriorityWindowManager))\r
- stream->nThreadPriority = outputStreamInfo->threadPriority;\r
+ memcpy(&stream->out.params.wasapi_params, outputParameters->hostApiSpecificStreamInfo, min(sizeof(stream->out.params.wasapi_params), ((PaWasapiStreamInfo *)outputParameters->hostApiSpecificStreamInfo)->size));\r
+ stream->out.params.wasapi_params.size = sizeof(stream->out.params.wasapi_params);\r
+\r
+ stream->out.params.stream_params.hostApiSpecificStreamInfo = &stream->out.params.wasapi_params;\r
+ outputStreamInfo = &stream->out.params.wasapi_params;\r
+\r
+ stream->out.flags = outputStreamInfo->flags;\r
+\r
+ // Exclusive Mode\r
+ if (outputStreamInfo->flags & paWinWasapiExclusive)\r
+ {\r
+ // Boost thread priority\r
+ stream->nThreadPriority = eThreadPriorityProAudio;\r
+ // Make Exclusive\r
+ stream->out.shareMode = AUDCLNT_SHAREMODE_EXCLUSIVE;\r
+ }\r
+\r
+ // explicit thread priority level\r
+ if (outputStreamInfo->flags & paWinWasapiThreadPriority)\r
+ {\r
+ if ((outputStreamInfo->threadPriority > eThreadPriorityNone) &&\r
+ (outputStreamInfo->threadPriority <= eThreadPriorityWindowManager))\r
+ stream->nThreadPriority = outputStreamInfo->threadPriority;\r
+ }\r
}\r
\r
// Choose processing mode\r
// Fill parameters for Audio Client creation\r
stream->out.params.device_info = info;\r
stream->out.params.stream_params = (*outputParameters);\r
- if (inputStreamInfo != NULL)\r
- {\r
- stream->out.params.wasapi_params = (*outputStreamInfo);\r
- stream->out.params.stream_params.hostApiSpecificStreamInfo = &stream->out.params.wasapi_params;\r
- }\r
stream->out.params.frames_per_buffer = framesPerBuffer;\r
stream->out.params.sample_rate = sampleRate;\r
stream->out.params.blocking = (streamCallback == NULL);\r
substream->clientProc = NULL;\r
\r
// IAudioClient\r
- hResult = CoGetInterfaceAndReleaseStream(substream->clientStream, &pa_IID_IAudioClient, (LPVOID*)&substream->clientProc);\r
+ hResult = CoGetInterfaceAndReleaseStream(substream->clientStream, GetAudioClientIID(), (LPVOID*)&substream->clientProc);\r
substream->clientStream = NULL;\r
if (hResult != S_OK) \r
{\r
substream->clientStream = NULL;\r
\r
// IAudioClient\r
- hResult = CoMarshalInterThreadInterfaceInStream(&pa_IID_IAudioClient, (LPUNKNOWN)substream->clientParent, &substream->clientStream);\r
+ hResult = CoMarshalInterThreadInterfaceInStream(GetAudioClientIID(), (LPUNKNOWN)substream->clientParent, &substream->clientStream);\r
if (hResult != S_OK)\r
goto marshal_sub_error;\r
\r