[WIN32][WASAPI] created a drain method.
[vuplus_xbmc] / xbmc / cores / AudioEngine / Sinks / AESinkWASAPI.cpp
1 /*
2  *      Copyright (C) 2010-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "AESinkWASAPI.h"
22 #include <Audioclient.h>
23 #include <avrt.h>
24 #include <initguid.h>
25 #include <Mmreg.h>
26 #include <stdint.h>
27
28 #include "../Utils/AEUtil.h"
29 #include "settings/AdvancedSettings.h"
30 #include "utils/StdString.h"
31 #include "utils/log.h"
32 #include "threads/SingleLock.h"
33 #include "utils/CharsetConverter.h"
34 #include "../Utils/AEDeviceInfo.h"
35 #include <Mmreg.h>
36 #include <mmdeviceapi.h>
37 #include "utils/StringUtils.h"
38
39 #pragma comment(lib, "Avrt.lib")
40
41 const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
42 const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
43 const IID IID_IAudioClient = __uuidof(IAudioClient);
44 const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
45
46 static const unsigned int WASAPISampleRateCount = 10;
47 static const unsigned int WASAPISampleRates[] = {384000, 192000, 176400, 96000, 88200, 48000, 44100, 32000, 22050, 11025};
48
49 #define WASAPI_SPEAKER_COUNT 21
50 static const unsigned int WASAPIChannelOrder[] = {AE_CH_RAW,
51                                                   SPEAKER_FRONT_LEFT,           SPEAKER_FRONT_RIGHT,           SPEAKER_FRONT_CENTER,
52                                                   SPEAKER_LOW_FREQUENCY,        SPEAKER_BACK_LEFT,             SPEAKER_BACK_RIGHT,
53                                                   SPEAKER_FRONT_LEFT_OF_CENTER, SPEAKER_FRONT_RIGHT_OF_CENTER,
54                                                   SPEAKER_BACK_CENTER,          SPEAKER_SIDE_LEFT,             SPEAKER_SIDE_RIGHT,
55                                                   SPEAKER_TOP_FRONT_LEFT,       SPEAKER_TOP_FRONT_RIGHT,       SPEAKER_TOP_FRONT_CENTER,
56                                                   SPEAKER_TOP_CENTER,           SPEAKER_TOP_BACK_LEFT,         SPEAKER_TOP_BACK_RIGHT,
57                                                   SPEAKER_TOP_BACK_CENTER,      SPEAKER_RESERVED,              SPEAKER_RESERVED};
58
59 static const enum AEChannel AEChannelNames[]   = {AE_CH_RAW,
60                                                   AE_CH_FL,                     AE_CH_FR,                      AE_CH_FC,
61                                                   AE_CH_LFE,                    AE_CH_BL,                      AE_CH_BR,
62                                                   AE_CH_FLOC,                   AE_CH_FROC,
63                                                   AE_CH_BC,                     AE_CH_SL,                      AE_CH_SR,
64                                                   AE_CH_TFL,                    AE_CH_TFR,                     AE_CH_TFC ,
65                                                   AE_CH_TC  ,                   AE_CH_TBL,                     AE_CH_TBR,
66                                                   AE_CH_TBC,                    AE_CH_BLOC,                    AE_CH_BROC};
67
68 static const enum AEChannel layoutsList[][16] = 
69 {
70   /* Most common configurations */
71   {AE_CH_FC,  AE_CH_NULL}, // Mono
72   {AE_CH_FL,  AE_CH_FR,  AE_CH_NULL}, // Stereo
73   {AE_CH_FL,  AE_CH_FR,  AE_CH_BL,  AE_CH_BR,  AE_CH_NULL}, // Quad
74   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_BC,  AE_CH_NULL}, // Surround
75   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_NULL}, // Standard 5.1
76   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BR,  AE_CH_NULL}, // Standard 7.1
77   /* Less common configurations */
78   {AE_CH_FL,  AE_CH_FR,  AE_CH_LFE, AE_CH_NULL}, // 2.1
79   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_BL,  AE_CH_BR,  AE_CH_NULL}, // 5.1 wide (obsolete)
80   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_BL,  AE_CH_BR,  AE_CH_FLOC,AE_CH_FROC,AE_CH_NULL}, // 7.1 wide (obsolete)
81   /* Exotic configurations */
82   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_NULL}, // 3 front speakers
83   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_NULL}, // 3 front speakers + LFE
84   {AE_CH_FL,  AE_CH_FR,  AE_CH_BL,  AE_CH_BR,  AE_CH_LFE, AE_CH_NULL}, // Quad + LFE
85   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_BC,  AE_CH_LFE, AE_CH_NULL}, // Surround + LFE
86   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_SL,  AE_CH_SR,  AE_CH_NULL}, // Standard 5.1 w/o LFE
87   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_BL,  AE_CH_BR,  AE_CH_NULL}, // 5.1 wide w/o LFE
88   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_SL,  AE_CH_SR,  AE_CH_BC,  AE_CH_NULL}, // Standard 5.1 w/o LFE + Back Center
89   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_BL,  AE_CH_BC,  AE_CH_BR,  AE_CH_NULL}, // 5.1 wide w/o LFE + Back Center
90   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_BL,  AE_CH_BR,  AE_CH_TC,  AE_CH_NULL}, // DVD speakers
91   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_BL,  AE_CH_BR,  AE_CH_BC,  AE_CH_LFE, AE_CH_NULL}, // 5.1 wide + Back Center
92   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BR,  AE_CH_NULL}, // Standard 7.1 w/o LFE
93   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_BL,  AE_CH_BR,  AE_CH_FLOC,AE_CH_FROC,AE_CH_NULL}, // 7.1 wide w/o LFE
94   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BC,  AE_CH_BR,  AE_CH_NULL}, // Standard 7.1 + Back Center
95   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BR,  AE_CH_FLOC,AE_CH_FROC,AE_CH_NULL}, // Standard 7.1 + front wide
96   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BR,  AE_CH_TFL, AE_CH_TFR, AE_CH_NULL}, // Standard 7.1 + 2 front top
97   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BR,  AE_CH_TFL, AE_CH_TFR, AE_CH_TFC, AE_CH_NULL}, // Standard 7.1 + 3 front top
98   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BR,  AE_CH_TFL, AE_CH_TFR, AE_CH_TBL, AE_CH_TBR, AE_CH_NULL}, // Standard 7.1 + 2 front top + 2 back top
99   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BR,  AE_CH_TFL, AE_CH_TFR, AE_CH_TFC, AE_CH_TBL, AE_CH_TBR, AE_CH_NULL}, // Standard 7.1 + 3 front top + 2 back top
100   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BR,  AE_CH_TFL, AE_CH_TFR, AE_CH_TFC, AE_CH_TBL, AE_CH_TBR, AE_CH_TBC, AE_CH_NULL}, // Standard 7.1 + 3 front top + 3 back top
101   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BR,  AE_CH_TFL, AE_CH_TFR, AE_CH_TFC, AE_CH_TBL, AE_CH_TBR, AE_CH_TBC, AE_CH_TC,  AE_CH_NULL} // Standard 7.1 + 3 front top + 3 back top + Top Center
102 };
103
104 struct sampleFormat
105 {
106   GUID subFormat;
107   unsigned int bitsPerSample;
108   unsigned int validBitsPerSample;
109   AEDataFormat subFormatType;
110 };
111
112 /* Sample formats go from float -> 32 bit int -> 24 bit int (packed in 32) -> -> 24 bit int -> 16 bit int */
113 static const sampleFormat testFormats[] = { {KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 32, 32, AE_FMT_FLOAT},
114                                             {KSDATAFORMAT_SUBTYPE_PCM, 32, 32, AE_FMT_S32NE},
115                                             {KSDATAFORMAT_SUBTYPE_PCM, 32, 24, AE_FMT_S24NE4},
116                                             {KSDATAFORMAT_SUBTYPE_PCM, 24, 24, AE_FMT_S24NE3},
117                                             {KSDATAFORMAT_SUBTYPE_PCM, 16, 16, AE_FMT_S16NE} };
118
119 struct winEndpointsToAEDeviceType
120 {
121   std::string winEndpointType;
122   AEDeviceType aeDeviceType;
123 };
124
125 static const winEndpointsToAEDeviceType winEndpoints[EndpointFormFactor_enum_count] =
126 {
127   {"Network Device - ",         AE_DEVTYPE_PCM},
128   {"Speakers - ",               AE_DEVTYPE_PCM},
129   {"LineLevel - ",              AE_DEVTYPE_PCM},
130   {"Headphones - ",             AE_DEVTYPE_PCM},
131   {"Microphone - ",             AE_DEVTYPE_PCM},
132   {"Headset - ",                AE_DEVTYPE_PCM},
133   {"Handset - ",                AE_DEVTYPE_PCM},
134   {"Digital Passthrough - ", AE_DEVTYPE_IEC958},
135   {"SPDIF - ",               AE_DEVTYPE_IEC958},
136   {"HDMI - ",                  AE_DEVTYPE_HDMI},
137   {"Unknown - ",                AE_DEVTYPE_PCM},
138 };
139
140 AEDeviceInfoList DeviceInfoList;
141
142 #define EXIT_ON_FAILURE(hr, reason, ...) if(FAILED(hr)) {CLog::Log(LOGERROR, reason " - %s", __VA_ARGS__, WASAPIErrToStr(hr)); goto failed;}
143
144 #define ERRTOSTR(err) case err: return #err
145
146 DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14);
147
148 DWORD ChLayoutToChMask(const enum AEChannel * layout, unsigned int * numberOfChannels = NULL)
149 {
150   if (numberOfChannels)
151     *numberOfChannels = 0;
152   if (!layout)
153     return 0;
154   
155   DWORD mask = 0;
156   unsigned int i;
157   for (i = 0; layout[i] != AE_CH_NULL; i++)
158     mask |= WASAPIChannelOrder[layout[i]];
159   
160   if (numberOfChannels)
161     *numberOfChannels = i;
162
163   return mask;
164 }
165
166 CStdStringA localWideToUtf(LPCWSTR wstr)
167 {
168   if (wstr == NULL)
169     return "";
170   int bufSize = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
171   CStdStringA strA ("", bufSize);
172   if ( bufSize == 0 || WideCharToMultiByte(CP_UTF8, 0, wstr, -1, strA.GetBuf(bufSize), bufSize, NULL, NULL) != bufSize )
173     strA.clear();
174   strA.RelBuf();
175   return strA;
176 }
177
178 CAESinkWASAPI::CAESinkWASAPI() :
179   m_needDataEvent(0),
180   m_pDevice(NULL),
181   m_pAudioClient(NULL),
182   m_pRenderClient(NULL),
183   m_encodedFormat(AE_FMT_INVALID),
184   m_encodedChannels(0),
185   m_encodedSampleRate(0),
186   sinkReqFormat(AE_FMT_INVALID),
187   sinkRetFormat(AE_FMT_INVALID),
188   m_running(false),
189   m_initialized(false),
190   m_isSuspended(false),
191   m_isDirty(false),
192   m_uiBufferLen(0),
193   m_avgTimeWaiting(50),
194   m_sinkLatency(0.0),
195   m_pBuffer(NULL),
196   m_bufferPtr(0),
197   m_hnsRequestedDuration(0)
198 {
199   m_channelLayout.Reset();
200 }
201
202 CAESinkWASAPI::~CAESinkWASAPI()
203 {
204
205 }
206
207 bool CAESinkWASAPI::Initialize(AEAudioFormat &format, std::string &device)
208 {
209   if (m_initialized)
210     return false;
211
212   m_device = device;
213   bool bdefault = false;
214
215   /* Save requested format */
216   /* Clear returned format */
217   sinkReqFormat = format.m_dataFormat;
218   sinkRetFormat = AE_FMT_INVALID;
219
220   IMMDeviceEnumerator* pEnumerator = NULL;
221   IMMDeviceCollection* pEnumDevices = NULL;
222
223   HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator);
224   EXIT_ON_FAILURE(hr, __FUNCTION__": Could not allocate WASAPI device enumerator. CoCreateInstance error code: %li", hr)
225
226   /* Get our device. First try to find the named device. */
227   UINT uiCount = 0;
228
229   hr = pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pEnumDevices);
230   EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint enumeration failed.")
231
232   hr = pEnumDevices->GetCount(&uiCount);
233   EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint count failed.")
234
235   if(StringUtils::EndsWith(device, std::string("default")))
236     bdefault = true;
237
238   if(!bdefault)
239   {
240     for (UINT i = 0; i < uiCount; i++)
241     {
242       IPropertyStore *pProperty = NULL;
243       PROPVARIANT varName;
244
245       hr = pEnumDevices->Item(i, &m_pDevice);
246       EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint failed.")
247
248       hr = m_pDevice->OpenPropertyStore(STGM_READ, &pProperty);
249       EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint properties failed.")
250
251       hr = pProperty->GetValue(PKEY_AudioEndpoint_GUID, &varName);
252       if (FAILED(hr))
253       {
254         CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint GUID failed.");
255         SAFE_RELEASE(pProperty);
256         goto failed;
257       }
258
259       std::string strDevName = localWideToUtf(varName.pwszVal);
260
261       if (device == strDevName)
262         i = uiCount;
263       else
264         SAFE_RELEASE(m_pDevice);
265
266       PropVariantClear(&varName);
267       SAFE_RELEASE(pProperty);
268     }
269   }
270   SAFE_RELEASE(pEnumDevices);
271
272   if (!m_pDevice)
273   {
274     if(!bdefault)
275       CLog::Log(LOGINFO, __FUNCTION__": Could not locate the device named \"%s\" in the list of WASAPI endpoint devices.  Trying the default device...", device.c_str());
276     hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &m_pDevice);
277     EXIT_ON_FAILURE(hr, __FUNCTION__": Could not retrieve the default WASAPI audio endpoint.")
278
279     IPropertyStore *pProperty = NULL;
280     PROPVARIANT varName;
281
282     hr = m_pDevice->OpenPropertyStore(STGM_READ, &pProperty);
283     EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint properties failed.")
284
285     hr = pProperty->GetValue(PKEY_AudioEndpoint_GUID, &varName);
286
287     device = localWideToUtf(varName.pwszVal);
288     PropVariantClear(&varName);
289     SAFE_RELEASE(pProperty);
290   }
291
292   SAFE_RELEASE(pEnumerator);
293
294   hr = m_pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&m_pAudioClient);
295   EXIT_ON_FAILURE(hr, __FUNCTION__": Activating the WASAPI endpoint device failed.")
296
297   if (!InitializeExclusive(format))
298   {
299     CLog::Log(LOGINFO, __FUNCTION__": Could not Initialize Exclusive with that format");
300     goto failed;
301   }
302
303   /* get the buffer size and calculate the frames for AE */
304   m_pAudioClient->GetBufferSize(&m_uiBufferLen);
305
306   format.m_frames       = m_uiBufferLen;
307   format.m_frameSamples = format.m_frames * format.m_channelLayout.Count();
308   m_format              = format;
309   sinkRetFormat         = format.m_dataFormat;
310
311   hr = m_pAudioClient->GetService(IID_IAudioRenderClient, (void**)&m_pRenderClient);
312   EXIT_ON_FAILURE(hr, __FUNCTION__": Could not initialize the WASAPI render client interface.")
313
314   m_needDataEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
315   hr = m_pAudioClient->SetEventHandle(m_needDataEvent);
316   EXIT_ON_FAILURE(hr, __FUNCTION__": Could not set the WASAPI event handler.");
317
318   m_initialized = true;
319   m_isDirty     = false;
320
321   // allow feeding less samples than buffer size
322   // if the device is opened exclusive and event driven, provided samples must match buffersize
323   // ActiveAE tries to align provided samples with buffer size but cannot guarantee (e.g. transcoding)
324   // this can be avoided by dropping the event mode which has not much benefit; SoftAE polls anyway
325   delete [] m_pBuffer;
326   m_pBuffer = new uint8_t[format.m_frames * format.m_frameSize];
327   m_bufferPtr = 0;
328
329   return true;
330
331 failed:
332   CLog::Log(LOGERROR, __FUNCTION__": WASAPI initialization failed.");
333   SAFE_RELEASE(pEnumDevices);
334   SAFE_RELEASE(pEnumerator);
335   SAFE_RELEASE(m_pRenderClient);
336   SAFE_RELEASE(m_pAudioClient);
337   SAFE_RELEASE(m_pDevice);
338   if(m_needDataEvent)
339   {
340     CloseHandle(m_needDataEvent);
341     m_needDataEvent = 0;
342   }
343
344   return false;
345 }
346
347 void CAESinkWASAPI::Deinitialize()
348 {
349   if (!m_initialized && !m_isDirty)
350     return;
351
352   if (m_running)
353   {
354     try
355     {
356     m_pAudioClient->Stop();  //stop the audio output
357     m_pAudioClient->Reset(); //flush buffer and reset audio clock stream position
358     }
359     catch (...)
360     {
361       CLog::Log(LOGDEBUG, __FUNCTION__, "Invalidated AudioClient - Releasing");
362     }
363   }
364   m_running = false;
365
366   CloseHandle(m_needDataEvent);
367
368   SAFE_RELEASE(m_pRenderClient);
369   SAFE_RELEASE(m_pAudioClient);
370   SAFE_RELEASE(m_pDevice);
371
372   m_initialized = false;
373
374   delete [] m_pBuffer;
375   m_bufferPtr = 0;
376 }
377
378 bool CAESinkWASAPI::IsCompatible(const AEAudioFormat format, const std::string &device)
379 {
380   if (!m_initialized || m_isDirty)
381     return false;
382
383   u_int notCompatible         = 0;
384   const u_int numTests        = 5;
385   std::string strDiffBecause ("");
386   static const char* compatibleParams[numTests] = {":Devices",
387                                                    ":Channels",
388                                                    ":Sample Rates",
389                                                    ":Data Formats",
390                                                    ":Passthrough Formats"};
391
392   notCompatible = (notCompatible  +!((AE_IS_RAW(format.m_dataFormat)  == AE_IS_RAW(m_encodedFormat))        ||
393                                      (!AE_IS_RAW(format.m_dataFormat) == !AE_IS_RAW(m_encodedFormat))))     << 1;
394   notCompatible = (notCompatible  +!((sinkReqFormat                   == format.m_dataFormat)               &&
395                                      (sinkRetFormat                   == m_format.m_dataFormat)))           << 1;
396   notCompatible = (notCompatible  + !(format.m_sampleRate             == m_format.m_sampleRate))            << 1;
397   notCompatible = (notCompatible  + !(format.m_channelLayout.Count()  == m_format.m_channelLayout.Count())) << 1;
398   notCompatible = (notCompatible  + !(m_device                        == device));
399
400   if (!notCompatible)
401   {
402     CLog::Log(LOGDEBUG, __FUNCTION__": Formats compatible - reusing existing sink");
403     return true;
404   }
405
406   for (int i = 0; i < numTests ; i++)
407   {
408     strDiffBecause += (notCompatible & 0x01) ? (std::string) compatibleParams[i] : "";
409     notCompatible    = notCompatible >> 1;
410   }
411
412   CLog::Log(LOGDEBUG, __FUNCTION__": Formats Incompatible due to different %s", strDiffBecause.c_str());
413   return false;
414 }
415
416 double CAESinkWASAPI::GetDelay()
417 {
418   if (!m_initialized)
419     return 0.0;
420
421   return m_sinkLatency;
422 }
423
424 double CAESinkWASAPI::GetCacheTime()
425 {
426   /* This function deviates from the defined usage due to the event-driven */
427   /* mode of WASAPI utilizing twin buffers which are written to in single  */
428   /* buffer chunks. Therefore the buffers are either 100% full or 50% full */
429   /* At 50% issues arise with water levels in the stream and player. For   */
430   /* this reason the cache is shown as 100% full at all times, and control */
431   /* of the buffer filling is assumed in AddPackets() and by the WASAPI    */
432   /* implementation of the WaitforSingleObject event indicating one of the */
433   /* buffers is ready for filling via AddPackets                           */
434   if (!m_initialized)
435     return 0.0;
436
437   return m_sinkLatency;
438 }
439
440 double CAESinkWASAPI::GetCacheTotal()
441 {
442   if (!m_initialized)
443     return 0.0;
444
445   return m_sinkLatency;
446 }
447
448 unsigned int CAESinkWASAPI::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio, bool blocking)
449 {
450   if (!m_initialized)
451     return 0;
452
453   HRESULT hr;
454   BYTE *buf;
455   DWORD flags = 0;
456
457 #ifndef _DEBUG
458   LARGE_INTEGER timerStart;
459   LARGE_INTEGER timerStop;
460   LARGE_INTEGER timerFreq;
461 #endif
462
463   unsigned int NumFramesRequested = m_format.m_frames;
464   unsigned int FramesToCopy = std::min(m_format.m_frames - m_bufferPtr, frames);
465   if (m_bufferPtr != 0 || frames != m_format.m_frames)
466   {
467     memcpy(m_pBuffer+m_bufferPtr*m_format.m_frameSize, data, FramesToCopy*m_format.m_frameSize);
468     m_bufferPtr += FramesToCopy;
469     if (frames != m_format.m_frames)
470       return frames;
471   }
472
473   if (!m_running) //first time called, pre-fill buffer then start audio client
474   {
475     hr = m_pAudioClient->Reset();
476     if (FAILED(hr))
477     {
478       CLog::Log(LOGERROR, __FUNCTION__ " AudioClient reset failed due to %s", WASAPIErrToStr(hr));
479       return 0;
480     }
481     hr = m_pRenderClient->GetBuffer(NumFramesRequested, &buf);
482     if (FAILED(hr))
483     {
484       #ifdef _DEBUG
485       CLog::Log(LOGERROR, __FUNCTION__": GetBuffer failed due to %s", WASAPIErrToStr(hr));
486       #endif
487       m_isDirty = true; //flag new device or re-init needed
488       return INT_MAX;
489     }
490
491     /* Inject one buffer of silence if sink has just opened */
492     /* to avoid losing start of stream or GUI sound         */
493     if (g_advancedSettings.m_streamSilence)
494       memcpy(buf, data, NumFramesRequested * m_format.m_frameSize); //fill buffer with audio
495     else
496       memset(buf,    0, NumFramesRequested * m_format.m_frameSize); //fill buffer with silence
497
498     hr = m_pRenderClient->ReleaseBuffer(NumFramesRequested, flags); //pass back to audio driver
499     if (FAILED(hr))
500     {
501       #ifdef _DEBUG
502       CLog::Log(LOGDEBUG, __FUNCTION__": ReleaseBuffer failed due to %s.", WASAPIErrToStr(hr));
503       #endif
504       m_isDirty = true; //flag new device or re-init needed
505       return INT_MAX;
506     }
507     hr = m_pAudioClient->Start(); //start the audio driver running
508     if (FAILED(hr))
509       CLog::Log(LOGERROR, __FUNCTION__": AudioClient Start Failed");
510     m_running = true; //signal that we're processing frames
511     return g_advancedSettings.m_streamSilence ? NumFramesRequested : 0U;
512   }
513
514 #ifndef _DEBUG
515   /* Get clock time for latency checks */
516   QueryPerformanceFrequency(&timerFreq);
517   QueryPerformanceCounter(&timerStart);
518 #endif
519
520   /* Wait for Audio Driver to tell us it's got a buffer available */
521   DWORD eventAudioCallback;
522   if(!blocking)
523     eventAudioCallback = WaitForSingleObject(m_needDataEvent, 0);
524   else
525     eventAudioCallback = WaitForSingleObject(m_needDataEvent, 1100);
526
527   if (!blocking)
528   {
529     if(eventAudioCallback != WAIT_OBJECT_0)
530           return 0;
531   }
532   else
533   {
534     if(eventAudioCallback != WAIT_OBJECT_0 || !&buf)
535     {
536       /* Event handle timed out - flag sink as dirty for re-initializing */
537       CLog::Log(LOGERROR, __FUNCTION__": Endpoint Buffer timed out");
538       if (g_advancedSettings.m_streamSilence)
539       {
540         m_isDirty = true; //flag new device or re-init needed
541         Deinitialize();
542         m_running = false;
543         return INT_MAX;
544       }
545     }
546   }
547
548
549   if (!m_running)
550     return 0;
551
552 #ifndef _DEBUG
553   QueryPerformanceCounter(&timerStop);
554   LONGLONG timerDiff = timerStop.QuadPart - timerStart.QuadPart;
555   double timerElapsed = (double) timerDiff * 1000.0 / (double) timerFreq.QuadPart;
556   m_avgTimeWaiting += (timerElapsed - m_avgTimeWaiting) * 0.5;
557
558   if (m_avgTimeWaiting < 3.0)
559   {
560     CLog::Log(LOGDEBUG, __FUNCTION__": Possible AQ Loss: Avg. Time Waiting for Audio Driver callback : %dmsec", (int)m_avgTimeWaiting);
561   }
562 #endif
563
564   hr = m_pRenderClient->GetBuffer(NumFramesRequested, &buf);
565   if (FAILED(hr))
566   {
567     #ifdef _DEBUG
568       CLog::Log(LOGERROR, __FUNCTION__": GetBuffer failed due to %s", WASAPIErrToStr(hr));
569     #endif
570     return INT_MAX;
571   }
572   memcpy(buf, m_bufferPtr == 0 ? data : m_pBuffer, NumFramesRequested * m_format.m_frameSize); //fill buffer
573   m_bufferPtr = 0;
574   hr = m_pRenderClient->ReleaseBuffer(NumFramesRequested, flags); //pass back to audio driver
575   if (FAILED(hr))
576   {
577     #ifdef _DEBUG
578     CLog::Log(LOGDEBUG, __FUNCTION__": ReleaseBuffer failed due to %s.", WASAPIErrToStr(hr));
579     #endif
580     return INT_MAX;
581   }
582
583   if (FramesToCopy != frames)
584   {
585     m_bufferPtr = frames-FramesToCopy;
586     memcpy(m_pBuffer, data+FramesToCopy*m_format.m_frameSize, m_bufferPtr*m_format.m_frameSize);
587   }
588
589   return frames;
590 }
591
592 bool CAESinkWASAPI::SoftSuspend()
593 {
594   /* Sink has been asked to suspend output - we release audio   */
595   /* device as we are in exclusive mode and thus allow external */
596   /* audio sources to play. This requires us to reinitialize    */
597   /* on resume.                                                 */
598
599   Deinitialize();
600
601   return true;
602 }
603
604 bool CAESinkWASAPI::SoftResume()
605 {
606   /* Sink asked to resume output. To release audio device in    */
607   /* exclusive mode we release the device context and therefore */
608   /* must reinitialize. Return false to force re-init by engine */
609
610   return false;
611 }
612
613 void CAESinkWASAPI::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool force)
614 {
615   IMMDeviceEnumerator* pEnumerator = NULL;
616   IMMDeviceCollection* pEnumDevices = NULL;
617   CAEDeviceInfo        deviceInfo;
618   CAEChannelInfo       deviceChannels;
619
620   WAVEFORMATEXTENSIBLE wfxex = {0};
621   HRESULT              hr;
622
623   // add default device entry
624   deviceInfo.m_deviceName       = std::string("default");
625   deviceInfo.m_displayName      = std::string("default");
626
627   /* Store the device info */
628   deviceInfoList.push_back(deviceInfo);
629
630   hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator);
631   EXIT_ON_FAILURE(hr, __FUNCTION__": Could not allocate WASAPI device enumerator. CoCreateInstance error code: %li", hr)
632
633   UINT uiCount = 0;
634
635   hr = pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pEnumDevices);
636   EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint enumeration failed.")
637
638   hr = pEnumDevices->GetCount(&uiCount);
639   EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint count failed.")
640
641   for (UINT i = 0; i < uiCount; i++)
642   {
643     IMMDevice *pDevice = NULL;
644     IPropertyStore *pProperty = NULL;
645     PROPVARIANT varName;
646     PropVariantInit(&varName);
647
648     deviceInfo.m_channels.Reset();
649     deviceInfo.m_dataFormats.clear();
650     deviceInfo.m_sampleRates.clear();
651
652     hr = pEnumDevices->Item(i, &pDevice);
653     if (FAILED(hr))
654     {
655       CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint failed.");
656       goto failed;
657     }
658
659     hr = pDevice->OpenPropertyStore(STGM_READ, &pProperty);
660     if (FAILED(hr))
661     {
662       CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint properties failed.");
663       SAFE_RELEASE(pDevice);
664       goto failed;
665     }
666
667     hr = pProperty->GetValue(PKEY_Device_FriendlyName, &varName);
668     if (FAILED(hr))
669     {
670       CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint device name failed.");
671       SAFE_RELEASE(pDevice);
672       SAFE_RELEASE(pProperty);
673       goto failed;
674     }
675
676     std::string strFriendlyName = localWideToUtf(varName.pwszVal);
677     PropVariantClear(&varName);
678
679     hr = pProperty->GetValue(PKEY_AudioEndpoint_GUID, &varName);
680     if(FAILED(hr))
681     {
682       CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint GUID failed.");
683       SAFE_RELEASE(pDevice);
684       SAFE_RELEASE(pProperty);
685       goto failed;
686     }
687
688     std::string strDevName = localWideToUtf(varName.pwszVal);
689     PropVariantClear(&varName);
690
691     hr = pProperty->GetValue(PKEY_AudioEndpoint_FormFactor, &varName);
692     if (FAILED(hr))
693     {
694       CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint form factor failed.");
695       SAFE_RELEASE(pDevice);
696       SAFE_RELEASE(pProperty);
697       goto failed;
698     }
699     std::string strWinDevType = winEndpoints[(EndpointFormFactor)varName.uiVal].winEndpointType;
700     AEDeviceType aeDeviceType = winEndpoints[(EndpointFormFactor)varName.uiVal].aeDeviceType;
701
702     PropVariantClear(&varName);
703
704     hr = pProperty->GetValue(PKEY_AudioEndpoint_PhysicalSpeakers, &varName);
705     if (FAILED(hr))
706     {
707       CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint speaker layout failed.");
708       SAFE_RELEASE(pDevice);
709       SAFE_RELEASE(pProperty);
710       goto failed;
711     }
712     unsigned int uiChannelMask = std::max(varName.uintVal, (unsigned int) KSAUDIO_SPEAKER_STEREO);
713
714     deviceChannels.Reset();
715
716     for (unsigned int c = 0; c < WASAPI_SPEAKER_COUNT; c++)
717     {
718       if (uiChannelMask & WASAPIChannelOrder[c])
719         deviceChannels += AEChannelNames[c];
720     }
721
722     PropVariantClear(&varName);
723
724     IAudioClient *pClient;
725     hr = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pClient);
726     if (SUCCEEDED(hr))
727     {
728       /* Test format DTS-HD */
729       wfxex.Format.cbSize               = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
730       wfxex.Format.nSamplesPerSec       = 192000;
731       wfxex.dwChannelMask               = KSAUDIO_SPEAKER_7POINT1_SURROUND;
732       wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
733       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD;
734       wfxex.Format.wBitsPerSample       = 16;
735       wfxex.Samples.wValidBitsPerSample = 16;
736       wfxex.Format.nChannels            = 8;
737       wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
738       wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
739       hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
740       if (SUCCEEDED(hr))
741         deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_DTSHD));
742
743       /* Test format Dolby TrueHD */
744       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP;
745       hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
746       if (SUCCEEDED(hr))
747         deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_TRUEHD));
748
749       /* Test format Dolby EAC3 */
750       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS;
751       wfxex.Format.nChannels            = 2;
752       wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
753       wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
754       hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
755       if (SUCCEEDED(hr))
756         deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_EAC3));
757
758       /* Test format DTS */
759       wfxex.Format.nSamplesPerSec       = 48000;
760       wfxex.dwChannelMask               = KSAUDIO_SPEAKER_5POINT1;
761       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_DTS;
762       wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
763       wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
764       hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
765       if (SUCCEEDED(hr))
766         deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_DTS));
767
768       /* Test format Dolby AC3 */
769       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL;
770       hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
771       if (SUCCEEDED(hr))
772         deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_AC3));
773
774       /* Test format AAC */
775       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_AAC;
776       hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
777       if (SUCCEEDED(hr))
778         deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_AAC));
779
780       /* Test format for PCM format iteration */
781       wfxex.Format.cbSize               = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
782       wfxex.dwChannelMask               = KSAUDIO_SPEAKER_STEREO;
783       wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
784       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
785
786       for (int p = AE_FMT_FLOAT; p > AE_FMT_INVALID; p--)
787       {
788         if (p < AE_FMT_FLOAT)
789           wfxex.SubFormat               = KSDATAFORMAT_SUBTYPE_PCM;
790         wfxex.Format.wBitsPerSample     = CAEUtil::DataFormatToBits((AEDataFormat) p);
791         wfxex.Format.nBlockAlign        = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
792         wfxex.Format.nAvgBytesPerSec    = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
793         if (p <= AE_FMT_S24NE4 && p >= AE_FMT_S24BE4)
794         {
795           wfxex.Samples.wValidBitsPerSample = 24;
796         }
797         else
798         {
799           wfxex.Samples.wValidBitsPerSample = wfxex.Format.wBitsPerSample;
800         }
801
802         hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
803         if (SUCCEEDED(hr))
804           deviceInfo.m_dataFormats.push_back((AEDataFormat) p);
805       }
806
807       /* Test format for sample rate iteration */
808       wfxex.Format.cbSize               = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
809       wfxex.dwChannelMask               = KSAUDIO_SPEAKER_STEREO;
810       wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
811       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_PCM;
812       wfxex.Format.wBitsPerSample       = 16;
813       wfxex.Samples.wValidBitsPerSample = 16;
814       wfxex.Format.nChannels            = 2;
815       wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
816       wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
817
818       for (int j = 0; j < WASAPISampleRateCount; j++)
819       {
820         wfxex.Format.nSamplesPerSec     = WASAPISampleRates[j];
821         wfxex.Format.nAvgBytesPerSec    = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
822         hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
823         if (SUCCEEDED(hr))
824           deviceInfo.m_sampleRates.push_back(WASAPISampleRates[j]);
825       }
826
827       /* Test format for channels iteration */
828       wfxex.Format.cbSize               = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
829       wfxex.dwChannelMask               = KSAUDIO_SPEAKER_STEREO;
830       wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
831       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_PCM;
832       wfxex.Format.nSamplesPerSec       = 48000;
833       wfxex.Format.wBitsPerSample       = 16;
834       wfxex.Samples.wValidBitsPerSample = 16;
835       wfxex.Format.nChannels            = 2;
836       wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
837       wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
838
839       bool hasLpcm = false;
840
841       // Try with KSAUDIO_SPEAKER_DIRECTOUT
842       for (unsigned int k = WASAPI_SPEAKER_COUNT; k > 0; k--)
843       {
844         wfxex.dwChannelMask             = KSAUDIO_SPEAKER_DIRECTOUT;
845         wfxex.Format.nChannels          = k;
846         wfxex.Format.nBlockAlign        = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
847         wfxex.Format.nAvgBytesPerSec    = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
848         hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
849         if (SUCCEEDED(hr))
850         {
851           if (k > 3) // Add only multichannel LPCM
852           {
853             deviceInfo.m_dataFormats.push_back(AE_FMT_LPCM);
854             hasLpcm = true;
855           }
856           break;
857         }
858       }
859
860       /* Try with reported channel mask */
861       for (unsigned int k = WASAPI_SPEAKER_COUNT; k > 0; k--)
862       {
863         wfxex.dwChannelMask             = uiChannelMask;
864         wfxex.Format.nChannels          = k;
865         wfxex.Format.nBlockAlign        = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
866         wfxex.Format.nAvgBytesPerSec    = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
867         hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
868         if (SUCCEEDED(hr))
869         {
870           if ( !hasLpcm && k > 3) // Add only multichannel LPCM
871           {
872             deviceInfo.m_dataFormats.push_back(AE_FMT_LPCM);
873             hasLpcm = true;
874           }
875           break;
876         }
877       }
878
879       /* Try with specific speakers configurations */
880       for (unsigned int i = 0; i < ARRAYSIZE(layoutsList); i++)
881       {
882         unsigned int nmbOfCh;
883         wfxex.dwChannelMask             = ChLayoutToChMask(layoutsList[i], &nmbOfCh);
884         wfxex.Format.nChannels          = nmbOfCh;
885         wfxex.Format.nBlockAlign        = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
886         wfxex.Format.nAvgBytesPerSec    = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
887         hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
888         if (SUCCEEDED(hr))
889         {
890           if ( deviceChannels.Count() < nmbOfCh)
891             deviceChannels = layoutsList[i];
892           if ( !hasLpcm && nmbOfCh > 3) // Add only multichannel LPCM
893           {
894             deviceInfo.m_dataFormats.push_back(AE_FMT_LPCM);
895             hasLpcm = true;
896           }
897         }
898       }
899       pClient->Release();
900     }
901     else
902     {
903       CLog::Log(LOGDEBUG, __FUNCTION__": Failed to activate device for passthrough capability testing.");
904     }
905
906     SAFE_RELEASE(pDevice);
907     SAFE_RELEASE(pProperty);
908
909     deviceInfo.m_deviceName       = strDevName;
910     deviceInfo.m_displayName      = strWinDevType.append(strFriendlyName);
911     deviceInfo.m_displayNameExtra = std::string("WASAPI: ").append(strFriendlyName);
912     deviceInfo.m_deviceType       = aeDeviceType;
913     deviceInfo.m_channels         = deviceChannels;
914
915     /* Store the device info */
916     deviceInfoList.push_back(deviceInfo);
917   }
918   return;
919
920 failed:
921
922   if (FAILED(hr))
923     CLog::Log(LOGERROR, __FUNCTION__": Failed to enumerate WASAPI endpoint devices (%s).", WASAPIErrToStr(hr));
924
925   SAFE_RELEASE(pEnumDevices);
926   SAFE_RELEASE(pEnumerator);
927 }
928
929 //Private utility functions////////////////////////////////////////////////////
930
931 void CAESinkWASAPI::BuildWaveFormatExtensible(AEAudioFormat &format, WAVEFORMATEXTENSIBLE &wfxex)
932 {
933   wfxex.Format.wFormatTag        = WAVE_FORMAT_EXTENSIBLE;
934   wfxex.Format.cbSize            = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
935
936
937   if (!AE_IS_RAW(format.m_dataFormat)) // PCM data
938   {
939     wfxex.dwChannelMask          = SpeakerMaskFromAEChannels(format.m_channelLayout);
940     wfxex.Format.nChannels       = (WORD)format.m_channelLayout.Count();
941     wfxex.Format.nSamplesPerSec  = format.m_sampleRate;
942     wfxex.Format.wBitsPerSample  = CAEUtil::DataFormatToBits((AEDataFormat) format.m_dataFormat);
943     wfxex.SubFormat              = format.m_dataFormat <= AE_FMT_FLOAT ? KSDATAFORMAT_SUBTYPE_PCM : KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
944   }
945   else //Raw bitstream
946   {
947     wfxex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
948     if (format.m_dataFormat == AE_FMT_AC3 || format.m_dataFormat == AE_FMT_DTS)
949     {
950       wfxex.dwChannelMask               = bool (format.m_channelLayout.Count() == 2) ? KSAUDIO_SPEAKER_STEREO : KSAUDIO_SPEAKER_5POINT1;
951       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL;
952       wfxex.Format.wBitsPerSample       = 16;
953       wfxex.Samples.wValidBitsPerSample = 16;
954       wfxex.Format.nChannels            = (WORD)format.m_channelLayout.Count();
955       wfxex.Format.nSamplesPerSec       = format.m_sampleRate;
956     }
957     else if (format.m_dataFormat == AE_FMT_EAC3 || format.m_dataFormat == AE_FMT_TRUEHD || format.m_dataFormat == AE_FMT_DTSHD)
958     {
959       /* IEC 61937 transmissions over HDMI */            
960       wfxex.Format.nSamplesPerSec       = 192000L;
961       wfxex.Format.wBitsPerSample       = 16;
962       wfxex.Samples.wValidBitsPerSample = 16;
963       wfxex.dwChannelMask               = KSAUDIO_SPEAKER_7POINT1_SURROUND;
964
965       switch (format.m_dataFormat)
966       {
967         case AE_FMT_EAC3:
968           wfxex.SubFormat             = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS;
969           wfxex.Format.nChannels      = 2; // One IEC 60958 Line.
970           wfxex.dwChannelMask         = KSAUDIO_SPEAKER_5POINT1;
971           break;
972         case AE_FMT_TRUEHD:
973           wfxex.SubFormat             = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP;
974           wfxex.Format.nChannels      = 8; // Four IEC 60958 Lines.
975           wfxex.dwChannelMask         = KSAUDIO_SPEAKER_7POINT1_SURROUND;
976           break;
977         case AE_FMT_DTSHD:
978           wfxex.SubFormat             = KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD;
979           wfxex.Format.nChannels      = 8; // Four IEC 60958 Lines.
980           wfxex.dwChannelMask         = KSAUDIO_SPEAKER_7POINT1_SURROUND;
981           break;
982       }
983
984       if (format.m_channelLayout.Count() == 8)
985         wfxex.dwChannelMask         = KSAUDIO_SPEAKER_7POINT1_SURROUND;
986       else
987         wfxex.dwChannelMask         = KSAUDIO_SPEAKER_5POINT1;
988     }
989   }
990
991   if (wfxex.Format.wBitsPerSample == 32 && wfxex.SubFormat != KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
992     wfxex.Samples.wValidBitsPerSample = 24;
993   else
994     wfxex.Samples.wValidBitsPerSample = wfxex.Format.wBitsPerSample;
995
996   wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
997   wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
998 }
999
1000 void CAESinkWASAPI::BuildWaveFormatExtensibleIEC61397(AEAudioFormat &format, WAVEFORMATEXTENSIBLE_IEC61937 &wfxex)
1001 {
1002   /* Fill the common structure */
1003   BuildWaveFormatExtensible(format, wfxex.FormatExt);
1004
1005   /* Code below kept for future use - preferred for later Windows versions */
1006   /* but can cause problems on older Windows versions and drivers          */
1007   /*
1008   wfxex.FormatExt.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE_IEC61937)-sizeof(WAVEFORMATEX);
1009   wfxex.dwEncodedChannelCount   = format.m_channelLayout.Count();
1010   wfxex.dwEncodedSamplesPerSec  = bool(format.m_dataFormat == AE_FMT_TRUEHD ||
1011                                        format.m_dataFormat == AE_FMT_DTSHD  ||
1012                                        format.m_dataFormat == AE_FMT_EAC3) ? 96000L : 48000L;
1013   wfxex.dwAverageBytesPerSec    = 0; //Ignored */
1014 }
1015
1016 bool CAESinkWASAPI::InitializeExclusive(AEAudioFormat &format)
1017 {
1018   WAVEFORMATEXTENSIBLE_IEC61937 wfxex_iec61937;
1019   WAVEFORMATEXTENSIBLE &wfxex = wfxex_iec61937.FormatExt;
1020
1021   if (format.m_dataFormat <= AE_FMT_FLOAT)
1022     BuildWaveFormatExtensible(format, wfxex);
1023   else
1024     BuildWaveFormatExtensibleIEC61397(format, wfxex_iec61937);
1025
1026   /* Test for incomplete format and provide defaults */
1027   if (format.m_sampleRate == 0 ||
1028       format.m_channelLayout == NULL ||
1029       format.m_dataFormat <= AE_FMT_INVALID ||
1030       format.m_dataFormat >= AE_FMT_MAX ||
1031       format.m_channelLayout.Count() == 0)
1032   {
1033     wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
1034     wfxex.Format.nChannels            = 2;
1035     wfxex.Format.nSamplesPerSec       = 44100L;
1036     wfxex.Format.wBitsPerSample       = 16;
1037     wfxex.Format.nBlockAlign          = 4;
1038     wfxex.Samples.wValidBitsPerSample = 16;
1039     wfxex.Format.cbSize               = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
1040     wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nBlockAlign * wfxex.Format.nSamplesPerSec;
1041     wfxex.dwChannelMask               = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
1042     wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_PCM;
1043   }
1044
1045   HRESULT hr = m_pAudioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
1046
1047   if (SUCCEEDED(hr))
1048   {
1049     CLog::Log(LOGINFO, __FUNCTION__": Format is Supported - will attempt to Initialize");
1050     goto initialize;
1051   }
1052   else if (hr != AUDCLNT_E_UNSUPPORTED_FORMAT) //It failed for a reason unrelated to an unsupported format.
1053   {
1054     CLog::Log(LOGERROR, __FUNCTION__": IsFormatSupported failed (%s)", WASAPIErrToStr(hr));
1055     return false;
1056   }
1057   else if (AE_IS_RAW(format.m_dataFormat)) //No sense in trying other formats for passthrough.
1058     return false;
1059
1060   CLog::Log(LOGERROR, __FUNCTION__": IsFormatSupported failed (%s) - trying to find a compatible format", WASAPIErrToStr(hr));
1061
1062   int closestMatch;
1063
1064   /* The requested format is not supported by the device.  Find something that works */
1065   for (int j = 0; j < sizeof(testFormats)/sizeof(sampleFormat); j++)
1066   {
1067     closestMatch = -1;
1068
1069     wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
1070     wfxex.SubFormat                   = testFormats[j].subFormat;
1071     wfxex.Format.wBitsPerSample       = testFormats[j].bitsPerSample;
1072     wfxex.Samples.wValidBitsPerSample = testFormats[j].validBitsPerSample;
1073     wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
1074
1075     for (int i = 0 ; i < WASAPISampleRateCount; i++)
1076     {
1077       wfxex.Format.nSamplesPerSec    = WASAPISampleRates[i];
1078       wfxex.Format.nAvgBytesPerSec   = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
1079
1080       /* Trace format match iteration loop via log */
1081       #if 0
1082       CLog::Log(LOGDEBUG, "WASAPI: Trying Format: %s, %d, %d, %d", CAEUtil::DataFormatToStr(testFormats[j].subFormatType),
1083                                                                    wfxex.Format.nSamplesPerSec,
1084                                                                    wfxex.Format.wBitsPerSample,
1085                                                                    wfxex.Samples.wValidBitsPerSample);
1086       #endif
1087
1088       hr = m_pAudioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
1089
1090       if (SUCCEEDED(hr))
1091       {
1092         /* If the current sample rate matches the source then stop looking and use it */
1093         if ((WASAPISampleRates[i] == format.m_sampleRate) && (testFormats[j].subFormatType <= format.m_dataFormat))
1094           goto initialize;
1095         /* If this rate is closer to the source then the previous one, save it */
1096         else if (closestMatch < 0 || abs((int)WASAPISampleRates[i] - (int)format.m_sampleRate) < abs((int)WASAPISampleRates[closestMatch] - (int)format.m_sampleRate))
1097           closestMatch = i;
1098       }
1099       else if (hr != AUDCLNT_E_UNSUPPORTED_FORMAT)
1100           CLog::Log(LOGERROR, __FUNCTION__": IsFormatSupported failed (%s)", WASAPIErrToStr(hr));
1101     }
1102
1103     if (closestMatch >= 0)
1104     {
1105       wfxex.Format.nSamplesPerSec    = WASAPISampleRates[closestMatch];
1106       wfxex.Format.nAvgBytesPerSec   = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
1107       goto initialize;
1108     }
1109   }
1110
1111   CLog::Log(LOGERROR, __FUNCTION__": Unable to locate a supported output format for the device.  Check the speaker settings in the control panel.");
1112
1113   /* We couldn't find anything supported. This should never happen      */
1114   /* unless the user set the wrong speaker setting in the control panel */
1115   return false;
1116
1117 initialize:
1118
1119   AEChannelsFromSpeakerMask(wfxex.dwChannelMask);
1120
1121   /* When the stream is raw, the values in the format structure are set to the link    */
1122   /* parameters, so store the encoded stream values here for the IsCompatible function */
1123   m_encodedFormat     = format.m_dataFormat;
1124   m_encodedChannels   = wfxex.Format.nChannels;
1125   m_encodedSampleRate = format.m_encodedRate;
1126   wfxex_iec61937.dwEncodedChannelCount = wfxex.Format.nChannels;
1127   wfxex_iec61937.dwEncodedSamplesPerSec = m_encodedSampleRate;
1128
1129   /* Set up returned sink format for engine */
1130   if (!AE_IS_RAW(format.m_dataFormat))
1131   {
1132     if (wfxex.Format.wBitsPerSample == 32)
1133     {
1134       if (wfxex.SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
1135         format.m_dataFormat = AE_FMT_FLOAT;
1136       else if (wfxex.Samples.wValidBitsPerSample == 32)
1137         format.m_dataFormat = AE_FMT_S32NE;
1138       else
1139         format.m_dataFormat = AE_FMT_S24NE4;
1140     }
1141     else if (wfxex.Format.wBitsPerSample == 24)
1142       format.m_dataFormat = AE_FMT_S24NE3;
1143     else
1144       format.m_dataFormat = AE_FMT_S16NE;
1145   }
1146
1147   format.m_sampleRate    = wfxex.Format.nSamplesPerSec; //PCM: Sample rate.  RAW: Link speed
1148   format.m_frameSize     = (wfxex.Format.wBitsPerSample >> 3) * wfxex.Format.nChannels;
1149
1150   REFERENCE_TIME audioSinkBufferDurationMsec, hnsLatency;
1151
1152   /* Get m_audioSinkBufferSizeMsec from advancedsettings.xml */
1153   audioSinkBufferDurationMsec = (REFERENCE_TIME)g_advancedSettings.m_audioSinkBufferDurationMsec * 10000;
1154
1155   /* Use advancedsetting value for buffer size as long as it's over minimum set above */
1156   audioSinkBufferDurationMsec = (REFERENCE_TIME)std::max(audioSinkBufferDurationMsec, (REFERENCE_TIME)500000);
1157   audioSinkBufferDurationMsec = (REFERENCE_TIME)((audioSinkBufferDurationMsec / format.m_frameSize) * format.m_frameSize); //even number of frames
1158
1159   if (AE_IS_RAW(format.m_dataFormat))
1160     format.m_dataFormat = AE_FMT_S16NE;
1161
1162   hr = m_pAudioClient->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE, AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST,
1163                                     audioSinkBufferDurationMsec, audioSinkBufferDurationMsec, &wfxex.Format, NULL);
1164
1165   m_hnsRequestedDuration = audioSinkBufferDurationMsec;
1166
1167   if (hr == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED)
1168   {
1169     /* WASAPI requires aligned buffer */
1170     /* Get the next aligned frame     */
1171     hr = m_pAudioClient->GetBufferSize(&m_uiBufferLen);
1172     if (FAILED(hr))
1173     {
1174       CLog::Log(LOGERROR, __FUNCTION__": GetBufferSize Failed : %s", WASAPIErrToStr(hr));
1175       return false;
1176     }
1177
1178     audioSinkBufferDurationMsec = (REFERENCE_TIME) ((10000.0 * 1000 / wfxex.Format.nSamplesPerSec * m_uiBufferLen) + 0.5);
1179
1180     /* Release the previous allocations */
1181     SAFE_RELEASE(m_pAudioClient);
1182
1183     /* Create a new audio client */
1184     hr = m_pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&m_pAudioClient);
1185     if (FAILED(hr))
1186     {
1187       CLog::Log(LOGERROR, __FUNCTION__": Device Activation Failed : %s", WASAPIErrToStr(hr));
1188       return false;
1189     }
1190
1191     /* Open the stream and associate it with an audio session */
1192     hr = m_pAudioClient->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE, AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST,
1193                                       audioSinkBufferDurationMsec, audioSinkBufferDurationMsec, &wfxex.Format, NULL);
1194   }
1195   if (FAILED(hr))
1196   {
1197     CLog::Log(LOGERROR, __FUNCTION__": Failed to initialize WASAPI in exclusive mode %d - (%s).", HRESULT(hr), WASAPIErrToStr(hr));
1198     CLog::Log(LOGDEBUG, "  Sample Rate     : %d", wfxex.Format.nSamplesPerSec);
1199     CLog::Log(LOGDEBUG, "  Sample Format   : %s", CAEUtil::DataFormatToStr(format.m_dataFormat));
1200     CLog::Log(LOGDEBUG, "  Bits Per Sample : %d", wfxex.Format.wBitsPerSample);
1201     CLog::Log(LOGDEBUG, "  Valid Bits/Samp : %d", wfxex.Samples.wValidBitsPerSample);
1202     CLog::Log(LOGDEBUG, "  Channel Count   : %d", wfxex.Format.nChannels);
1203     CLog::Log(LOGDEBUG, "  Block Align     : %d", wfxex.Format.nBlockAlign);
1204     CLog::Log(LOGDEBUG, "  Avg. Bytes Sec  : %d", wfxex.Format.nAvgBytesPerSec);
1205     CLog::Log(LOGDEBUG, "  Samples/Block   : %d", wfxex.Samples.wSamplesPerBlock);
1206     CLog::Log(LOGDEBUG, "  Format cBSize   : %d", wfxex.Format.cbSize);
1207     CLog::Log(LOGDEBUG, "  Channel Layout  : %s", ((std::string)format.m_channelLayout).c_str());
1208     CLog::Log(LOGDEBUG, "  Enc. Channels   : %d", wfxex_iec61937.dwEncodedChannelCount);
1209     CLog::Log(LOGDEBUG, "  Enc. Samples/Sec: %d", wfxex_iec61937.dwEncodedSamplesPerSec);
1210     CLog::Log(LOGDEBUG, "  Channel Mask    : %d", wfxex.dwChannelMask);
1211     CLog::Log(LOGDEBUG, "  Periodicty      : %d", audioSinkBufferDurationMsec);
1212     return false;
1213   }
1214
1215   /* Latency of WASAPI buffers in event-driven mode is equal to the returned value  */
1216   /* of GetStreamLatency converted from 100ns intervals to seconds then multiplied  */
1217   /* by two as there are two equally-sized buffers and playback starts when the     */
1218   /* second buffer is filled. Multiplying the returned 100ns intervals by 0.0000002 */
1219   /* is handles both the unit conversion and twin buffers.                          */
1220   hr = m_pAudioClient->GetStreamLatency(&hnsLatency);
1221   if (FAILED(hr))
1222   {
1223     CLog::Log(LOGERROR, __FUNCTION__": GetStreamLatency Failed : %s", WASAPIErrToStr(hr));
1224     return false;
1225   }
1226
1227   m_sinkLatency = hnsLatency * 0.0000002;
1228
1229   CLog::Log(LOGINFO, __FUNCTION__": WASAPI Exclusive Mode Sink Initialized using: %s, %d, %d",
1230                                      CAEUtil::DataFormatToStr(format.m_dataFormat),
1231                                      wfxex.Format.nSamplesPerSec,
1232                                      wfxex.Format.nChannels);
1233   return true;
1234 }
1235
1236 void CAESinkWASAPI::AEChannelsFromSpeakerMask(DWORD speakers)
1237 {
1238   m_channelLayout.Reset();
1239
1240   for (int i = 0; i < WASAPI_SPEAKER_COUNT; i++)
1241   {
1242     if (speakers & WASAPIChannelOrder[i])
1243       m_channelLayout += AEChannelNames[i];
1244   }
1245 }
1246
1247 DWORD CAESinkWASAPI::SpeakerMaskFromAEChannels(const CAEChannelInfo &channels)
1248 {
1249   DWORD mask = 0;
1250
1251   for (unsigned int i = 0; i < channels.Count(); i++)
1252   {
1253     for (unsigned int j = 0; j < WASAPI_SPEAKER_COUNT; j++)
1254       if (channels[i] == AEChannelNames[j])
1255         mask |= WASAPIChannelOrder[j];
1256   }
1257   return mask;
1258 }
1259
1260 const char *CAESinkWASAPI::WASAPIErrToStr(HRESULT err)
1261 {
1262   switch(err)
1263   {
1264     ERRTOSTR(AUDCLNT_E_NOT_INITIALIZED);
1265     ERRTOSTR(AUDCLNT_E_ALREADY_INITIALIZED);
1266     ERRTOSTR(AUDCLNT_E_WRONG_ENDPOINT_TYPE);
1267     ERRTOSTR(AUDCLNT_E_DEVICE_INVALIDATED);
1268     ERRTOSTR(AUDCLNT_E_NOT_STOPPED);
1269     ERRTOSTR(AUDCLNT_E_BUFFER_TOO_LARGE);
1270     ERRTOSTR(AUDCLNT_E_OUT_OF_ORDER);
1271     ERRTOSTR(AUDCLNT_E_UNSUPPORTED_FORMAT);
1272     ERRTOSTR(AUDCLNT_E_INVALID_SIZE);
1273     ERRTOSTR(AUDCLNT_E_DEVICE_IN_USE);
1274     ERRTOSTR(AUDCLNT_E_BUFFER_OPERATION_PENDING);
1275     ERRTOSTR(AUDCLNT_E_THREAD_NOT_REGISTERED);
1276     ERRTOSTR(AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED);
1277     ERRTOSTR(AUDCLNT_E_ENDPOINT_CREATE_FAILED);
1278     ERRTOSTR(AUDCLNT_E_SERVICE_NOT_RUNNING);
1279     ERRTOSTR(AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED);
1280     ERRTOSTR(AUDCLNT_E_EXCLUSIVE_MODE_ONLY);
1281     ERRTOSTR(AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL);
1282     ERRTOSTR(AUDCLNT_E_EVENTHANDLE_NOT_SET);
1283     ERRTOSTR(AUDCLNT_E_INCORRECT_BUFFER_SIZE);
1284     ERRTOSTR(AUDCLNT_E_BUFFER_SIZE_ERROR);
1285     ERRTOSTR(AUDCLNT_E_CPUUSAGE_EXCEEDED);
1286     ERRTOSTR(AUDCLNT_E_BUFFER_ERROR);
1287     ERRTOSTR(AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED);
1288     ERRTOSTR(AUDCLNT_E_INVALID_DEVICE_PERIOD);
1289     ERRTOSTR(E_POINTER);
1290     ERRTOSTR(E_INVALIDARG);
1291     ERRTOSTR(E_OUTOFMEMORY);
1292     default: break;
1293   }
1294   return NULL;
1295 }
1296
1297 void CAESinkWASAPI::Drain()
1298 {
1299   if(!m_pAudioClient)
1300     return;
1301
1302   Sleep( (DWORD)(m_hnsRequestedDuration / 10000));
1303
1304   if (m_running)
1305   {
1306     try
1307     {
1308       m_pAudioClient->Stop();  //stop the audio output
1309       m_pAudioClient->Reset(); //flush buffer and reset audio clock stream position
1310     }
1311     catch (...)
1312     {
1313       CLog::Log(LOGDEBUG, __FUNCTION__, "Invalidated AudioClient - Releasing");
1314     }
1315   }
1316   m_running = false;
1317 }