deviceInfo->structVersion = 2;\r
deviceInfo->hostApi = hostApiIndex;\r
\r
- PA_DEBUG(("WASAPI: device i: %d\n", i));\r
+ PA_DEBUG(("WASAPI: device idx: %02d\n", i));\r
+ PA_DEBUG(("WASAPI: ---------------\n"));\r
\r
hr = IMMDeviceCollection_Item(pEndPoints, i, &paWasapi->devInfo[i].device);\r
IF_FAILED_JUMP(hr, error);\r
_snprintf(deviceName, MAX_STR_LEN-1, "baddev%d", i);\r
deviceInfo->name = deviceName;\r
PropVariantClear(&value);\r
+ PA_DEBUG(("WASAPI:%d| name[%s]\n", i, deviceInfo->name));\r
}\r
\r
// Default format\r
#else\r
paWasapi->devInfo[i].formFactor = (EndpointFormFactor)value.uintVal;\r
#endif\r
- PA_DEBUG(("WASAPI: device[%s] form-factor: %d\n", deviceInfo->name, paWasapi->devInfo[i].formFactor));\r
+ PA_DEBUG(("WASAPI:%d| form-factor[%d]\n", i, paWasapi->devInfo[i].formFactor));\r
// cleanup\r
PropVariantClear(&value);\r
}\r
}\r
\r
// we can now fill in portaudio device data\r
- deviceInfo->maxInputChannels = 0; //for now\r
- deviceInfo->maxOutputChannels = 0; //for now\r
+ deviceInfo->maxInputChannels = 0;\r
+ deviceInfo->maxOutputChannels = 0;\r
+ deviceInfo->defaultSampleRate = paWasapi->devInfo[i].DefaultFormat.Format.nSamplesPerSec;\r
switch (paWasapi->devInfo[i].flow)\r
{\r
- case eRender:\r
- // WASAPI accepts exact channels count\r
+ case eRender: {\r
deviceInfo->maxOutputChannels = paWasapi->devInfo[i].DefaultFormat.Format.nChannels;\r
deviceInfo->defaultHighOutputLatency = nano100ToSeconds(paWasapi->devInfo[i].DefaultDevicePeriod);\r
deviceInfo->defaultLowOutputLatency = nano100ToSeconds(paWasapi->devInfo[i].MinimumDevicePeriod);\r
- break;\r
- case eCapture:\r
- // WASAPI accepts exact channels count\r
+ PA_DEBUG(("WASAPI:%d| def.SR[%d] max.CH[%d] latency{hi[%f] lo[%f]}\n", i, (UINT32)deviceInfo->defaultSampleRate,\r
+ deviceInfo->maxOutputChannels, (float)deviceInfo->defaultHighOutputLatency, (float)deviceInfo->defaultLowOutputLatency));\r
+ break;}\r
+ case eCapture: {\r
deviceInfo->maxInputChannels = paWasapi->devInfo[i].DefaultFormat.Format.nChannels;\r
deviceInfo->defaultHighInputLatency = nano100ToSeconds(paWasapi->devInfo[i].DefaultDevicePeriod);\r
deviceInfo->defaultLowInputLatency = nano100ToSeconds(paWasapi->devInfo[i].MinimumDevicePeriod);\r
- break;\r
+ PA_DEBUG(("WASAPI:%d| def.SR[%d] max.CH[%d] latency{hi[%f] lo[%f]}\n", i, (UINT32)deviceInfo->defaultSampleRate,\r
+ deviceInfo->maxInputChannels, (float)deviceInfo->defaultHighInputLatency, (float)deviceInfo->defaultLowInputLatency));\r
+ break; }\r
default:\r
- PRINT(("WASAPI: device %d bad Data FLow! \n",i));\r
- goto error;\r
+ PRINT(("WASAPI:%d| bad Data Flow!\n", i));\r
+ //continue; // do not skip from list, allow to initialize\r
break;\r
}\r
\r
- deviceInfo->defaultSampleRate = paWasapi->devInfo[i].DefaultFormat.Format.nSamplesPerSec;\r
-\r
(*hostApi)->deviceInfos[i] = deviceInfo;\r
++(*hostApi)->info.deviceCount;\r
}\r
HRESULT hr = S_OK;\r
UINT32 nFrames = 0;\r
IAudioClient *pAudioClient = NULL;\r
+ double suggestedLatency = 0.0;\r
\r
if (!pSubStream || !info || !params)\r
return E_POINTER;\r
{\r
if (pa_error)\r
(*pa_error) = error;\r
- return AUDCLNT_E_UNSUPPORTED_FORMAT;\r
+\r
+ LogHostError(hr = AUDCLNT_E_UNSUPPORTED_FORMAT);\r
+ goto done; // fail, format not supported\r
}\r
\r
// Check for Mono >> Stereo workaround\r
if ((params->channelCount == 1) && (pSubStream->wavex.Format.nChannels == 2))\r
{\r
if (blocking)\r
- return AUDCLNT_E_UNSUPPORTED_FORMAT; // fail, blocking mode not supported\r
+ {\r
+ LogHostError(hr = AUDCLNT_E_UNSUPPORTED_FORMAT);\r
+ goto done; // fail, blocking mode not supported\r
+ }\r
\r
// select mixer\r
pSubStream->monoMixer = _GetMonoToStereoMixer(params->sampleFormat);\r
if (pSubStream->monoMixer == NULL)\r
- return AUDCLNT_E_UNSUPPORTED_FORMAT; // fail, no mixer for format\r
+ {\r
+ LogHostError(hr = AUDCLNT_E_UNSUPPORTED_FORMAT);\r
+ goto done; // fail, no mixer for format\r
+ }\r
}\r
\r
+ // Correct latency to default device period (in Exclusive mode this is 10ms) if user selected 0\r
+ suggestedLatency = (params->suggestedLatency < 0.001 ? nano100ToSeconds(info->DefaultDevicePeriod) : params->suggestedLatency);\r
+\r
// Add latency frames\r
- framesPerLatency += MakeFramesFromHns(SecondsTonano100(params->suggestedLatency), pSubStream->wavex.Format.nSamplesPerSec);\r
+ framesPerLatency += MakeFramesFromHns(SecondsTonano100(suggestedLatency), pSubStream->wavex.Format.nSamplesPerSec);\r
\r
// Align frames to HD Audio packet size of 128 bytes for Exclusive mode only.\r
// Not aligning on Windows Vista will cause Event timeout, although Windows 7 will\r
&pSubStream->wavex.Format,\r
NULL);\r
\r
+ // This would mean too low latency\r
+ if (hr == AUDCLNT_E_BUFFER_SIZE_ERROR)\r
+ {\r
+ PRINT(("WASAPI: CreateAudioClient: correcting buffer size to device minimum\n"));\r
+\r
+ // User was trying to set lowest possible, so set lowest device possible\r
+ pSubStream->period = info->MinimumDevicePeriod;\r
+\r
+ // Release the previous allocations\r
+ SAFE_RELEASE(pAudioClient);\r
+\r
+ // Create a new audio client\r
+ hr = IMMDevice_Activate(info->device, &pa_IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pAudioClient);\r
+ if (hr != S_OK)\r
+ {\r
+ LogHostError(hr);\r
+ goto done;\r
+ }\r
+\r
+ // Open the stream and associate it with an audio session\r
+ hr = IAudioClient_Initialize(pAudioClient,\r
+ pSubStream->shareMode,\r
+ streamFlags/*AUDCLNT_STREAMFLAGS_EVENTCALLBACK*/,\r
+ pSubStream->period,\r
+ (pSubStream->shareMode == AUDCLNT_SHAREMODE_EXCLUSIVE ? pSubStream->period : 0),\r
+ &pSubStream->wavex.Format,\r
+ NULL);\r
+ }\r
+\r
// If the requested buffer size is not aligned...\r
if (hr == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED)\r
{\r
- PRINT(("WASAPI: CreateAudioClient: aligning buffer size"));\r
+ PRINT(("WASAPI: CreateAudioClient: aligning buffer size\n"));\r
\r
// Get the next aligned frame\r
hr = IAudioClient_GetBufferSize(pAudioClient, &nFrames);\r
}\r
\r
// Get closest format\r
- if (GetClosestFormat(pAudioClient, sampleRate, params, pSubStream->shareMode, &pSubStream->wavex) != paFormatIsSupported)\r
- return AUDCLNT_E_UNSUPPORTED_FORMAT;\r
+ if ((error = GetClosestFormat(pAudioClient, sampleRate, params, pSubStream->shareMode, &pSubStream->wavex)) != paFormatIsSupported)\r
+ {\r
+ if (pa_error)\r
+ (*pa_error) = error;\r
+\r
+ LogHostError(hr = AUDCLNT_E_UNSUPPORTED_FORMAT); // fail, format not supported\r
+ goto done;\r
+ }\r
\r
// Check for Mono >> Stereo workaround\r
if ((params->channelCount == 1) && (pSubStream->wavex.Format.nChannels == 2))\r
{\r
if (blocking)\r
- return AUDCLNT_E_UNSUPPORTED_FORMAT; // fail, blocking mode not supported\r
+ {\r
+ LogHostError(hr = AUDCLNT_E_UNSUPPORTED_FORMAT);\r
+ goto done; // fail, blocking mode not supported\r
+ }\r
\r
// select mixer\r
pSubStream->monoMixer = _GetMonoToStereoMixer(params->sampleFormat);\r
if (pSubStream->monoMixer == NULL)\r
- return AUDCLNT_E_UNSUPPORTED_FORMAT; // fail, no mixer for format\r
+ {\r
+ LogHostError(hr = AUDCLNT_E_UNSUPPORTED_FORMAT);\r
+ goto done; // fail, no mixer for format\r
+ }\r
}\r
\r
// Calculate period\r
error:\r
\r
if (stream != NULL)\r
- {\r
CloseStream(stream);\r
- PaUtil_FreeMemory(stream);\r
- }\r
\r
return result;\r
}\r