diff -wruN portaudio/src/hostapi/wasapi/pa_win_wasapi.c portaudio-v19/src/hostapi/wasapi/pa_win_wasapi.c --- portaudio/src/hostapi/wasapi/pa_win_wasapi.c 2012-06-29 06:44:12.000000000 -0500 +++ portaudio-v19/src/hostapi/wasapi/pa_win_wasapi.c 2012-12-31 14:46:16.533923600 -0600 @@ -1052,6 +1055,8 @@ HRESULT hr = S_OK; IMMDeviceCollection* pEndPoints = NULL; UINT i; + UINT renderCount; + UINT devIndex; if (!SetupAVRT()) { @@ -1148,6 +1153,19 @@ } } + hr = IMMDeviceEnumerator_EnumAudioEndpoints(paWasapi->enumerator, 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(paWasapi->enumerator, eAll, DEVICE_STATE_ACTIVE, &pEndPoints); // We need to set the result to a value otherwise we will return paNoError // [IF_FAILED_JUMP(hResult, error);] @@ -1158,6 +1176,8 @@ // [IF_FAILED_JUMP(hResult, error);] IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error); + paWasapi->deviceCount += renderCount; + paWasapi->devInfo = (PaWasapiDeviceInfo *)PaUtil_AllocateMemory(sizeof(PaWasapiDeviceInfo) * paWasapi->deviceCount); for (i = 0; i < paWasapi->deviceCount; ++i) memset(&paWasapi->devInfo[i], 0, sizeof(PaWasapiDeviceInfo)); @@ -1181,7 +1201,7 @@ goto error; } - for (i = 0; i < paWasapi->deviceCount; ++i) + for (devIndex = 0, i = 0; i < paWasapi->deviceCount; ++i, ++devIndex) { DWORD state = 0; PaDeviceInfo *deviceInfo = &deviceInfoArray[i]; @@ -1191,7 +1211,7 @@ PA_DEBUG(("WASAPI: device idx: %02d\n", i)); PA_DEBUG(("WASAPI: ---------------\n")); - 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 // [IF_FAILED_JUMP(hResult, error);] IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error); @@ -1373,6 +1393,41 @@ (*hostApi)->deviceInfos[i] = deviceInfo; ++(*hostApi)->info.deviceCount; + + if (paWasapi->devInfo[i].flow == eRender) + { + char *deviceName; + UINT deviceNameLen; + + memcpy(&deviceInfoArray[i + 1], deviceInfo, sizeof(*deviceInfo)); + memcpy(&paWasapi->devInfo[i + 1], &paWasapi->devInfo[i], sizeof(*paWasapi->devInfo)); + + i++; + 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; + } } } @@ -2170,7 +2225,7 @@ }*/ // 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; @@ -2423,7 +2478,7 @@ }*/ // 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; @@ -2728,6 +2786,9 @@ if (fullDuplex) stream->in.streamFlags = 0; // polling interface is implemented for full-duplex mode also + if (info->flow == eRender) + stream->in.streamFlags |= AUDCLNT_STREAMFLAGS_LOOPBACK; + // Fill parameters for Audio Client creation stream->in.params.device_info = info; stream->in.params.stream_params = (*inputParameters); @@ -3411,7 +3474,7 @@ // ------------------------------------------------------------------------------------------ static PaError IsStreamStopped( PaStream *s ) { - return !((PaWasapiStream *)s)->running; + return ((PaWasapiStream *)s)->stopped; } // ------------------------------------------------------------------------------------------