\r
#ifndef NTDDI_VERSION\r
\r
+ #define NTDDI_VERSION 0x06000000 // NTDDI_VISTA\r
+\r
#ifndef _AVRT_ //<< fix MinGW dummy compile by defining missing type: AVRT_PRIORITY\r
typedef enum _AVRT_PRIORITY\r
{\r
#define NONAMELESSUNION\r
#endif\r
\r
+ #undef NTDDI_VERSION\r
#undef WINVER\r
+ #define WINVER 0x0600\r
#undef _WIN32_WINNT\r
+ #define _WIN32_WINNT 0x0600\r
#include <sdkddkver.h>\r
#include <propkeydef.h>\r
#define COBJMACROS\r
#include <mmdeviceapi.h>\r
#include <endpointvolume.h>\r
#include <functiondiscoverykeys.h>\r
+ #include <devicetopology.h> // Used to get IKsJackDescription interface\r
#undef INITGUID\r
\r
#endif // NTDDI_VERSION\r
}\r
\r
// ------------------------------------------------------------------------------------------\r
-static double nano100ToMillis(REFERENCE_TIME ref)\r
+/*static double nano100ToMillis(REFERENCE_TIME ref)\r
{\r
// 1 nano = 0.000000001 seconds\r
//100 nano = 0.0000001 seconds\r
//100 nano = 0.0001 milliseconds\r
return ((double)ref)*0.0001;\r
-}\r
+}*/\r
\r
// ------------------------------------------------------------------------------------------\r
static double nano100ToSeconds(REFERENCE_TIME ref)\r
}\r
\r
// ------------------------------------------------------------------------------------------\r
-static REFERENCE_TIME MillisTonano100(double ref)\r
+/*static REFERENCE_TIME MillisTonano100(double ref)\r
{\r
// 1 nano = 0.000000001 seconds\r
//100 nano = 0.0000001 seconds\r
//100 nano = 0.0001 milliseconds\r
return (REFERENCE_TIME)(ref/0.0001);\r
-}\r
+}*/\r
\r
// ------------------------------------------------------------------------------------------\r
static REFERENCE_TIME SecondsTonano100(double ref)\r
\r
// ------------------------------------------------------------------------------------------\r
// Converts PaSampleFormat to bits per sample value\r
-static WORD PaSampleFormatToBytesPerSample(PaSampleFormat format_id)\r
+/*static WORD PaSampleFormatToBytesPerSample(PaSampleFormat format_id)\r
{\r
return PaSampleFormatToBitsPerSample(format_id) >> 3; // 'bits/8'\r
-}\r
+}*/\r
\r
// ------------------------------------------------------------------------------------------\r
// Converts Hns period into number of frames\r
\r
// ------------------------------------------------------------------------------------------\r
// Aligns 'v' forward\r
-static UINT32 ALIGN_FWD(UINT32 v, UINT32 align)\r
+/*static UINT32 ALIGN_FWD(UINT32 v, UINT32 align)\r
{\r
UINT32 remainder = (align ? (v % align) : 0);\r
if (remainder == 0)\r
return v;\r
return v + (align - remainder);\r
-}\r
+}*/\r
\r
// ------------------------------------------------------------------------------------------\r
// Aligns WASAPI buffer to 128 byte packet boundary. HD Audio will fail to play if buffer\r
// is misaligned. This problem was solved in Windows 7 were AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED\r
// is thrown although we must align for Vista anyway.\r
-static UINT32 AlignFramesPerBuffer(UINT32 nFrames, UINT32 nSamplesPerSec, UINT32 nBlockAlign, \r
+static UINT32 AlignFramesPerBuffer(UINT32 nFrames, UINT32 nSamplesPerSec, UINT32 nBlockAlign,\r
ALIGN_FUNC pAlignFunc)\r
{\r
#define HDA_PACKET_SIZE (128)\r
\r
frame_bytes = packets * HDA_PACKET_SIZE;\r
nFrames = frame_bytes / nBlockAlign;\r
- \r
+\r
return nFrames;\r
\r
#undef HDA_PACKET_SIZE\r
If COM is already initialized CoInitialize will either return\r
FALSE, or RPC_E_CHANGED_MODE if it was initialised in a different\r
threading mode. In either case we shouldn't consider it an error\r
- but we need to be careful to not call CoUninitialize() if \r
+ but we need to be careful to not call CoUninitialize() if\r
RPC_E_CHANGED_MODE was returned.\r
*/\r
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);\r
DWORD calling_thread_id = GetCurrentThreadId();\r
if (g_WasapiInitThread != calling_thread_id)\r
{\r
- PRINT(("WASAPI: failed CoUninitializes calling thread[%d] does not match initializing thread[%d]\n", \r
+ PRINT(("WASAPI: failed CoUninitializes calling thread[%d] does not match initializing thread[%d]\n",\r
calling_thread_id, g_WasapiInitThread));\r
}\r
else\r
}\r
}\r
break; }\r
- \r
- case WAVE_FORMAT_IEEE_FLOAT: \r
+\r
+ case WAVE_FORMAT_IEEE_FLOAT:\r
return paFloat32;\r
\r
case WAVE_FORMAT_PCM: {\r
}\r
\r
// ------------------------------------------------------------------------------------------\r
-static void wasapiFillWFEXT( WAVEFORMATEXTENSIBLE* pwfext, PaSampleFormat sampleFormat, double sampleRate, int channelCount)\r
+/*static void wasapiFillWFEXT( WAVEFORMATEXTENSIBLE* pwfext, PaSampleFormat sampleFormat, double sampleRate, int channelCount)\r
{\r
PA_DEBUG(( "sampleFormat = %lx\n" , sampleFormat ));\r
PA_DEBUG(( "sampleRate = %f\n" , sampleRate ));\r
pwfext->SubFormat = pa_KSDATAFORMAT_SUBTYPE_PCM;\r
}\r
pwfext->Format.nAvgBytesPerSec = pwfext->Format.nSamplesPerSec * pwfext->Format.nBlockAlign;\r
-}\r
+}*/\r
\r
// ------------------------------------------------------------------------------------------\r
static PaError GetClosestFormat(IAudioClient *myClient, double sampleRate,\r
// - For Shared mode we use double buffering.\r
if ((sub->shareMode == AUDCLNT_SHAREMODE_EXCLUSIVE) || fullDuplex)\r
{\r
- // Exclusive mode does not allow >1 buffers be used for Event interface, e.g. GetBuffer \r
+ // Exclusive mode does not allow >1 buffers be used for Event interface, e.g. GetBuffer\r
// call must acquire max buffer size and it all must be processed.\r
if (sub->streamFlags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK)\r
sub->userBufferAndHostMatch = 1;\r
- \r
+\r
// Use paUtilBoundedHostBufferSize because exclusive mode will starve and produce\r
// bad quality of audio\r
sub->buffers = 1;\r
}\r
\r
// ------------------------------------------------------------------------------------------\r
-static void _CalculateAlignedPeriod(PaWasapiSubStream *pSub, UINT32 *nFramesPerLatency, \r
+static void _CalculateAlignedPeriod(PaWasapiSubStream *pSub, UINT32 *nFramesPerLatency,\r
ALIGN_FUNC pAlignFunc)\r
{\r
// Align frames to HD Audio packet size of 128 bytes for Exclusive mode only.\r
}\r
\r
// ------------------------------------------------------------------------------------------\r
-static HRESULT CreateAudioClient(PaWasapiStream *pStream, PaWasapiSubStream *pSub, \r
- PaWasapiDeviceInfo *pInfo, const PaStreamParameters *params, UINT32 framesPerLatency, \r
+static HRESULT CreateAudioClient(PaWasapiStream *pStream, PaWasapiSubStream *pSub,\r
+ PaWasapiDeviceInfo *pInfo, const PaStreamParameters *params, UINT32 framesPerLatency,\r
double sampleRate, BOOL blocking, BOOL output, BOOL fullDuplex, PaError *pa_error)\r
{\r
PaError error;\r
framesPerLatency += MakeFramesFromHns(SecondsTonano100(params->suggestedLatency), pSub->wavex.Format.nSamplesPerSec);\r
#else\r
// Calculate host buffer size\r
- if ((pSub->shareMode != AUDCLNT_SHAREMODE_EXCLUSIVE) && \r
+ if ((pSub->shareMode != AUDCLNT_SHAREMODE_EXCLUSIVE) &&\r
(!pSub->streamFlags || ((pSub->streamFlags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) == 0)))\r
{\r
- framesPerLatency = PaUtil_GetFramesPerHostBuffer(userFramesPerBuffer, \r
+ framesPerLatency = PaUtil_GetFramesPerHostBuffer(userFramesPerBuffer,\r
params->suggestedLatency, pSub->wavex.Format.nSamplesPerSec, 0/*,\r
(pSub->streamFlags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK ? 0 : 1)*/);\r
}\r
\r
// Work 1:1 with user buffer (only polling allows to use >1)\r
framesPerLatency += MakeFramesFromHns(SecondsTonano100(params->suggestedLatency), pSub->wavex.Format.nSamplesPerSec);\r
- \r
+\r
// Use Polling if overall latency is > 5ms as it allows to use 100% CPU in a callback,\r
// or user specified latency parameter\r
overall = MakeHnsPeriod(framesPerLatency, pSub->wavex.Format.nSamplesPerSec);\r
if ((overall > 50000) || (params->suggestedLatency > 0))\r
{\r
- framesPerLatency = PaUtil_GetFramesPerHostBuffer(userFramesPerBuffer, \r
+ framesPerLatency = PaUtil_GetFramesPerHostBuffer(userFramesPerBuffer,\r
params->suggestedLatency, pSub->wavex.Format.nSamplesPerSec, 0/*,\r
(streamFlags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK ? 0 : 1)*/);\r
\r
*/\r
{\r
/*! AUDCLNT_E_BUFFER_SIZE_ERROR: Applies to Windows 7 and later.\r
- Indicates that the buffer duration value requested by an exclusive-mode client is \r
- out of range. The requested duration value for pull mode must not be greater than \r
+ Indicates that the buffer duration value requested by an exclusive-mode client is\r
+ out of range. The requested duration value for pull mode must not be greater than\r
500 milliseconds; for push mode the duration value must not be greater than 2 seconds.\r
*/\r
if (pSub->shareMode == AUDCLNT_SHAREMODE_EXCLUSIVE)\r
NULL);\r
\r
/*! WASAPI is tricky on large device buffer, sometimes 2000ms can be allocated sometimes\r
- less. There is no known guaranteed level thus we make subsequent tries by decreasing \r
+ less. There is no known guaranteed level thus we make subsequent tries by decreasing\r
buffer by 100ms per try.\r
*/\r
while ((hr == E_OUTOFMEMORY) && (pSub->period > (100 * 10000)))\r
IAudioClient_AddRef(pSub->client);\r
\r
// Recalculate buffers count\r
- _RecalculateBuffersCount(pSub, \r
- userFramesPerBuffer, \r
- MakeFramesFromHns(pSub->period, pSub->wavex.Format.nSamplesPerSec), \r
+ _RecalculateBuffersCount(pSub,\r
+ userFramesPerBuffer,\r
+ MakeFramesFromHns(pSub->period, pSub->wavex.Format.nSamplesPerSec),\r
fullDuplex);\r
\r
done:\r
stream->in.framesPerHostCallback = maxBufferSize;\r
\r
// Calculate frames per single buffer, if buffers > 1 then always framesPerBuffer\r
- stream->in.framesPerBuffer = \r
+ stream->in.framesPerBuffer =\r
(stream->in.userBufferAndHostMatch ? stream->in.framesPerHostCallback : framesPerBuffer);\r
\r
// Calculate buffer latency\r
stream->out.framesPerHostCallback = maxBufferSize;\r
\r
// Calculate frames per single buffer, if buffers > 1 then always framesPerBuffer\r
- stream->out.framesPerBuffer = \r
+ stream->out.framesPerBuffer =\r
(stream->out.userBufferAndHostMatch ? stream->out.framesPerHostCallback : framesPerBuffer);\r
\r
// Calculate buffer latency\r
{\r
// serious problem #1 - No, Not a problem, especially concerning Exclusive mode.\r
// Input device in exclusive mode somehow is getting large buffer always, thus we\r
- // adjust Output latency to reflect it, thus period will differ but playback will be \r
+ // adjust Output latency to reflect it, thus period will differ but playback will be\r
// normal.\r
/*if (stream->in.period != stream->out.period)\r
{\r
else\r
if (outputParameters)\r
{\r
- if ((stream->out.buffers == 1) && \r
+ if ((stream->out.buffers == 1) &&\r
(!stream->out.streamFlags || ((stream->out.streamFlags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) == 0)))\r
bufferMode = paUtilBoundedHostBufferSize;\r
}\r
\r
// Register available frames to processor\r
PaUtil_SetInputFrameCount(&stream->bufferProcessor, frames);\r
- \r
+\r
// Register host buffer pointer to processor\r
PaUtil_SetInterleavedInputChannels(&stream->bufferProcessor, 0, wasapi_buffer, stream->bufferProcessor.inputChannelCount);\r
- \r
+\r
// Copy user data to host buffer (with conversion if applicable)\r
processed = PaUtil_CopyInput(&stream->bufferProcessor, (void **)&user_buffer, frames);\r
\r
\r
// Register available frames to processor\r
PaUtil_SetOutputFrameCount(&stream->bufferProcessor, available);\r
- \r
+\r
// Register host buffer pointer to processor\r
PaUtil_SetInterleavedOutputChannels(&stream->bufferProcessor, 0, wasapi_buffer, stream->bufferProcessor.outputChannelCount);\r
- \r
+\r
// Copy user data to host buffer (with conversion if applicable)\r
processed = PaUtil_CopyOutput(&stream->bufferProcessor, (const void **)&user_buffer, available);\r
\r
return paInvalidDevice;\r
\r
// Get the endpoint device's IDeviceTopology interface.\r
- hr = IMMDevice_Activate(paWasapi->devInfo[index].device, &pa_IID_IDeviceTopology, \r
+ hr = IMMDevice_Activate(paWasapi->devInfo[index].device, &pa_IID_IDeviceTopology,\r
CLSCTX_INPROC_SERVER, NULL, (void**)&pDeviceTopology);\r
IF_FAILED_JUMP(hr, error);\r
\r
switch (connType)\r
{\r
case eConnTypeUnknown: return eJackConnTypeUnknown;\r
+#ifdef _KS_\r
case eConnType3Point5mm: return eJackConnType3Point5mm;\r
+#else\r
+ case eConnTypeEighth: return eJackConnType3Point5mm;\r
+#endif\r
case eConnTypeQuarter: return eJackConnTypeQuarter;\r
case eConnTypeAtapiInternal: return eJackConnTypeAtapiInternal;\r
case eConnTypeRCA: return eJackConnTypeRCA;\r
case eGeoLocRight: return eJackGeoLocRight;\r
case eGeoLocTop: return eJackGeoLocTop;\r
case eGeoLocBottom: return eJackGeoLocBottom;\r
+#ifdef _KS_\r
case eGeoLocRearPanel: return eJackGeoLocRearPanel;\r
+#else\r
+ case eGeoLocRearOPanel: return eJackGeoLocRearPanel;\r
+#endif\r
case eGeoLocRiser: return eJackGeoLocRiser;\r
case eGeoLocInsideMobileLid: return eJackGeoLocInsideMobileLid;\r
case eGeoLocDrivebay: return eJackGeoLocDrivebay;\r
{\r
case eGenLocPrimaryBox: return eJackGenLocPrimaryBox;\r
case eGenLocInternal: return eJackGenLocInternal;\r
+#ifdef _KS_\r
case eGenLocSeparate: return eJackGenLocSeparate;\r
+#else\r
+ case eGenLocSeperate: return eJackGenLocSeparate;\r
+#endif\r
case eGenLocOther: return eJackGenLocOther;\r
}\r
return eJackGenLocPrimaryBox;\r
return paInvalidDevice;\r
\r
// Get the endpoint device's IDeviceTopology interface.\r
- hr = IMMDevice_Activate(paWasapi->devInfo[index].device, &pa_IID_IDeviceTopology, \r
+ hr = IMMDevice_Activate(paWasapi->devInfo[index].device, &pa_IID_IDeviceTopology,\r
CLSCTX_INPROC_SERVER, NULL, (void**)&pDeviceTopology);\r
IF_FAILED_JUMP(hr, error);\r
\r
static HRESULT PollGetOutputFramesAvailable(PaWasapiStream *stream, UINT32 *available)\r
{\r
HRESULT hr;\r
- UINT32 frames = stream->out.framesPerHostCallback, \r
+ UINT32 frames = stream->out.framesPerHostCallback,\r
padding = 0;\r
\r
(*available) = 0;\r
\r
// get available\r
frames -= padding;\r
- \r
+\r
// set\r
(*available) = frames;\r
return hr;\r
DWORD sleep_ms = 0;\r
DWORD sleep_ms_in = GetFramesSleepTime(stream->in.framesPerBuffer, stream->in.wavex.Format.nSamplesPerSec);\r
DWORD sleep_ms_out = GetFramesSleepTime(stream->out.framesPerBuffer, stream->out.wavex.Format.nSamplesPerSec);\r
- \r
+\r
// Adjust polling time\r
if (stream->bufferMode != paUtilFixedHostBufferSize)\r
{\r
sleep_ms_out = GetFramesSleepTime(stream->bufferProcessor.framesPerUserBuffer, stream->out.wavex.Format.nSamplesPerSec);\r
}\r
\r
- // Choose smallest \r
+ // Choose smallest\r
if ((sleep_ms_in != 0) && (sleep_ms_out != 0))\r
sleep_ms = min(sleep_ms_in, sleep_ms_out);\r
else\r
else\r
{\r
LogHostError(hr); // not fatal, just log\r
- } \r
+ }\r
}\r
\r
// Start\r
LogHostError(hr);\r
break;\r
}\r
- \r
+\r
// output\r
if (stream->bufferMode == paUtilFixedHostBufferSize)\r
{\r