strip added smb:// shares of their user/pass when adding, and instead store that...
[vuplus_xbmc] / xbmc / cores / AudioEngine / Sinks / AESinkWASAPI.cpp
1 /*
2  *      Copyright (C) 2010-2012 Team XBMC
3  *      http://www.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, write to
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18  *  http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21
22 #include "AESinkWASAPI.h"
23 #include <Audioclient.h>
24 #include <avrt.h>
25 #include <initguid.h>
26 #include <Mmreg.h>
27 #include <stdint.h>
28
29 #include "../Utils/AEUtil.h"
30 #include "settings/GUISettings.h"
31 #include "settings/AdvancedSettings.h"
32 #include "utils/StdString.h"
33 #include "utils/log.h"
34 #include "threads/SingleLock.h"
35 #include "utils/CharsetConverter.h"
36 #include "../Utils/AEDeviceInfo.h"
37 #include <Mmreg.h>
38 #include <mmdeviceapi.h>
39
40 #pragma comment(lib, "Avrt.lib")
41
42 const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
43 const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
44 const IID IID_IAudioClient = __uuidof(IAudioClient);
45 const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
46
47 static const unsigned int WASAPISampleRateCount = 10;
48 static const unsigned int WASAPISampleRates[] = {384000, 192000, 176400, 96000, 88200, 48000, 44100, 32000, 22050, 11025};
49
50 #define WASAPI_SPEAKER_COUNT 21
51 static const unsigned int WASAPIChannelOrder[] = {AE_CH_RAW,
52                                                   SPEAKER_FRONT_LEFT,           SPEAKER_FRONT_RIGHT,           SPEAKER_FRONT_CENTER,
53                                                   SPEAKER_LOW_FREQUENCY,        SPEAKER_BACK_LEFT,             SPEAKER_BACK_RIGHT,
54                                                   SPEAKER_FRONT_LEFT_OF_CENTER, SPEAKER_FRONT_RIGHT_OF_CENTER,
55                                                   SPEAKER_BACK_CENTER,          SPEAKER_SIDE_LEFT,             SPEAKER_SIDE_RIGHT,
56                                                   SPEAKER_TOP_FRONT_LEFT,       SPEAKER_TOP_FRONT_RIGHT,       SPEAKER_TOP_FRONT_CENTER,
57                                                   SPEAKER_TOP_CENTER,           SPEAKER_TOP_BACK_LEFT,         SPEAKER_TOP_BACK_RIGHT,
58                                                   SPEAKER_TOP_BACK_CENTER,      SPEAKER_RESERVED,              SPEAKER_RESERVED};
59
60 static const enum AEChannel AEChannelNames[]   = {AE_CH_RAW,
61                                                   AE_CH_FL,                     AE_CH_FR,                      AE_CH_FC,
62                                                   AE_CH_LFE,                    AE_CH_BL,                      AE_CH_BR,
63                                                   AE_CH_FLOC,                   AE_CH_FROC,
64                                                   AE_CH_BC,                     AE_CH_SL,                      AE_CH_SR,
65                                                   AE_CH_TFL,                    AE_CH_TFR,                     AE_CH_TFC ,
66                                                   AE_CH_TC  ,                   AE_CH_TBL,                     AE_CH_TBR,
67                                                   AE_CH_TBC,                    AE_CH_BLOC,                    AE_CH_BROC};
68
69 static enum AEChannel layoutsByChCount[9][9] = {
70     {AE_CH_NULL},
71     {AE_CH_FC, AE_CH_NULL},
72     {AE_CH_FL, AE_CH_FR, AE_CH_NULL},
73     {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_NULL},
74     {AE_CH_FL, AE_CH_FR, AE_CH_BL, AE_CH_BR, AE_CH_NULL},
75     {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_BL, AE_CH_BR, AE_CH_NULL},
76     {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_BL, AE_CH_BR, AE_CH_LFE, AE_CH_NULL},
77     {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_BL, AE_CH_BR, AE_CH_BC, AE_CH_LFE, AE_CH_NULL},
78     {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_BL, AE_CH_BR, AE_CH_SL, AE_CH_SR, AE_CH_LFE, AE_CH_NULL}};
79
80 struct sampleFormat
81 {
82   GUID subFormat;
83   unsigned int bitsPerSample;
84   unsigned int validBitsPerSample;
85   AEDataFormat subFormatType;
86 };
87
88 //Sample formats go from float -> 32 bit int -> 24 bit int (packed in 32) -> 16 bit int
89 static const sampleFormat testFormats[] = { {KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 32, 32, AE_FMT_FLOAT},
90                                             {KSDATAFORMAT_SUBTYPE_PCM, 32, 32, AE_FMT_S32NE},
91                                             {KSDATAFORMAT_SUBTYPE_PCM, 32, 24, AE_FMT_S24NE4},
92                                             {KSDATAFORMAT_SUBTYPE_PCM, 16, 16, AE_FMT_S16NE} };
93
94 struct winEndpointsToAEDeviceType
95 {
96   std::string winEndpointType;
97   AEDeviceType aeDeviceType;
98 };
99
100 static const winEndpointsToAEDeviceType winEndpoints[EndpointFormFactor_enum_count] =
101 {
102   {"Network Device - ",         AE_DEVTYPE_PCM},
103   {"Speakers - ",               AE_DEVTYPE_PCM},
104   {"LineLevel - ",              AE_DEVTYPE_PCM},
105   {"Headphones - ",             AE_DEVTYPE_PCM},
106   {"Microphone - ",             AE_DEVTYPE_PCM},
107   {"Headset - ",                AE_DEVTYPE_PCM},
108   {"Handset - ",                AE_DEVTYPE_PCM},
109   {"Digital Passthrough - ", AE_DEVTYPE_IEC958},
110   {"SPDIF - ",               AE_DEVTYPE_IEC958},
111   {"HDMI - ",                  AE_DEVTYPE_HDMI},
112   {"Unknown - ",                AE_DEVTYPE_PCM},
113 };
114
115 AEDeviceInfoList DeviceInfoList;
116
117 #define EXIT_ON_FAILURE(hr, reason, ...) if(FAILED(hr)) {CLog::Log(LOGERROR, reason " - %s", __VA_ARGS__, WASAPIErrToStr(hr)); goto failed;}
118
119 #define ERRTOSTR(err) case err: return #err
120
121 DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14);
122
123 CAESinkWASAPI::CAESinkWASAPI() :
124   m_pAudioClient(NULL),
125   m_pRenderClient(NULL),
126   m_needDataEvent(0),
127   m_pDevice(NULL),
128   m_initialized(false),
129   m_running(false),
130   m_encodedFormat(AE_FMT_INVALID),
131   m_encodedChannels(0),
132   m_encodedSampleRate(0),
133   m_uiBufferLen(0),
134   m_avgTimeWaiting(50),
135   m_isDirty(false)
136 {
137   m_channelLayout.Reset();
138 }
139
140 CAESinkWASAPI::~CAESinkWASAPI()
141 {
142
143 }
144
145 bool CAESinkWASAPI::Initialize(AEAudioFormat &format, std::string &device)
146 {
147   if (m_initialized)
148     return false;
149
150   CLog::Log(LOGDEBUG, __FUNCTION__": Initializing WASAPI Sink Rev. 1.0.5");
151
152   m_device = device;
153
154   /* Save requested format */
155   /* Clear returned format */
156   sinkReqFormat = format.m_dataFormat;
157   sinkRetFormat = AE_FMT_INVALID;
158
159   IMMDeviceEnumerator* pEnumerator = NULL;
160   IMMDeviceCollection* pEnumDevices = NULL;
161
162   HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator);
163   EXIT_ON_FAILURE(hr, __FUNCTION__": Could not allocate WASAPI device enumerator. CoCreateInstance error code: %li", hr)
164
165   //Get our device.
166   //First try to find the named device.
167   UINT uiCount = 0;
168
169   hr = pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pEnumDevices);
170   EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint enumeration failed.")
171
172   hr = pEnumDevices->GetCount(&uiCount);
173   EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint count failed.")
174
175   for (UINT i = 0; i < uiCount; i++)
176   {
177     IPropertyStore *pProperty = NULL;
178     PROPVARIANT varName;
179
180     hr = pEnumDevices->Item(i, &m_pDevice);
181     EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint failed.")
182
183     hr = m_pDevice->OpenPropertyStore(STGM_READ, &pProperty);
184     EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint properties failed.")
185
186     hr = pProperty->GetValue(PKEY_AudioEndpoint_GUID, &varName);
187     if (FAILED(hr))
188     {
189       CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint GUID failed.");
190       SAFE_RELEASE(pProperty);
191       goto failed;
192     }
193
194     std::wstring strRawDevName(varName.pwszVal);
195     std::string strDevName = std::string(strRawDevName.begin(), strRawDevName.end());
196     //g_charsetConverter.ucs2CharsetToStringCharset(strRawDevName, strDevName.c_str());
197
198     if (device == strDevName)
199       i = uiCount;
200     else
201       SAFE_RELEASE(m_pDevice);
202
203     PropVariantClear(&varName);
204     SAFE_RELEASE(pProperty);
205   }
206
207   SAFE_RELEASE(pEnumDevices);
208
209   if (!m_pDevice)
210   {
211     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());
212     hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &m_pDevice);
213     EXIT_ON_FAILURE(hr, __FUNCTION__": Could not retrieve the default WASAPI audio endpoint.")
214
215     IPropertyStore *pProperty = NULL;
216     PROPVARIANT varName;
217
218     hr = m_pDevice->OpenPropertyStore(STGM_READ, &pProperty);
219     EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint properties failed.")
220
221     hr = pProperty->GetValue(PKEY_AudioEndpoint_GUID, &varName);
222
223     std::wstring strRawDevName(varName.pwszVal);
224     std::string strDevName = std::string(strRawDevName.begin(), strRawDevName.end());
225
226     PropVariantClear(&varName);
227     SAFE_RELEASE(pProperty);
228   }
229
230   //We are done with the enumerator.
231   SAFE_RELEASE(pEnumerator);
232
233   hr = m_pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&m_pAudioClient);
234   EXIT_ON_FAILURE(hr, __FUNCTION__": Activating the WASAPI endpoint device failed.")
235
236   if (!InitializeExclusive(format))
237   {
238     CLog::Log(LOGINFO, __FUNCTION__": Could not Initialize Exclusive with that format");
239     goto failed;
240   }
241
242   /* get the buffer size and calculate the frames for AE */
243   m_pAudioClient->GetBufferSize(&m_uiBufferLen);
244
245   format.m_frames       = m_uiBufferLen;
246   format.m_frameSamples = format.m_frames * format.m_channelLayout.Count();
247   m_format              = format;
248   sinkRetFormat         = format.m_dataFormat;
249
250   CLog::Log(LOGDEBUG, __FUNCTION__": Buffer Size     = %d Bytes", m_uiBufferLen * format.m_frameSize);
251
252   hr = m_pAudioClient->GetService(IID_IAudioRenderClient, (void**)&m_pRenderClient);
253   EXIT_ON_FAILURE(hr, __FUNCTION__": Could not initialize the WASAPI render client interface.")
254
255   m_needDataEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
256   hr = m_pAudioClient->SetEventHandle(m_needDataEvent);
257   EXIT_ON_FAILURE(hr, __FUNCTION__": Could not set the WASAPI event handler.");
258
259   m_initialized = true;
260   m_isDirty     = false;
261
262   return true;
263
264 failed:
265   CLog::Log(LOGERROR, __FUNCTION__": WASAPI initialization failed.");
266   SAFE_RELEASE(pEnumDevices);
267   SAFE_RELEASE(pEnumerator);
268   SAFE_RELEASE(m_pRenderClient);
269   SAFE_RELEASE(m_pAudioClient);
270   SAFE_RELEASE(m_pDevice);
271   CloseHandle(m_needDataEvent);
272
273   return false;
274 }
275
276 void CAESinkWASAPI::Deinitialize()
277 {
278   if (!m_initialized)
279     return;
280
281
282   if (m_running)
283     m_pAudioClient->Stop();
284   m_running = false;
285
286
287   SAFE_RELEASE(m_pRenderClient);
288   SAFE_RELEASE(m_pAudioClient);
289   SAFE_RELEASE(m_pDevice);
290   CloseHandle(m_needDataEvent);
291
292   m_initialized = false;
293 }
294
295 bool CAESinkWASAPI::IsCompatible(const AEAudioFormat format, const std::string device)
296 {
297   if (!m_initialized || m_isDirty)
298     return false;
299
300   u_int notCompatible         = 0;
301   const u_int numTests        = 5;
302   std::string strDiffBecause ("");
303   static const char* compatibleParams[numTests] = {":Devices",
304                                                    ":Channels",
305                                                    ":Sample Rates",
306                                                    ":Data Formats",
307                                                    ":Passthrough Formats"};
308
309   notCompatible = (notCompatible  +!((AE_IS_RAW(format.m_dataFormat)  == AE_IS_RAW(m_encodedFormat))        ||
310                                      (!AE_IS_RAW(format.m_dataFormat) == !AE_IS_RAW(m_encodedFormat))))     << 1;
311   notCompatible = (notCompatible  +!((sinkReqFormat                   == format.m_dataFormat)               &&
312                                      (sinkRetFormat                   == m_format.m_dataFormat)))           << 1;
313   notCompatible = (notCompatible  + !(format.m_sampleRate             == m_format.m_sampleRate))            << 1;
314   notCompatible = (notCompatible  + !(format.m_channelLayout.Count()  == m_format.m_channelLayout.Count())) << 1;
315   notCompatible = (notCompatible  + !(m_device                        == device));
316
317   if (!notCompatible)
318   {
319     CLog::Log(LOGDEBUG, __FUNCTION__": Formats compatible - reusing existing sink");
320     return true;
321   }
322
323   for (int i = 0; i < numTests ; i++)
324   {
325     strDiffBecause += (notCompatible & 0x01) ? (std::string) compatibleParams[i] : "";
326     notCompatible    = notCompatible >> 1;
327   }
328
329   CLog::Log(LOGDEBUG, __FUNCTION__": Formats Incompatible due to different %s", strDiffBecause.c_str());
330   return false;
331 }
332
333 double CAESinkWASAPI::GetDelay()
334 {
335   HRESULT hr;
336   if (!m_initialized)
337     return 0.0;
338
339   hr = m_pAudioClient->GetBufferSize(&m_uiBufferLen);
340   if (FAILED(hr))
341   {
342     #ifdef _DEBUG
343     CLog::Log(LOGERROR, __FUNCTION__": GetBufferSize Failed : %s", WASAPIErrToStr(hr));
344     #endif
345     return 0.0;
346   }
347   return (double)m_uiBufferLen / (double)m_format.m_sampleRate;
348 }
349
350 double CAESinkWASAPI::GetCacheTime()
351 {
352   if (!m_initialized)
353     return 0.0;
354
355   REFERENCE_TIME hnsLatency;
356   HRESULT hr = m_pAudioClient->GetStreamLatency(&hnsLatency);
357
358   /** returns buffer duration in seconds */
359   return hnsLatency / 10.0;
360 }
361
362 double CAESinkWASAPI::GetCacheTotal()
363 {
364   if (!m_initialized)
365     return 0.0;
366
367   REFERENCE_TIME hnsLatency;
368   HRESULT hr = m_pAudioClient->GetStreamLatency(&hnsLatency);
369
370   /** returns buffer duration in seconds */
371   return hnsLatency / 10.0;
372 }
373
374 unsigned int CAESinkWASAPI::AddPackets(uint8_t *data, unsigned int frames)
375 {
376   if (!m_initialized)
377     return 0;
378
379   HRESULT hr;
380   BYTE *buf;
381   DWORD flags = 0;
382
383 #ifndef _DEBUG
384   LARGE_INTEGER timerStart;
385   LARGE_INTEGER timerStop;
386   LARGE_INTEGER timerFreq;
387 #endif
388
389   unsigned int NumFramesRequested = frames;
390
391   if (!m_running) //first time called, pre-fill buffer then start audio client
392   {
393     hr = m_pRenderClient->GetBuffer(NumFramesRequested, &buf);
394     if (FAILED(hr))
395     {
396       #ifdef _DEBUG
397       CLog::Log(LOGERROR, __FUNCTION__": GetBuffer failed due to %s", WASAPIErrToStr(hr));
398       #endif
399       m_isDirty = true; //flag new device or re-init needed
400       return INT_MAX;
401     }
402     memcpy(buf, data, NumFramesRequested * m_format.m_frameSize); //fill buffer
403     hr = m_pRenderClient->ReleaseBuffer(NumFramesRequested, flags); //pass back to audio driver
404     if (FAILED(hr))
405     {
406       #ifdef _DEBUG
407       CLog::Log(LOGDEBUG, __FUNCTION__": ReleaseBuffer failed due to %s.", WASAPIErrToStr(hr));
408       #endif
409       m_isDirty = true; //flag new device or re-init needed
410       return INT_MAX;
411     }
412     hr = m_pAudioClient->Start(); //start the audio driver running
413     if FAILED(hr)
414       CLog::Log(LOGERROR, __FUNCTION__": AudioClient Start Failed");
415     m_running = true; //signal that we're processing frames
416     return NumFramesRequested;
417   }
418
419 #ifndef _DEBUG
420   /* Get clock time for latency checks */
421   QueryPerformanceFrequency(&timerFreq);
422   QueryPerformanceCounter(&timerStart);
423 #endif
424
425   /* Wait for Audio Driver to tell us it's got a buffer available */
426   DWORD eventAudioCallback = WaitForSingleObject(m_needDataEvent, 1100);
427   if (eventAudioCallback != WAIT_OBJECT_0)
428   {
429     // Event handle timed out - stop audio device
430     m_pAudioClient->Stop();
431     CLog::Log(LOGERROR, __FUNCTION__": Endpoint Buffer timed out");
432     m_running = false;
433     m_pAudioClient->Stop(); //stop processing - we're done
434     m_isDirty = true; //flag new device or re-init needed
435     return INT_MAX;
436   }
437
438 #ifndef _DEBUG
439   QueryPerformanceCounter(&timerStop);
440   LONGLONG timerDiff = timerStop.QuadPart - timerStart.QuadPart;
441   double timerElapsed = (double) timerDiff * 1000.0 / (double) timerFreq.QuadPart;
442   m_avgTimeWaiting += (timerElapsed - m_avgTimeWaiting) * 0.5;
443
444   if (m_avgTimeWaiting < 3.0)
445   {
446     CLog::Log(LOGDEBUG, __FUNCTION__": Possible AQ Loss: Avg. Time Waiting for Audio Driver callback : %dmsec", (int)m_avgTimeWaiting);
447   }
448 #endif
449
450   hr = m_pRenderClient->GetBuffer(NumFramesRequested, &buf);
451   if (FAILED(hr))
452   {
453     #ifdef _DEBUG
454       CLog::Log(LOGERROR, __FUNCTION__": GetBuffer failed due to %s", WASAPIErrToStr(hr));
455     #endif
456     return 0;
457   }
458   memcpy(buf, data, NumFramesRequested * m_format.m_frameSize); //fill buffer
459   hr = m_pRenderClient->ReleaseBuffer(NumFramesRequested, flags); //pass back to audio driver
460   if (FAILED(hr))
461   {
462     #ifdef _DEBUG
463     CLog::Log(LOGDEBUG, __FUNCTION__": ReleaseBuffer failed due to %s.", WASAPIErrToStr(hr));
464     #endif
465     return 0;
466   }
467
468   return NumFramesRequested;
469 }
470
471 void CAESinkWASAPI::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList)
472 {
473   IMMDeviceEnumerator* pEnumerator = NULL;
474   IMMDeviceCollection* pEnumDevices = NULL;
475   CAEDeviceInfo        deviceInfo;
476   CAEChannelInfo       deviceChannels;
477
478   WAVEFORMATEXTENSIBLE wfxex = {0};
479   WAVEFORMATEX*        pwfxex = NULL;
480   HRESULT              hr;
481
482   hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator);
483   EXIT_ON_FAILURE(hr, __FUNCTION__": Could not allocate WASAPI device enumerator. CoCreateInstance error code: %li", hr)
484
485   UINT uiCount = 0;
486
487   hr = pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pEnumDevices);
488   EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint enumeration failed.")
489
490   hr = pEnumDevices->GetCount(&uiCount);
491   EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint count failed.")
492
493   for (UINT i = 0; i < uiCount; i++)
494   {
495     IMMDevice *pDevice = NULL;
496     IPropertyStore *pProperty = NULL;
497     PROPVARIANT varName;
498     PropVariantInit(&varName);
499
500     deviceInfo.m_channels.Reset();
501     deviceInfo.m_dataFormats.clear();
502     deviceInfo.m_sampleRates.clear();
503
504     hr = pEnumDevices->Item(i, &pDevice);
505     if (FAILED(hr))
506     {
507       CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint failed.");
508       goto failed;
509     }
510
511     hr = pDevice->OpenPropertyStore(STGM_READ, &pProperty);
512     if (FAILED(hr))
513     {
514       CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint properties failed.");
515       SAFE_RELEASE(pDevice);
516       goto failed;
517     }
518
519     hr = pProperty->GetValue(PKEY_Device_FriendlyName, &varName);
520     if (FAILED(hr))
521     {
522       CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint device name failed.");
523       SAFE_RELEASE(pDevice);
524       SAFE_RELEASE(pProperty);
525       goto failed;
526     }
527
528     std::wstring strRawFriendlyName(varName.pwszVal);
529     std::string strFriendlyName = std::string(strRawFriendlyName.begin(), strRawFriendlyName.end());
530
531     PropVariantClear(&varName);
532
533     hr = pProperty->GetValue(PKEY_AudioEndpoint_GUID, &varName);
534     if(FAILED(hr))
535     {
536       CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint GUID failed.");
537       SAFE_RELEASE(pDevice);
538       SAFE_RELEASE(pProperty);
539       goto failed;
540     }
541
542     std::wstring strRawDevName(varName.pwszVal);
543     std::string strDevName = std::string(strRawDevName.begin(), strRawDevName.end());
544
545     PropVariantClear(&varName);
546
547     hr = pProperty->GetValue(PKEY_AudioEndpoint_FormFactor, &varName);
548     if (FAILED(hr))
549     {
550       CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint form factor failed.");
551       SAFE_RELEASE(pDevice);
552       SAFE_RELEASE(pProperty);
553       goto failed;
554     }
555     std::string strWinDevType = winEndpoints[(EndpointFormFactor)varName.uiVal].winEndpointType;
556     AEDeviceType aeDeviceType = winEndpoints[(EndpointFormFactor)varName.uiVal].aeDeviceType;
557
558     PropVariantClear(&varName);
559
560     hr = pProperty->GetValue(PKEY_AudioEndpoint_PhysicalSpeakers, &varName);
561     if (FAILED(hr))
562     {
563       CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint speaker layout failed.");
564       SAFE_RELEASE(pDevice);
565       SAFE_RELEASE(pProperty);
566       goto failed;
567     }
568     unsigned int uiChannelMask = std::max(varName.uintVal, (unsigned int) AE_CH_FL | AE_CH_FR);
569
570     deviceChannels.Reset();
571
572     for (unsigned int c = 0; c < WASAPI_SPEAKER_COUNT; c++)
573     {
574       if (uiChannelMask & WASAPIChannelOrder[c])
575         deviceChannels += AEChannelNames[c];
576     }
577
578     PropVariantClear(&varName);
579
580     IAudioClient *pClient;
581     hr = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pClient);
582     if (SUCCEEDED(hr))
583     {
584       /* Test format DTS-HD */
585       wfxex.Format.cbSize               = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
586       wfxex.Format.nSamplesPerSec       = 192000;
587       wfxex.dwChannelMask               = KSAUDIO_SPEAKER_7POINT1_SURROUND;
588       wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
589       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD;
590       wfxex.Format.wBitsPerSample       = 16;
591       wfxex.Samples.wValidBitsPerSample = 16;
592       wfxex.Format.nChannels            = 8;
593       wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
594       wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
595       hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
596       if (SUCCEEDED(hr))
597         deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_DTSHD));
598
599       /* Test format Dolby TrueHD */
600       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP;
601       hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
602       if (SUCCEEDED(hr))
603         deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_TRUEHD));
604
605       /* Test format Dolby EAC3 */
606       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS;
607       wfxex.Format.nChannels            = 2;
608       wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
609       wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
610       hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
611       if (SUCCEEDED(hr))
612         deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_EAC3));
613
614       /* Test format DTS */
615       wfxex.Format.nSamplesPerSec       = 48000;
616       wfxex.dwChannelMask               = KSAUDIO_SPEAKER_5POINT1;
617       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_DTS;
618       wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
619       wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
620       hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
621       if (SUCCEEDED(hr))
622         deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_DTS));
623
624       /* Test format Dolby AC3 */
625       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL;
626       hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
627       if (SUCCEEDED(hr))
628         deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_AC3));
629
630       /* Test format AAC */
631       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_AAC;
632       hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
633       if (SUCCEEDED(hr))
634         deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_AAC));
635
636       /* Test format for PCM format iteration */
637       wfxex.Format.cbSize               = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
638       wfxex.dwChannelMask               = AE_CH_FL | AE_CH_FR;
639       wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
640       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
641
642       for (int p = AE_FMT_FLOAT; p > AE_FMT_INVALID; p--)
643       {
644         if (p < AE_FMT_FLOAT)
645           wfxex.SubFormat               = KSDATAFORMAT_SUBTYPE_PCM;
646         wfxex.Format.wBitsPerSample     = CAEUtil::DataFormatToBits((AEDataFormat) p);
647         wfxex.Format.nBlockAlign        = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
648         wfxex.Format.nAvgBytesPerSec    = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
649         if (p <= AE_FMT_S24NE4 && p >= AE_FMT_S24BE4)
650         {
651           wfxex.Samples.wValidBitsPerSample = 24;
652         }
653         else
654         {
655           wfxex.Samples.wValidBitsPerSample = wfxex.Format.wBitsPerSample;
656         }
657
658         hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
659         if (SUCCEEDED(hr))
660           deviceInfo.m_dataFormats.push_back((AEDataFormat) p);
661       }
662
663       /* Test format for sample rate iteration */
664       wfxex.Format.cbSize               = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
665       wfxex.dwChannelMask               = AE_CH_FL | AE_CH_FR;
666       wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
667       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_PCM;
668       wfxex.Format.wBitsPerSample       = 16;
669       wfxex.Samples.wValidBitsPerSample = 16;
670       wfxex.Format.nChannels            = 2;
671       wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
672       wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
673
674       for (int j = 0; j < WASAPISampleRateCount; j++)
675       {
676         wfxex.Format.nSamplesPerSec     = WASAPISampleRates[j];
677         wfxex.Format.nAvgBytesPerSec    = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
678         hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
679         if (SUCCEEDED(hr))
680           deviceInfo.m_sampleRates.push_back(WASAPISampleRates[j]);
681       }
682
683       /* Test format for channels iteration */
684       wfxex.Format.cbSize               = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
685       wfxex.dwChannelMask               = AE_CH_FL | AE_CH_FR;
686       wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
687       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_PCM;
688       wfxex.Format.nSamplesPerSec       = 48000;
689       wfxex.Format.wBitsPerSample       = 16;
690       wfxex.Samples.wValidBitsPerSample = 16;
691       wfxex.Format.nChannels            = 2;
692       wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
693       wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
694
695       //bool mpcmFlagged                  = false;
696
697       for (int k = AE_CH_LAYOUT_MAX; k > 0; k--)
698       {
699         DWORD mask = 0;
700         for (int c = 0; c < WASAPI_SPEAKER_COUNT; c++)
701         {
702           if (uiChannelMask & WASAPIChannelOrder[c])
703             mask |= WASAPIChannelOrder[c];
704         }
705
706         wfxex.dwChannelMask             = mask;
707         wfxex.Format.nChannels          = k;
708         wfxex.Format.nBlockAlign        = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
709         wfxex.Format.nAvgBytesPerSec    = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
710         hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
711         if (SUCCEEDED(hr))
712         {
713           deviceChannels                = layoutsByChCount[k];
714           if (k > AE_CH_LAYOUT_2_1) // && !mpcmFlagged)
715           {
716             deviceInfo.m_dataFormats.push_back(AE_FMT_LPCM);
717             //mpcmFlagged = true;
718           }
719           break;
720         }
721       }
722       pClient->Release();
723     }
724     else
725     {
726       CLog::Log(LOGDEBUG, __FUNCTION__": Failed to activate device for passthrough capability testing.");
727     }
728
729     SAFE_RELEASE(pDevice);
730     SAFE_RELEASE(pProperty);
731
732     deviceInfo.m_deviceName       = strDevName;
733     deviceInfo.m_displayName      = strWinDevType.append(strFriendlyName);
734     deviceInfo.m_displayNameExtra = std::string("WASAPI: ").append(strFriendlyName);
735     deviceInfo.m_deviceType       = aeDeviceType;
736     deviceInfo.m_channels         = deviceChannels;
737
738     /* Now logged by AESinkFactory on startup */
739     //CLog::Log(LOGDEBUG,"Audio Device %d:    %s", i, ((std::string)deviceInfo).c_str());
740
741     deviceInfoList.push_back(deviceInfo);
742   }
743   return;
744
745 failed:
746
747   if (FAILED(hr))
748     CLog::Log(LOGERROR, __FUNCTION__": Failed to enumerate WASAPI endpoint devices (%s).", WASAPIErrToStr(hr));
749
750   SAFE_RELEASE(pEnumDevices);
751   SAFE_RELEASE(pEnumerator);
752 }
753
754 //Private utility functions////////////////////////////////////////////////////
755
756 void CAESinkWASAPI::BuildWaveFormatExtensible(AEAudioFormat &format, WAVEFORMATEXTENSIBLE &wfxex)
757 {
758   wfxex.Format.wFormatTag        = WAVE_FORMAT_EXTENSIBLE;
759   wfxex.Format.cbSize            = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
760
761
762   if (!AE_IS_RAW(format.m_dataFormat)) // PCM data
763   {
764     wfxex.dwChannelMask          = SpeakerMaskFromAEChannels(format.m_channelLayout);
765     wfxex.Format.nChannels       = (WORD)format.m_channelLayout.Count();
766     wfxex.Format.nSamplesPerSec  = format.m_sampleRate;
767     wfxex.Format.wBitsPerSample  = format.m_dataFormat <= AE_FMT_S16NE ? 16 : 32;
768     wfxex.SubFormat              = format.m_dataFormat <= AE_FMT_FLOAT ? KSDATAFORMAT_SUBTYPE_PCM : KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
769   }
770   else //Raw bitstream
771   {
772     wfxex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
773     if (format.m_dataFormat == AE_FMT_AC3 || format.m_dataFormat == AE_FMT_DTS)
774     {
775       wfxex.dwChannelMask          = bool (format.m_channelLayout.Count() == 2) ? KSAUDIO_SPEAKER_STEREO : KSAUDIO_SPEAKER_5POINT1;
776
777       if (format.m_dataFormat == AE_FMT_AC3)
778       {
779         wfxex.SubFormat            = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL;
780         //wfxex.Format.wFormatTag    = WAVE_FORMAT_DOLBY_AC3_SPDIF;
781       }
782       else
783       {
784         wfxex.SubFormat            = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL; //KSDATAFORMAT_SUBTYPE_IEC61937_DTS;
785         //wfxex.Format.wFormatTag    = WAVE_FORMAT_DTS;
786       }
787
788       wfxex.Format.wBitsPerSample       = 16;
789       wfxex.Samples.wValidBitsPerSample = 16;
790       wfxex.Format.nChannels            = (WORD)format.m_channelLayout.Count();
791       wfxex.Format.nSamplesPerSec       = format.m_sampleRate;
792     }
793     else if (format.m_dataFormat == AE_FMT_EAC3 || format.m_dataFormat == AE_FMT_TRUEHD || format.m_dataFormat == AE_FMT_DTSHD)
794     {
795       //IEC 61937 transmissions.
796       //Currently these formats only run over HDMI.
797       wfxex.Format.nSamplesPerSec       = 192000L; // Link runs at 192 KHz.
798       wfxex.Format.wBitsPerSample       = 16; // Always at 16 bits over IEC 60958.
799       wfxex.Samples.wValidBitsPerSample = 16;
800       wfxex.dwChannelMask               = KSAUDIO_SPEAKER_7POINT1_SURROUND;
801
802       switch (format.m_dataFormat)
803       {
804         case AE_FMT_EAC3:
805           wfxex.SubFormat             = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS;
806           wfxex.Format.nChannels      = 2; // One IEC 60958 Line.
807           wfxex.dwChannelMask         = KSAUDIO_SPEAKER_5POINT1;
808           break;
809         case AE_FMT_TRUEHD:
810           wfxex.SubFormat             = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP;
811           wfxex.Format.nChannels      = 8; // Four IEC 60958 Lines.
812           wfxex.dwChannelMask         = KSAUDIO_SPEAKER_7POINT1_SURROUND;
813           break;
814         case AE_FMT_DTSHD:
815           wfxex.SubFormat             = KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD;
816           wfxex.Format.nChannels      = 8; // Four IEC 60958 Lines.
817           wfxex.dwChannelMask         = KSAUDIO_SPEAKER_7POINT1_SURROUND;
818           break;
819       }
820
821       if (format.m_channelLayout.Count() == 8)
822         wfxex.dwChannelMask         = KSAUDIO_SPEAKER_7POINT1_SURROUND;
823       else
824         wfxex.dwChannelMask         = KSAUDIO_SPEAKER_5POINT1;
825     }
826   }
827
828   if (wfxex.Format.wBitsPerSample == 32 && wfxex.SubFormat != KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
829     wfxex.Samples.wValidBitsPerSample = 24;
830   else
831     wfxex.Samples.wValidBitsPerSample = wfxex.Format.wBitsPerSample;
832
833   wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
834   wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
835 }
836
837 void CAESinkWASAPI::BuildWaveFormatExtensibleIEC61397(AEAudioFormat &format, WAVEFORMATEXTENSIBLE_IEC61937 &wfxex)
838 {
839   //Fill the common structure.
840   BuildWaveFormatExtensible(format, wfxex.FormatExt);
841   /*
842   wfxex.FormatExt.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE_IEC61937)-sizeof(WAVEFORMATEX);
843   wfxex.dwEncodedChannelCount   = format.m_channelLayout.Count();
844   wfxex.dwEncodedSamplesPerSec  = bool(format.m_dataFormat == AE_FMT_TRUEHD ||
845                                        format.m_dataFormat == AE_FMT_DTSHD  ||
846                                        format.m_dataFormat == AE_FMT_EAC3) ? 96000L : 48000L;
847   wfxex.dwAverageBytesPerSec    = 0; //Ignored */
848 }
849
850 bool CAESinkWASAPI::InitializeExclusive(AEAudioFormat &format)
851 {
852   WAVEFORMATEXTENSIBLE_IEC61937 wfxex_iec61937;
853   WAVEFORMATEXTENSIBLE &wfxex = wfxex_iec61937.FormatExt;
854
855   if (format.m_dataFormat <= AE_FMT_FLOAT) //DDDamian was AE_FMT_DTS
856     BuildWaveFormatExtensible(format, wfxex);
857   else
858     BuildWaveFormatExtensibleIEC61397(format, wfxex_iec61937);
859
860   //test for incomplete or startup format and provide default
861   if (format.m_sampleRate == 0 ||
862       format.m_channelLayout == NULL ||
863       format.m_dataFormat <= AE_FMT_INVALID ||
864       format.m_dataFormat >= AE_FMT_MAX ||
865       format.m_channelLayout.Count() == 0)
866   {
867     wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
868     wfxex.Format.nChannels            = 2;
869     wfxex.Format.nSamplesPerSec       = 44100L;
870     wfxex.Format.wBitsPerSample       = 16;
871     wfxex.Format.nBlockAlign          = 4;
872     wfxex.Samples.wValidBitsPerSample = 16;
873     wfxex.Format.cbSize               = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
874     wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nBlockAlign * wfxex.Format.nSamplesPerSec;
875     wfxex.dwChannelMask               = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
876     wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_PCM;
877   }
878
879   CLog::Log(LOGDEBUG, __FUNCTION__": Checking IsFormatSupported with the following parameters:");
880   CLog::Log(LOGDEBUG, "  Sample Rate     : %d", wfxex.Format.nSamplesPerSec);
881   CLog::Log(LOGDEBUG, "  Sample Format   : %s", CAEUtil::DataFormatToStr(format.m_dataFormat));
882   CLog::Log(LOGDEBUG, "  Bits Per Sample : %d", wfxex.Format.wBitsPerSample);
883   CLog::Log(LOGDEBUG, "  Valid Bits/Samp : %d", wfxex.Samples.wValidBitsPerSample);
884   CLog::Log(LOGDEBUG, "  Channel Count   : %d", wfxex.Format.nChannels);
885   CLog::Log(LOGDEBUG, "  Block Align     : %d", wfxex.Format.nBlockAlign);
886   CLog::Log(LOGDEBUG, "  Avg. Bytes Sec  : %d", wfxex.Format.nAvgBytesPerSec);
887   CLog::Log(LOGDEBUG, "  Samples/Block   : %d", wfxex.Samples.wSamplesPerBlock);
888   CLog::Log(LOGDEBUG, "  Format cBSize   : %d", wfxex.Format.cbSize);
889   CLog::Log(LOGDEBUG, "  Channel Layout  : %s", ((std::string)format.m_channelLayout).c_str());
890   CLog::Log(LOGDEBUG, "  Channel Mask    : %d", wfxex.dwChannelMask);
891
892   if (wfxex.SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
893     CLog::Log(LOGDEBUG, "  SubFormat       : KSDATAFORMAT_SUBTYPE_IEEE_FLOAT");
894   else if (wfxex.SubFormat == KSDATAFORMAT_SUBTYPE_PCM)
895     CLog::Log(LOGDEBUG, "  SubFormat       : KSDATAFORMAT_SUBTYPE_PCM");
896   else if (wfxex.SubFormat == KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL)
897     CLog::Log(LOGDEBUG, "  SubFormat       : KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL");
898   else if (wfxex.SubFormat == KSDATAFORMAT_SUBTYPE_IEC61937_DTS)
899     CLog::Log(LOGDEBUG, "  SubFormat       : KSDATAFORMAT_SUBTYPE_IEC61937_DTS");
900   else if (wfxex.SubFormat == KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS)
901     CLog::Log(LOGDEBUG, "  SubFormat       : KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS");
902   else if (wfxex.SubFormat == KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP)
903     CLog::Log(LOGDEBUG, "  SubFormat       : KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP");
904   else if (wfxex.SubFormat == KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD)
905     CLog::Log(LOGDEBUG, "  SubFormat       : KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD");
906   else
907     CLog::Log(LOGDEBUG, "  SubFormat       : NO SUBFORMAT SPECIFIED");
908
909   HRESULT hr = m_pAudioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
910
911   if (SUCCEEDED(hr))
912   {
913     CLog::Log(LOGDEBUG, __FUNCTION__": Format is Supported - will attempt to Initialize");
914     goto initialize;
915   }
916   else if (hr != AUDCLNT_E_UNSUPPORTED_FORMAT) //It failed for a reason unrelated to an unsupported format.
917   {
918     CLog::Log(LOGERROR, __FUNCTION__": IsFormatSupported failed (%s)", WASAPIErrToStr(hr));
919     return false;
920   }
921   else if (AE_IS_RAW(format.m_dataFormat)) //No sense in trying other formats for passthrough.
922     return false;
923
924   CLog::Log(LOGERROR, __FUNCTION__": IsFormatSupported failed (%s) - trying to find a compatible format", WASAPIErrToStr(hr));
925
926   int closestMatch;
927
928   //The requested format is not supported by the device.  Find something that works.
929   //Try other formats
930   for (int j = 0; j < sizeof(testFormats)/sizeof(sampleFormat); j++)
931   {
932     closestMatch = -1;
933
934     wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
935     wfxex.SubFormat                   = testFormats[j].subFormat;
936     wfxex.Format.wBitsPerSample       = testFormats[j].bitsPerSample;
937     wfxex.Samples.wValidBitsPerSample = testFormats[j].validBitsPerSample;
938     wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
939
940     for (int i = 0 ; i < WASAPISampleRateCount; i++)
941     {
942       wfxex.Format.nSamplesPerSec    = WASAPISampleRates[i];
943       wfxex.Format.nAvgBytesPerSec   = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
944
945       /* Uncomment to trace format match iteration loop via log */
946       CLog::Log(LOGDEBUG, "WASAPI: Trying Sample Format    : %s", CAEUtil::DataFormatToStr(testFormats[j].subFormatType));
947       CLog::Log(LOGDEBUG, "WASAPI: Trying Sample Rate      : %d", wfxex.Format.nSamplesPerSec);
948       CLog::Log(LOGDEBUG, "WASAPI: Trying Bits/Sample      : %d", wfxex.Format.wBitsPerSample);
949       CLog::Log(LOGDEBUG, "WASAPI: Trying Valid Bits/Sample: %d", wfxex.Samples.wValidBitsPerSample);
950
951       hr = m_pAudioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
952
953       if (SUCCEEDED(hr))
954       {
955         //If the current sample rate matches the source then stop looking and use it.
956         if ((WASAPISampleRates[i] == format.m_sampleRate) && (testFormats[j].subFormatType <= format.m_dataFormat))
957           goto initialize;
958         //If this rate is closer to the source then the previous one, save it.
959         else if (closestMatch < 0 || abs((int)WASAPISampleRates[i] - (int)format.m_sampleRate) < abs((int)WASAPISampleRates[closestMatch] - (int)format.m_sampleRate))
960           closestMatch = i;
961       }
962       else if (hr != AUDCLNT_E_UNSUPPORTED_FORMAT)
963           CLog::Log(LOGERROR, __FUNCTION__": IsFormatSupported failed (%s)", WASAPIErrToStr(hr));
964     }
965
966     if (closestMatch >= 0)
967     {
968       wfxex.Format.nSamplesPerSec    = WASAPISampleRates[closestMatch];
969       wfxex.Format.nAvgBytesPerSec   = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
970       goto initialize;
971     }
972   }
973
974   CLog::Log(LOGERROR, __FUNCTION__": Unable to locate a supported output format for the device.  Check the speaker settings in the control panel.");
975
976   //We couldn't find anything supported.  This should never happen unless the user set the wrong
977   //speaker setting in the control panel.
978   return false;
979
980 initialize:
981
982   AEChannelsFromSpeakerMask(wfxex.dwChannelMask);
983
984   //When the stream is raw, the values in the format structure are set to the link
985   //parameters, so store the encoded stream values here for the IsCompatible function.
986   m_encodedFormat     = format.m_dataFormat;
987   m_encodedChannels   = wfxex.Format.nChannels;
988   m_encodedSampleRate = format.m_encodedRate;// bool(format.m_dataFormat == AE_FMT_TRUEHD || format.m_dataFormat == AE_FMT_DTSHD) ? 96000L : 48000L;
989   wfxex_iec61937.dwEncodedChannelCount = wfxex.Format.nChannels;
990   wfxex_iec61937.dwEncodedSamplesPerSec = m_encodedSampleRate;
991
992   if (!AE_IS_RAW(format.m_dataFormat))
993   {
994     if (wfxex.Format.wBitsPerSample == 32)
995     {
996       if (wfxex.SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
997         format.m_dataFormat = AE_FMT_FLOAT;
998       else if (wfxex.Samples.wValidBitsPerSample == 32)
999         format.m_dataFormat = AE_FMT_S32NE;
1000       else
1001         format.m_dataFormat = AE_FMT_S24NE4;
1002     }
1003     else
1004     {
1005       format.m_dataFormat = AE_FMT_S16NE;
1006     }
1007   }
1008
1009   format.m_sampleRate    = wfxex.Format.nSamplesPerSec; //PCM: Sample rate.  RAW: Link speed
1010
1011   format.m_frameSize     = (wfxex.Format.wBitsPerSample >> 3) * wfxex.Format.nChannels;
1012
1013   REFERENCE_TIME audioSinkBufferDurationMsec, hnsLatency;
1014
1015   /* Get m_audioSinkBufferSizeMsec from advancedsettings.xml */
1016   audioSinkBufferDurationMsec = (REFERENCE_TIME)g_advancedSettings.m_audioSinkBufferDurationMsec * 10000;
1017
1018   //use user's advancedsetting value for buffer size as long as it's over minimum set above
1019   audioSinkBufferDurationMsec = (REFERENCE_TIME)std::max(audioSinkBufferDurationMsec, (REFERENCE_TIME)500000);
1020   audioSinkBufferDurationMsec = (REFERENCE_TIME)((audioSinkBufferDurationMsec / format.m_frameSize) * format.m_frameSize); //even number of frames
1021
1022   CLog::Log(LOGDEBUG, __FUNCTION__": Initializing WASAPI exclusive mode with the following parameters:");
1023   CLog::Log(LOGDEBUG, "  Sample Rate     : %d", wfxex.Format.nSamplesPerSec);
1024   CLog::Log(LOGDEBUG, "  Sample Format   : %s", CAEUtil::DataFormatToStr(format.m_dataFormat));
1025   CLog::Log(LOGDEBUG, "  Bits Per Sample : %d", wfxex.Format.wBitsPerSample);
1026   CLog::Log(LOGDEBUG, "  Valid Bits/Samp : %d", wfxex.Samples.wValidBitsPerSample);
1027   CLog::Log(LOGDEBUG, "  Channel Count   : %d", wfxex.Format.nChannels);
1028   CLog::Log(LOGDEBUG, "  Block Align     : %d", wfxex.Format.nBlockAlign);
1029   CLog::Log(LOGDEBUG, "  Avg. Bytes Sec  : %d", wfxex.Format.nAvgBytesPerSec);
1030   CLog::Log(LOGDEBUG, "  Samples/Block   : %d", wfxex.Samples.wSamplesPerBlock);
1031   CLog::Log(LOGDEBUG, "  Format cBSize   : %d", wfxex.Format.cbSize);
1032   CLog::Log(LOGDEBUG, "  Channel Layout  : %s", ((std::string)format.m_channelLayout).c_str());
1033   CLog::Log(LOGDEBUG, "  Enc. Channels   : %d", wfxex_iec61937.dwEncodedChannelCount);
1034   CLog::Log(LOGDEBUG, "  Enc. Samples/Sec: %d", wfxex_iec61937.dwEncodedSamplesPerSec);
1035   CLog::Log(LOGDEBUG, "  Channel Mask    : %d", wfxex.dwChannelMask);
1036   CLog::Log(LOGDEBUG, "  Periodicty      : %d", audioSinkBufferDurationMsec);
1037
1038   if (wfxex.SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
1039     CLog::Log(LOGDEBUG, "  SubFormat       : KSDATAFORMAT_SUBTYPE_IEEE_FLOAT");
1040   else if (wfxex.SubFormat == KSDATAFORMAT_SUBTYPE_PCM)
1041     CLog::Log(LOGDEBUG, "  SubFormat       : KSDATAFORMAT_SUBTYPE_PCM");
1042   else if (wfxex.SubFormat == KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL)
1043     CLog::Log(LOGDEBUG, "  SubFormat       : KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL");
1044   else if (wfxex.SubFormat == KSDATAFORMAT_SUBTYPE_IEC61937_DTS)
1045     CLog::Log(LOGDEBUG, "  SubFormat       : KSDATAFORMAT_SUBTYPE_IEC61937_DTS");
1046   else if (wfxex.SubFormat == KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS)
1047     CLog::Log(LOGDEBUG, "  SubFormat       : KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS");
1048   else if (wfxex.SubFormat == KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP)
1049     CLog::Log(LOGDEBUG, "  SubFormat       : KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP");
1050   else if (wfxex.SubFormat == KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD)
1051     CLog::Log(LOGDEBUG, "  SubFormat       : KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD");
1052   else
1053     CLog::Log(LOGDEBUG, "  SubFormat       : NO SUBFORMAT SPECIFIED");
1054
1055   if (AE_IS_RAW(format.m_dataFormat))
1056     format.m_dataFormat = AE_FMT_S16NE;
1057
1058   hr = m_pAudioClient->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE, AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST,
1059                                     audioSinkBufferDurationMsec, audioSinkBufferDurationMsec, &wfxex.Format, NULL);
1060
1061   if (hr == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED)
1062   {
1063     CLog::Log(LOGDEBUG, __FUNCTION__": Re-aligning WASAPI sink buffer due to %s.", WASAPIErrToStr(hr));
1064     // Get the next aligned frame.
1065     hr = m_pAudioClient->GetBufferSize(&m_uiBufferLen);
1066     if (FAILED(hr))
1067     {
1068       CLog::Log(LOGERROR, __FUNCTION__": GetBufferSize Failed : %s", WASAPIErrToStr(hr));
1069       return false;
1070     }
1071
1072     audioSinkBufferDurationMsec = (REFERENCE_TIME) ((10000.0 * 1000 / wfxex.Format.nSamplesPerSec * m_uiBufferLen) + 0.5);
1073     CLog::Log(LOGDEBUG, __FUNCTION__": Number of Frames in Buffer   : %d", m_uiBufferLen);
1074     CLog::Log(LOGDEBUG, __FUNCTION__": Requested Duration of Buffer : %d", audioSinkBufferDurationMsec);
1075
1076     // Release the previous allocations.
1077     SAFE_RELEASE(m_pAudioClient);
1078
1079     // Create a new audio client.
1080     hr = m_pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&m_pAudioClient);
1081     if (FAILED(hr))
1082     {
1083       CLog::Log(LOGERROR, __FUNCTION__": Device Activation Failed : %s", WASAPIErrToStr(hr));
1084       return false;
1085     }
1086
1087     // Open the stream and associate it with an audio session.
1088     hr = m_pAudioClient->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE, AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST,
1089                                       audioSinkBufferDurationMsec, audioSinkBufferDurationMsec, &wfxex.Format, NULL);
1090   }
1091   if (FAILED(hr))
1092   {
1093     CLog::Log(LOGERROR, __FUNCTION__": Unable to initialize WASAPI in exclusive mode %d - (%s).", HRESULT(hr), WASAPIErrToStr(hr));
1094     return false;
1095   }
1096   hr = m_pAudioClient->GetStreamLatency(&hnsLatency);
1097   CLog::Log(LOGDEBUG,  __FUNCTION__": Requested Duration of Buffer : %fmsec", hnsLatency / 10000.0);
1098   CLog::Log(LOGNOTICE, __FUNCTION__": WASAPI Exclusive Mode Sink Initialized Successfully!!!");
1099   return true;
1100 }
1101
1102 void CAESinkWASAPI::AEChannelsFromSpeakerMask(DWORD speakers)
1103 {
1104   m_channelLayout.Reset();
1105
1106   for (int i = 0; i < WASAPI_SPEAKER_COUNT; i++)
1107   {
1108     if (speakers & WASAPIChannelOrder[i])
1109       m_channelLayout += AEChannelNames[i];
1110   }
1111 }
1112
1113 DWORD CAESinkWASAPI::SpeakerMaskFromAEChannels(const CAEChannelInfo &channels)
1114 {
1115   DWORD mask = 0;
1116
1117   for (unsigned int i = 0; i < channels.Count(); i++)
1118   {
1119     for (unsigned int j = 0; j < WASAPI_SPEAKER_COUNT; j++)
1120       if (channels[i] == AEChannelNames[j])
1121         mask |= WASAPIChannelOrder[j];
1122   }
1123   return mask;
1124 }
1125
1126 const char *CAESinkWASAPI::WASAPIErrToStr(HRESULT err)
1127 {
1128   switch(err)
1129   {
1130     ERRTOSTR(AUDCLNT_E_NOT_INITIALIZED);
1131     ERRTOSTR(AUDCLNT_E_ALREADY_INITIALIZED);
1132     ERRTOSTR(AUDCLNT_E_WRONG_ENDPOINT_TYPE);
1133     ERRTOSTR(AUDCLNT_E_DEVICE_INVALIDATED);
1134     ERRTOSTR(AUDCLNT_E_NOT_STOPPED);
1135     ERRTOSTR(AUDCLNT_E_BUFFER_TOO_LARGE);
1136     ERRTOSTR(AUDCLNT_E_OUT_OF_ORDER);
1137     ERRTOSTR(AUDCLNT_E_UNSUPPORTED_FORMAT);
1138     ERRTOSTR(AUDCLNT_E_INVALID_SIZE);
1139     ERRTOSTR(AUDCLNT_E_DEVICE_IN_USE);
1140     ERRTOSTR(AUDCLNT_E_BUFFER_OPERATION_PENDING);
1141     ERRTOSTR(AUDCLNT_E_THREAD_NOT_REGISTERED);
1142     ERRTOSTR(AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED);
1143     ERRTOSTR(AUDCLNT_E_ENDPOINT_CREATE_FAILED);
1144     ERRTOSTR(AUDCLNT_E_SERVICE_NOT_RUNNING);
1145     ERRTOSTR(AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED);
1146     ERRTOSTR(AUDCLNT_E_EXCLUSIVE_MODE_ONLY);
1147     ERRTOSTR(AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL);
1148     ERRTOSTR(AUDCLNT_E_EVENTHANDLE_NOT_SET);
1149     ERRTOSTR(AUDCLNT_E_INCORRECT_BUFFER_SIZE);
1150     ERRTOSTR(AUDCLNT_E_BUFFER_SIZE_ERROR);
1151     ERRTOSTR(AUDCLNT_E_CPUUSAGE_EXCEEDED);
1152     ERRTOSTR(AUDCLNT_E_BUFFER_ERROR);
1153     ERRTOSTR(AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED);
1154     ERRTOSTR(AUDCLNT_E_INVALID_DEVICE_PERIOD);
1155     ERRTOSTR(E_POINTER);
1156     ERRTOSTR(E_INVALIDARG);
1157     ERRTOSTR(E_OUTOFMEMORY);
1158     default: break;
1159   }
1160   return NULL;
1161 }