mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-16 08:09:32 +02:00
Recreate and apply the WASAPI loopback patch
This commit is contained in:
parent
e3e1758110
commit
be7467c0e3
@ -564,6 +564,15 @@ const wchar_t *PaWasapi_GetInputDeviceID( PaStream *s );
|
|||||||
*/
|
*/
|
||||||
const wchar_t *PaWasapi_GetOutputDeviceID( PaStream *s );
|
const wchar_t *PaWasapi_GetOutputDeviceID( PaStream *s );
|
||||||
|
|
||||||
|
/** Returns device loopback indicator.
|
||||||
|
|
||||||
|
@param nDevice device index.
|
||||||
|
|
||||||
|
@return 0 = Not loopback, 1 = loopback, < 0 = PaErrorCode
|
||||||
|
if PortAudio is not initialized or an error is encountered.
|
||||||
|
*/
|
||||||
|
int PaWasapi_IsLoopback( PaDeviceIndex nDevice );
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
IMPORTANT:
|
IMPORTANT:
|
||||||
|
@ -449,6 +449,9 @@ typedef struct PaWasapiDeviceInfo
|
|||||||
|
|
||||||
// Formfactor
|
// Formfactor
|
||||||
EndpointFormFactor formFactor;
|
EndpointFormFactor formFactor;
|
||||||
|
|
||||||
|
// Loopback indicator
|
||||||
|
int loopBack;
|
||||||
}
|
}
|
||||||
PaWasapiDeviceInfo;
|
PaWasapiDeviceInfo;
|
||||||
|
|
||||||
@ -1674,6 +1677,8 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
|
|||||||
IMMDeviceEnumerator *pEnumerator = NULL;
|
IMMDeviceEnumerator *pEnumerator = NULL;
|
||||||
#endif
|
#endif
|
||||||
IAudioClient *tmpClient;
|
IAudioClient *tmpClient;
|
||||||
|
UINT renderCount;
|
||||||
|
INT devIndex;
|
||||||
|
|
||||||
// Make sure device list empty
|
// Make sure device list empty
|
||||||
if ((paWasapi->deviceCount != 0) || (hostApi->info.deviceCount != 0))
|
if ((paWasapi->deviceCount != 0) || (hostApi->info.deviceCount != 0))
|
||||||
@ -1738,6 +1743,19 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hr = IMMDeviceEnumerator_EnumAudioEndpoints(pEnumerator, eRender, DEVICE_STATE_ACTIVE, &pEndPoints);
|
||||||
|
// We need to set the result to a value otherwise we will return paNoError
|
||||||
|
// [IF_FAILED_JUMP(hResult, error);]
|
||||||
|
IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
|
||||||
|
|
||||||
|
hr = IMMDeviceCollection_GetCount(pEndPoints, &renderCount);
|
||||||
|
// We need to set the result to a value otherwise we will return paNoError
|
||||||
|
// [IF_FAILED_JUMP(hResult, error);]
|
||||||
|
IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
|
||||||
|
|
||||||
|
SAFE_RELEASE(pEndPoints);
|
||||||
|
pEndPoints = NULL;
|
||||||
|
|
||||||
hr = IMMDeviceEnumerator_EnumAudioEndpoints(pEnumerator, eAll, DEVICE_STATE_ACTIVE, &pEndPoints);
|
hr = IMMDeviceEnumerator_EnumAudioEndpoints(pEnumerator, eAll, DEVICE_STATE_ACTIVE, &pEndPoints);
|
||||||
// We need to set the result to a value otherwise we will return paNoError
|
// We need to set the result to a value otherwise we will return paNoError
|
||||||
// [IF_FAILED_JUMP(hResult, error);]
|
// [IF_FAILED_JUMP(hResult, error);]
|
||||||
@ -1748,6 +1766,7 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
|
|||||||
// [IF_FAILED_JUMP(hResult, error);]
|
// [IF_FAILED_JUMP(hResult, error);]
|
||||||
IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
|
IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
|
||||||
|
|
||||||
|
paWasapi->deviceCount += renderCount;
|
||||||
#else
|
#else
|
||||||
// Determine number of available devices by activating AudioClient for render and capture data flows
|
// Determine number of available devices by activating AudioClient for render and capture data flows
|
||||||
if (SUCCEEDED(ActivateAudioInterface_WINRT(eRender, GetAudioClientIID(), &tmpClient)))
|
if (SUCCEEDED(ActivateAudioInterface_WINRT(eRender, GetAudioClientIID(), &tmpClient)))
|
||||||
@ -1797,7 +1816,7 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
|
|||||||
}
|
}
|
||||||
memset(deviceInfoArray, 0, sizeof(PaDeviceInfo) * deviceCount);
|
memset(deviceInfoArray, 0, sizeof(PaDeviceInfo) * deviceCount);
|
||||||
|
|
||||||
for (i = 0; i < paWasapi->deviceCount; ++i)
|
for (devIndex = 0, i = 0; i < paWasapi->deviceCount; ++i, ++devIndex)
|
||||||
{
|
{
|
||||||
PaDeviceInfo *deviceInfo = &deviceInfoArray[i];
|
PaDeviceInfo *deviceInfo = &deviceInfoArray[i];
|
||||||
deviceInfo->structVersion = 2;
|
deviceInfo->structVersion = 2;
|
||||||
@ -1807,7 +1826,7 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
|
|||||||
PA_DEBUG(("WASAPI: ---------------\n"));
|
PA_DEBUG(("WASAPI: ---------------\n"));
|
||||||
|
|
||||||
#ifndef PA_WINRT
|
#ifndef PA_WINRT
|
||||||
hr = IMMDeviceCollection_Item(pEndPoints, i, &paWasapi->devInfo[i].device);
|
hr = IMMDeviceCollection_Item(pEndPoints, devIndex, &paWasapi->devInfo[i].device);
|
||||||
// We need to set the result to a value otherwise we will return paNoError
|
// We need to set the result to a value otherwise we will return paNoError
|
||||||
// [IF_FAILED_JUMP(hResult, error);]
|
// [IF_FAILED_JUMP(hResult, error);]
|
||||||
IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
|
IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
|
||||||
@ -2039,6 +2058,42 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
|
|||||||
|
|
||||||
hostApi->deviceInfos[i] = deviceInfo;
|
hostApi->deviceInfos[i] = deviceInfo;
|
||||||
++hostApi->info.deviceCount;
|
++hostApi->info.deviceCount;
|
||||||
|
|
||||||
|
if (paWasapi->devInfo[i].flow == eRender)
|
||||||
|
{
|
||||||
|
char *deviceName;
|
||||||
|
|
||||||
|
memcpy(&deviceInfoArray[i + 1], deviceInfo, sizeof(*deviceInfo));
|
||||||
|
memcpy(&paWasapi->devInfo[i + 1], &paWasapi->devInfo[i], sizeof(*paWasapi->devInfo));
|
||||||
|
|
||||||
|
i++;
|
||||||
|
paWasapi->devInfo[i].loopBack = 1;
|
||||||
|
|
||||||
|
deviceInfo = &deviceInfoArray[i];
|
||||||
|
|
||||||
|
deviceInfo->maxInputChannels = deviceInfo->maxOutputChannels;
|
||||||
|
deviceInfo->defaultHighInputLatency = deviceInfo->defaultHighOutputLatency;
|
||||||
|
deviceInfo->defaultLowInputLatency = deviceInfo->defaultLowOutputLatency;
|
||||||
|
deviceInfo->maxOutputChannels = 0;
|
||||||
|
deviceInfo->defaultHighOutputLatency = 0;
|
||||||
|
deviceInfo->defaultLowOutputLatency = 0;
|
||||||
|
PA_DEBUG(("WASAPI:%d| def.SR[%d] max.CH[%d] latency{hi[%f] lo[%f]}\n", i, (UINT32)deviceInfo->defaultSampleRate,
|
||||||
|
deviceInfo->maxInputChannels, (float)deviceInfo->defaultHighInputLatency, (float)deviceInfo->defaultLowInputLatency));
|
||||||
|
|
||||||
|
IMMDevice_AddRef(paWasapi->devInfo[i].device);
|
||||||
|
|
||||||
|
deviceName = (char *)PaUtil_GroupAllocateMemory(paWasapi->allocations, MAX_STR_LEN + 1);
|
||||||
|
if (deviceName == NULL)
|
||||||
|
{
|
||||||
|
result = paInsufficientMemory;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
_snprintf(deviceName, MAX_STR_LEN-1, "%s (loopback)", deviceInfo->name);
|
||||||
|
deviceInfo->name = deviceName;
|
||||||
|
|
||||||
|
hostApi->deviceInfos[i] = deviceInfo;
|
||||||
|
++hostApi->info.deviceCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PA_WASAPI_MAX_CONST_DEVICE_COUNT) && (PA_WASAPI_MAX_CONST_DEVICE_COUNT > 0)
|
#if defined(PA_WASAPI_MAX_CONST_DEVICE_COUNT) && (PA_WASAPI_MAX_CONST_DEVICE_COUNT > 0)
|
||||||
@ -2392,6 +2447,29 @@ int PaWasapi_GetDeviceRole( PaDeviceIndex device )
|
|||||||
return paWasapi->devInfo[ index ].formFactor;
|
return paWasapi->devInfo[ index ].formFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------
|
||||||
|
int PaWasapi_IsLoopback( PaDeviceIndex nDevice )
|
||||||
|
{
|
||||||
|
PaError ret;
|
||||||
|
PaDeviceIndex index;
|
||||||
|
|
||||||
|
// Get API
|
||||||
|
PaWasapiHostApiRepresentation *paWasapi = _GetHostApi(&ret);
|
||||||
|
if (paWasapi == NULL)
|
||||||
|
return paNotInitialized;
|
||||||
|
|
||||||
|
// Get device index
|
||||||
|
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, nDevice, &paWasapi->inheritedHostApiRep);
|
||||||
|
if (ret != paNoError)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
// Validate index
|
||||||
|
if ((UINT32)index >= paWasapi->deviceCount)
|
||||||
|
return paInvalidDevice;
|
||||||
|
|
||||||
|
return paWasapi->devInfo[ index ].loopBack;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------
|
||||||
PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *pInput, unsigned int *pOutput )
|
PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *pInput, unsigned int *pOutput )
|
||||||
{
|
{
|
||||||
@ -3055,7 +3133,7 @@ static HRESULT CreateAudioClient(PaWasapiStream *pStream, PaWasapiSubStream *pSu
|
|||||||
if ((params->channelCount == 1) && (pSub->wavex.Format.nChannels == 2))
|
if ((params->channelCount == 1) && (pSub->wavex.Format.nChannels == 2))
|
||||||
{
|
{
|
||||||
// select mixer
|
// select mixer
|
||||||
pSub->monoMixer = GetMonoToStereoMixer(&pSub->wavex, (pInfo->flow == eRender ? MIX_DIR__1TO2 : MIX_DIR__2TO1_L));
|
pSub->monoMixer = GetMonoToStereoMixer(&pSub->wavex, (output ? MIX_DIR__1TO2 : MIX_DIR__2TO1_L));
|
||||||
if (pSub->monoMixer == NULL)
|
if (pSub->monoMixer == NULL)
|
||||||
{
|
{
|
||||||
(*pa_error) = paInvalidChannelCount;
|
(*pa_error) = paInvalidChannelCount;
|
||||||
@ -3618,6 +3696,9 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
|||||||
((inputStreamInfo != NULL) && (inputStreamInfo->flags & paWinWasapiAutoConvert)))
|
((inputStreamInfo != NULL) && (inputStreamInfo->flags & paWinWasapiAutoConvert)))
|
||||||
stream->in.streamFlags |= (AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY);
|
stream->in.streamFlags |= (AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY);
|
||||||
|
|
||||||
|
if (info->flow == eRender)
|
||||||
|
stream->in.streamFlags |= AUDCLNT_STREAMFLAGS_LOOPBACK;
|
||||||
|
|
||||||
// Fill parameters for Audio Client creation
|
// Fill parameters for Audio Client creation
|
||||||
stream->in.params.device_info = info;
|
stream->in.params.device_info = info;
|
||||||
stream->in.params.stream_params = (*inputParameters);
|
stream->in.params.stream_params = (*inputParameters);
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
diff --git a/lib-src/portaudio-v19/include/pa_win_wasapi.h b/lib-src/portaudio-v19/include/pa_win_wasapi.h
|
diff --git a/lib-src/portaudio-v19/include/pa_win_wasapi.h b/lib-src/portaudio-v19/include/pa_win_wasapi.h
|
||||||
index 1087157..e52d0a7 100644
|
index a4416b121..1999e8dad 100644
|
||||||
--- a/lib-src/portaudio-v19/include/pa_win_wasapi.h
|
--- a/lib-src/portaudio-v19/include/pa_win_wasapi.h
|
||||||
+++ b/lib-src/portaudio-v19/include/pa_win_wasapi.h
|
+++ b/lib-src/portaudio-v19/include/pa_win_wasapi.h
|
||||||
@@ -319,6 +319,16 @@ int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, Pa
|
@@ -564,6 +564,15 @@ const wchar_t *PaWasapi_GetInputDeviceID( PaStream *s );
|
||||||
int/*PaWasapiDeviceRole*/ PaWasapi_GetDeviceRole( PaDeviceIndex nDevice );
|
*/
|
||||||
|
const wchar_t *PaWasapi_GetOutputDeviceID( PaStream *s );
|
||||||
|
|
||||||
+/** Returns device loopback indicator.
|
+/** Returns device loopback indicator.
|
||||||
+
|
+
|
||||||
@ -15,15 +15,14 @@ index 1087157..e52d0a7 100644
|
|||||||
+*/
|
+*/
|
||||||
+int PaWasapi_IsLoopback( PaDeviceIndex nDevice );
|
+int PaWasapi_IsLoopback( PaDeviceIndex nDevice );
|
||||||
+
|
+
|
||||||
+
|
|
||||||
/** Boost thread priority of calling thread (MMCSS). Use it for Blocking Interface only for thread
|
|
||||||
which makes calls to Pa_WriteStream/Pa_ReadStream.
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
IMPORTANT:
|
||||||
diff --git a/lib-src/portaudio-v19/src/hostapi/wasapi/pa_win_wasapi.c b/lib-src/portaudio-v19/src/hostapi/wasapi/pa_win_wasapi.c
|
diff --git a/lib-src/portaudio-v19/src/hostapi/wasapi/pa_win_wasapi.c b/lib-src/portaudio-v19/src/hostapi/wasapi/pa_win_wasapi.c
|
||||||
index 0026033..2e9dca8 100644
|
index f64049ad5..4b28f7f0b 100644
|
||||||
--- a/lib-src/portaudio-v19/src/hostapi/wasapi/pa_win_wasapi.c
|
--- a/lib-src/portaudio-v19/src/hostapi/wasapi/pa_win_wasapi.c
|
||||||
+++ b/lib-src/portaudio-v19/src/hostapi/wasapi/pa_win_wasapi.c
|
+++ b/lib-src/portaudio-v19/src/hostapi/wasapi/pa_win_wasapi.c
|
||||||
@@ -375,6 +375,9 @@ typedef struct PaWasapiDeviceInfo
|
@@ -449,6 +449,9 @@ typedef struct PaWasapiDeviceInfo
|
||||||
|
|
||||||
// Formfactor
|
// Formfactor
|
||||||
EndpointFormFactor formFactor;
|
EndpointFormFactor formFactor;
|
||||||
@ -33,20 +32,20 @@ index 0026033..2e9dca8 100644
|
|||||||
}
|
}
|
||||||
PaWasapiDeviceInfo;
|
PaWasapiDeviceInfo;
|
||||||
|
|
||||||
@@ -1179,6 +1182,8 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
@@ -1674,6 +1677,8 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
|
||||||
HRESULT hr = S_OK;
|
IMMDeviceEnumerator *pEnumerator = NULL;
|
||||||
IMMDeviceCollection* pEndPoints = NULL;
|
#endif
|
||||||
UINT i;
|
IAudioClient *tmpClient;
|
||||||
+ UINT renderCount;
|
+ UINT renderCount;
|
||||||
+ UINT devIndex;
|
+ INT devIndex;
|
||||||
|
|
||||||
if (!SetupAVRT())
|
// Make sure device list empty
|
||||||
{
|
if ((paWasapi->deviceCount != 0) || (hostApi->info.deviceCount != 0))
|
||||||
@@ -1275,6 +1280,19 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
@@ -1738,6 +1743,19 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+ hr = IMMDeviceEnumerator_EnumAudioEndpoints(paWasapi->enumerator, eRender, DEVICE_STATE_ACTIVE, &pEndPoints);
|
+ hr = IMMDeviceEnumerator_EnumAudioEndpoints(pEnumerator, eRender, DEVICE_STATE_ACTIVE, &pEndPoints);
|
||||||
+ // We need to set the result to a value otherwise we will return paNoError
|
+ // We need to set the result to a value otherwise we will return paNoError
|
||||||
+ // [IF_FAILED_JUMP(hResult, error);]
|
+ // [IF_FAILED_JUMP(hResult, error);]
|
||||||
+ IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
|
+ IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
|
||||||
@ -59,45 +58,43 @@ index 0026033..2e9dca8 100644
|
|||||||
+ SAFE_RELEASE(pEndPoints);
|
+ SAFE_RELEASE(pEndPoints);
|
||||||
+ pEndPoints = NULL;
|
+ pEndPoints = NULL;
|
||||||
+
|
+
|
||||||
hr = IMMDeviceEnumerator_EnumAudioEndpoints(paWasapi->enumerator, eAll, DEVICE_STATE_ACTIVE, &pEndPoints);
|
hr = IMMDeviceEnumerator_EnumAudioEndpoints(pEnumerator, eAll, DEVICE_STATE_ACTIVE, &pEndPoints);
|
||||||
// We need to set the result to a value otherwise we will return paNoError
|
// We need to set the result to a value otherwise we will return paNoError
|
||||||
// [IF_FAILED_JUMP(hResult, error);]
|
// [IF_FAILED_JUMP(hResult, error);]
|
||||||
@@ -1285,6 +1303,8 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
@@ -1748,6 +1766,7 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
|
||||||
// [IF_FAILED_JUMP(hResult, error);]
|
// [IF_FAILED_JUMP(hResult, error);]
|
||||||
IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
|
IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
|
||||||
|
|
||||||
+ paWasapi->deviceCount += renderCount;
|
+ paWasapi->deviceCount += renderCount;
|
||||||
+
|
#else
|
||||||
paWasapi->devInfo = (PaWasapiDeviceInfo *)PaUtil_AllocateMemory(sizeof(PaWasapiDeviceInfo) * paWasapi->deviceCount);
|
// Determine number of available devices by activating AudioClient for render and capture data flows
|
||||||
if (paWasapi->devInfo == NULL)
|
if (SUCCEEDED(ActivateAudioInterface_WINRT(eRender, GetAudioClientIID(), &tmpClient)))
|
||||||
{
|
@@ -1797,7 +1816,7 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
|
||||||
@@ -1313,7 +1333,7 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
memset(deviceInfoArray, 0, sizeof(PaDeviceInfo) * deviceCount);
|
||||||
|
|
||||||
- for (i = 0; i < paWasapi->deviceCount; ++i)
|
- for (i = 0; i < paWasapi->deviceCount; ++i)
|
||||||
+ for (devIndex = 0, i = 0; i < paWasapi->deviceCount; ++i, ++devIndex)
|
+ for (devIndex = 0, i = 0; i < paWasapi->deviceCount; ++i, ++devIndex)
|
||||||
{
|
{
|
||||||
DWORD state = 0;
|
|
||||||
PaDeviceInfo *deviceInfo = &deviceInfoArray[i];
|
PaDeviceInfo *deviceInfo = &deviceInfoArray[i];
|
||||||
@@ -1323,7 +1343,7 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
deviceInfo->structVersion = 2;
|
||||||
PA_DEBUG(("WASAPI: device idx: %02d\n", i));
|
@@ -1807,7 +1826,7 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
|
||||||
PA_DEBUG(("WASAPI: ---------------\n"));
|
PA_DEBUG(("WASAPI: ---------------\n"));
|
||||||
|
|
||||||
|
#ifndef PA_WINRT
|
||||||
- hr = IMMDeviceCollection_Item(pEndPoints, i, &paWasapi->devInfo[i].device);
|
- hr = IMMDeviceCollection_Item(pEndPoints, i, &paWasapi->devInfo[i].device);
|
||||||
+ hr = IMMDeviceCollection_Item(pEndPoints, devIndex, &paWasapi->devInfo[i].device);
|
+ hr = IMMDeviceCollection_Item(pEndPoints, devIndex, &paWasapi->devInfo[i].device);
|
||||||
// We need to set the result to a value otherwise we will return paNoError
|
// We need to set the result to a value otherwise we will return paNoError
|
||||||
// [IF_FAILED_JUMP(hResult, error);]
|
// [IF_FAILED_JUMP(hResult, error);]
|
||||||
IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
|
IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
|
||||||
@@ -1513,6 +1533,43 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
@@ -2039,6 +2058,42 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
|
||||||
|
|
||||||
(*hostApi)->deviceInfos[i] = deviceInfo;
|
hostApi->deviceInfos[i] = deviceInfo;
|
||||||
++(*hostApi)->info.deviceCount;
|
++hostApi->info.deviceCount;
|
||||||
+
|
+
|
||||||
+ if (paWasapi->devInfo[i].flow == eRender)
|
+ if (paWasapi->devInfo[i].flow == eRender)
|
||||||
+ {
|
+ {
|
||||||
+ char *deviceName;
|
+ char *deviceName;
|
||||||
+ UINT deviceNameLen;
|
|
||||||
+
|
+
|
||||||
+ memcpy(&deviceInfoArray[i + 1], deviceInfo, sizeof(*deviceInfo));
|
+ memcpy(&deviceInfoArray[i + 1], deviceInfo, sizeof(*deviceInfo));
|
||||||
+ memcpy(&paWasapi->devInfo[i + 1], &paWasapi->devInfo[i], sizeof(*paWasapi->devInfo));
|
+ memcpy(&paWasapi->devInfo[i + 1], &paWasapi->devInfo[i], sizeof(*paWasapi->devInfo));
|
||||||
@ -127,16 +124,17 @@ index 0026033..2e9dca8 100644
|
|||||||
+ _snprintf(deviceName, MAX_STR_LEN-1, "%s (loopback)", deviceInfo->name);
|
+ _snprintf(deviceName, MAX_STR_LEN-1, "%s (loopback)", deviceInfo->name);
|
||||||
+ deviceInfo->name = deviceName;
|
+ deviceInfo->name = deviceName;
|
||||||
+
|
+
|
||||||
+ (*hostApi)->deviceInfos[i] = deviceInfo;
|
+ hostApi->deviceInfos[i] = deviceInfo;
|
||||||
+ ++(*hostApi)->info.deviceCount;
|
+ ++hostApi->info.deviceCount;
|
||||||
+ }
|
+ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(PA_WASAPI_MAX_CONST_DEVICE_COUNT) && (PA_WASAPI_MAX_CONST_DEVICE_COUNT > 0)
|
||||||
|
@@ -2392,6 +2447,29 @@ int PaWasapi_GetDeviceRole( PaDeviceIndex device )
|
||||||
|
return paWasapi->devInfo[ index ].formFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1691,6 +1748,29 @@ const wchar_t *PaWasapi_GetOutputDeviceID( PaStream* s )
|
+// ------------------------------------------------------------------------------------------
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------
|
|
||||||
+int PaWasapi_IsLoopback( PaDeviceIndex nDevice )
|
+int PaWasapi_IsLoopback( PaDeviceIndex nDevice )
|
||||||
+{
|
+{
|
||||||
+ PaError ret;
|
+ PaError ret;
|
||||||
@ -159,31 +157,21 @@ index 0026033..2e9dca8 100644
|
|||||||
+ return paWasapi->devInfo[ index ].loopBack;
|
+ return paWasapi->devInfo[ index ].loopBack;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+// ------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------
|
||||||
PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *nInput, unsigned int *nOutput )
|
PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *pInput, unsigned int *pOutput )
|
||||||
|
{
|
||||||
|
@@ -3055,7 +3133,7 @@ static HRESULT CreateAudioClient(PaWasapiStream *pStream, PaWasapiSubStream *pSu
|
||||||
|
if ((params->channelCount == 1) && (pSub->wavex.Format.nChannels == 2))
|
||||||
{
|
{
|
||||||
PaWasapiStream *stream = (PaWasapiStream *)pStream;
|
|
||||||
@@ -2336,7 +2416,7 @@ static HRESULT CreateAudioClient(PaWasapiStream *pStream, PaWasapiSubStream *pSu
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// select mixer
|
// select mixer
|
||||||
- pSub->monoMixer = _GetMonoToStereoMixer(WaveToPaFormat(&pSub->wavex), (pInfo->flow == eRender ? MIX_DIR__1TO2 : MIX_DIR__2TO1_L));
|
- pSub->monoMixer = GetMonoToStereoMixer(&pSub->wavex, (pInfo->flow == eRender ? MIX_DIR__1TO2 : MIX_DIR__2TO1_L));
|
||||||
+ pSub->monoMixer = _GetMonoToStereoMixer(WaveToPaFormat(&pSub->wavex), (output ? MIX_DIR__1TO2 : MIX_DIR__2TO1_L));
|
+ pSub->monoMixer = GetMonoToStereoMixer(&pSub->wavex, (output ? MIX_DIR__1TO2 : MIX_DIR__2TO1_L));
|
||||||
if (pSub->monoMixer == NULL)
|
if (pSub->monoMixer == NULL)
|
||||||
{
|
{
|
||||||
(*pa_error) = paInvalidChannelCount;
|
(*pa_error) = paInvalidChannelCount;
|
||||||
@@ -2621,7 +2701,7 @@ static HRESULT CreateAudioClient(PaWasapiStream *pStream, PaWasapiSubStream *pSu
|
@@ -3618,6 +3696,9 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
||||||
}*/
|
((inputStreamInfo != NULL) && (inputStreamInfo->flags & paWinWasapiAutoConvert)))
|
||||||
|
stream->in.streamFlags |= (AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY);
|
||||||
// Select mixer
|
|
||||||
- pSub->monoMixer = _GetMonoToStereoMixer(WaveToPaFormat(&pSub->wavex), (pInfo->flow == eRender ? MIX_DIR__1TO2 : MIX_DIR__2TO1_L));
|
|
||||||
+ pSub->monoMixer = _GetMonoToStereoMixer(WaveToPaFormat(&pSub->wavex), (output ? MIX_DIR__1TO2 : MIX_DIR__2TO1_L));
|
|
||||||
if (pSub->monoMixer == NULL)
|
|
||||||
{
|
|
||||||
(*pa_error) = paInvalidChannelCount;
|
|
||||||
@@ -2941,6 +3021,9 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
|
||||||
if (fullDuplex)
|
|
||||||
stream->in.streamFlags = 0; // polling interface is implemented for full-duplex mode also
|
|
||||||
|
|
||||||
+ if (info->flow == eRender)
|
+ if (info->flow == eRender)
|
||||||
+ stream->in.streamFlags |= AUDCLNT_STREAMFLAGS_LOOPBACK;
|
+ stream->in.streamFlags |= AUDCLNT_STREAMFLAGS_LOOPBACK;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user