Remove LiveTV menu.
[vuplus_xbmc] / xbmc / cores / AudioEngine / Sinks / AESinkDARWINOSX.cpp
1 /*
2  *      Copyright (C) 2005-2014 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 "cores/AudioEngine/AEFactory.h"
22 #include "cores/AudioEngine/Sinks/AESinkDARWINOSX.h"
23 #include "cores/AudioEngine/Utils/AEUtil.h"
24 #include "cores/AudioEngine/Utils/AERingBuffer.h"
25 #include "cores/AudioEngine/Sinks/osx/CoreAudioHelpers.h"
26 #include "cores/AudioEngine/Sinks/osx/CoreAudioHardware.h"
27 #include "cores/AudioEngine/Sinks/osx/CoreAudioChannelLayout.h"
28 #include "osx/DarwinUtils.h"
29 #include "utils/log.h"
30 #include "utils/StringUtils.h"
31 #include "threads/Condition.h"
32 #include "threads/CriticalSection.h"
33
34 #include <sstream>
35
36 #define CA_MAX_CHANNELS 16
37 // default channel map - in case it can't be fetched from the device
38 static enum AEChannel CAChannelMap[CA_MAX_CHANNELS + 1] = {
39   AE_CH_FL , AE_CH_FR , AE_CH_BL , AE_CH_BR , AE_CH_FC , AE_CH_LFE , AE_CH_SL , AE_CH_SR ,
40   AE_CH_UNKNOWN1 ,
41   AE_CH_UNKNOWN2 ,
42   AE_CH_UNKNOWN3 ,
43   AE_CH_UNKNOWN4 ,
44   AE_CH_UNKNOWN5 ,
45   AE_CH_UNKNOWN6 ,
46   AE_CH_UNKNOWN7 ,
47   AE_CH_UNKNOWN8 ,
48   AE_CH_NULL
49 };
50
51 // map coraudio channel labels to activeae channel labels
52 static enum AEChannel CAChannelToAEChannel(AudioChannelLabel CAChannelLabel)
53 {
54   enum AEChannel ret = AE_CH_NULL;
55   static unsigned int unknownChannel = AE_CH_UNKNOWN1;
56   switch(CAChannelLabel)
57   {
58     case kAudioChannelLabel_Left:
59       ret = AE_CH_FL;
60       break;
61     case kAudioChannelLabel_Right:
62       ret = AE_CH_FR;
63       break;
64     case kAudioChannelLabel_Center:
65       ret = AE_CH_FC;
66       break;
67     case kAudioChannelLabel_LFEScreen:
68       ret = AE_CH_LFE;
69       break;
70     case kAudioChannelLabel_LeftSurroundDirect:
71       ret = AE_CH_SL;
72       break;
73     case kAudioChannelLabel_RightSurroundDirect:
74       ret = AE_CH_SR;
75       break;
76     case kAudioChannelLabel_LeftCenter:
77       ret = AE_CH_FLOC;
78       break;
79     case kAudioChannelLabel_RightCenter:
80       ret = AE_CH_FROC;
81       break;
82     case kAudioChannelLabel_CenterSurround:
83       ret = AE_CH_TC;
84       break;
85     case kAudioChannelLabel_LeftSurround:
86       ret = AE_CH_SL;
87       break;
88     case kAudioChannelLabel_RightSurround:
89       ret = AE_CH_SR;
90       break;
91     case kAudioChannelLabel_VerticalHeightLeft:
92       ret = AE_CH_TFL;
93       break;
94     case kAudioChannelLabel_VerticalHeightRight:
95       ret = AE_CH_TFR;
96       break;
97     case kAudioChannelLabel_VerticalHeightCenter:
98       ret = AE_CH_TFC;
99       break;
100     case kAudioChannelLabel_TopCenterSurround:
101       ret = AE_CH_TC;
102       break;
103     case kAudioChannelLabel_TopBackLeft:
104       ret = AE_CH_TBL;
105       break;
106     case kAudioChannelLabel_TopBackRight:
107       ret = AE_CH_TBR;
108       break;
109     case kAudioChannelLabel_TopBackCenter:
110       ret = AE_CH_TBC;
111       break;
112     case kAudioChannelLabel_RearSurroundLeft:
113       ret = AE_CH_BL;
114       break;
115     case kAudioChannelLabel_RearSurroundRight:
116       ret = AE_CH_BR;
117       break;
118     case kAudioChannelLabel_LeftWide:
119       ret = AE_CH_BLOC;
120       break;
121     case kAudioChannelLabel_RightWide:
122       ret = AE_CH_BROC;
123       break;
124     case kAudioChannelLabel_LFE2:
125       ret = AE_CH_LFE;
126       break;
127     case kAudioChannelLabel_LeftTotal:
128       ret = AE_CH_FL;
129       break;
130     case kAudioChannelLabel_RightTotal:
131       ret = AE_CH_FR;
132       break;
133     case kAudioChannelLabel_HearingImpaired:
134       ret = AE_CH_FC;
135       break;
136     case kAudioChannelLabel_Narration:
137       ret = AE_CH_FC;
138       break;
139     case kAudioChannelLabel_Mono:
140       ret = AE_CH_FC;
141       break;
142     case kAudioChannelLabel_DialogCentricMix:
143       ret = AE_CH_FC;
144       break;
145     case kAudioChannelLabel_CenterSurroundDirect:
146       ret = AE_CH_TC;
147       break;
148     case kAudioChannelLabel_Haptic:
149       ret = AE_CH_FC;
150       break;
151     default:
152       ret = (enum AEChannel)unknownChannel++;
153   }
154   if (unknownChannel > AE_CH_UNKNOWN8)
155     unknownChannel = AE_CH_UNKNOWN1;
156     
157   return ret;
158 }
159
160 //Note: in multichannel mode CA will either pull 2 channels of data (stereo) or 6/8 channels of data
161 //(every speaker setup with more then 2 speakers). The difference between the number of real speakers
162 //and 6/8 channels needs to be padded with unknown channels so that the sample size fits 6/8 channels
163 //
164 //device [in] - the device whose channel layout should be used
165 //channelMap [in/out] - if filled it will it indicates that we are called from initialize and we log the requested map, out returns the channelMap for device
166 //channelsPerFrame [in] - the number of channels this device is configured to (e.x. 2 or 6/8)
167 static void GetAEChannelMap(CCoreAudioDevice &device, CAEChannelInfo &channelMap, unsigned int channelsPerFrame)
168 {
169   CCoreAudioChannelLayout calayout;
170   bool logMapping = channelMap.Count() > 0; // only log if the engine requests a layout during init
171   bool mapAvailable = false;
172   unsigned int numberChannelsInDeviceLayout = CA_MAX_CHANNELS; // default 8 channels from CAChannelMap
173   AudioChannelLayout *layout = NULL;
174
175   // try to fetch either the multichannel or the stereo channel layout from the device
176   if (channelsPerFrame == 2 || channelMap.Count() == 2)
177     mapAvailable = device.GetPreferredChannelLayoutForStereo(calayout);
178   else
179     mapAvailable = device.GetPreferredChannelLayout(calayout);
180
181   // if a map was fetched - check if it is usable
182   if (mapAvailable)
183   {
184     layout = calayout;
185     if (layout == NULL || layout->mChannelLayoutTag != kAudioChannelLayoutTag_UseChannelDescriptions)
186       mapAvailable = false;// wrong map format
187     else
188       numberChannelsInDeviceLayout = layout->mNumberChannelDescriptions;
189   }
190
191   // start the mapping action
192   // the number of channels to be added to the outgoing channelmap
193   // this is CA_MAX_CHANNELS at max and might be lower for some output devices (channelsPerFrame)
194   unsigned int numChannelsToMap = std::min((unsigned int)CA_MAX_CHANNELS, (unsigned int)channelsPerFrame);
195
196   // if there was a map fetched we force the number of
197   // channels to map to channelsPerFrame (this allows mapping
198   // of more then CA_MAX_CHANNELS if needed)
199   if (mapAvailable)
200     numChannelsToMap = channelsPerFrame;
201
202   std::string layoutStr;
203
204   if (logMapping)
205   {
206     CLog::Log(LOGDEBUG, "%s Engine requests layout %s", __FUNCTION__, ((std::string)channelMap).c_str());
207
208     if (mapAvailable)
209       CLog::Log(LOGDEBUG, "%s trying to map to %s layout: %s", __FUNCTION__, channelsPerFrame == 2 ? "stereo" : "multichannel", calayout.ChannelLayoutToString(*layout, layoutStr));
210     else
211       CLog::Log(LOGDEBUG, "%s no map available - using static multichannel map layout", __FUNCTION__);
212   }
213     
214   channelMap.Reset();// start with an empty map
215
216   for (unsigned int channel = 0; channel < numChannelsToMap; channel++)
217   {
218     // we only try to map channels which are defined in the device layout
219     enum AEChannel currentChannel;
220     if (channel < numberChannelsInDeviceLayout)
221     {
222       // get the channel from the fetched map
223       if (mapAvailable)
224         currentChannel = CAChannelToAEChannel(layout->mChannelDescriptions[channel].mChannelLabel);
225       else// get the channel from the default map
226         currentChannel = CAChannelMap[channel];
227
228     }
229     else// fill with unknown channels
230       currentChannel = CAChannelToAEChannel(kAudioChannelLabel_Unknown);
231
232     if(!channelMap.HasChannel(currentChannel))// only add if not already added
233       channelMap += currentChannel;
234   }
235
236   if (logMapping)
237     CLog::Log(LOGDEBUG, "%s mapped channels to layout %s", __FUNCTION__, ((std::string)channelMap).c_str());
238 }
239
240 static bool HasSampleRate(const AESampleRateList &list, const unsigned int samplerate)
241 {
242   for (size_t i = 0; i < list.size(); ++i)
243   {
244     if (list[i] == samplerate)
245       return true;
246   }
247   return false;
248 }
249
250 static bool HasDataFormat(const AEDataFormatList &list, const enum AEDataFormat format)
251 {
252   for (size_t i = 0; i < list.size(); ++i)
253   {
254     if (list[i] == format)
255       return true;
256   }
257   return false;
258 }
259
260 typedef std::vector< std::pair<AudioDeviceID, CAEDeviceInfo> > CADeviceList;
261
262 static void EnumerateDevices(CADeviceList &list)
263 {
264   CAEDeviceInfo device;
265
266   std::string defaultDeviceName;
267   CCoreAudioHardware::GetOutputDeviceName(defaultDeviceName);
268
269   CoreAudioDeviceList deviceIDList;
270   CCoreAudioHardware::GetOutputDevices(&deviceIDList);
271   while (!deviceIDList.empty())
272   {
273     AudioDeviceID deviceID = deviceIDList.front();
274     CCoreAudioDevice caDevice(deviceID);
275
276     device.m_channels.Reset();
277     device.m_dataFormats.clear();
278     device.m_sampleRates.clear();
279
280     device.m_deviceType = AE_DEVTYPE_PCM;
281     device.m_deviceName = caDevice.GetName();
282     device.m_displayName = device.m_deviceName;
283     device.m_displayNameExtra = "";
284
285     // flag indicating that passthroughformats where added throughout the stream enumeration
286     bool hasPassthroughFormats = false;
287     // the maximum number of channels found in the streams
288     UInt32 numMaxChannels = 0;
289     // the terminal type as reported by ca
290     UInt32 caTerminalType = 0;
291       
292     bool isDigital = caDevice.IsDigital(caTerminalType);
293
294
295     CLog::Log(LOGDEBUG, "EnumerateDevices:Device(%s)" , device.m_deviceName.c_str());
296     AudioStreamIdList streams;
297     if (caDevice.GetStreams(&streams))
298     {
299       for (AudioStreamIdList::iterator j = streams.begin(); j != streams.end(); ++j)
300       {
301         StreamFormatList streamFormats;
302         if (CCoreAudioStream::GetAvailablePhysicalFormats(*j, &streamFormats))
303         {
304           for (StreamFormatList::iterator i = streamFormats.begin(); i != streamFormats.end(); ++i)
305           {
306             AudioStreamBasicDescription desc = i->mFormat;
307             std::string formatString;
308             CLog::Log(LOGDEBUG, "EnumerateDevices:Format(%s)" ,
309                                 StreamDescriptionToString(desc, formatString));
310
311             // add stream format info
312             switch (desc.mFormatID)
313             {
314               case kAudioFormatAC3:
315               case kAudioFormat60958AC3:
316                 if (!HasDataFormat(device.m_dataFormats, AE_FMT_AC3))
317                   device.m_dataFormats.push_back(AE_FMT_AC3);
318                 if (!HasDataFormat(device.m_dataFormats, AE_FMT_DTS))
319                   device.m_dataFormats.push_back(AE_FMT_DTS);
320                 hasPassthroughFormats = true;
321                 isDigital = true;// sanity - those are always digital devices!
322                 break;
323               default:
324                 AEDataFormat format = AE_FMT_INVALID;
325                 switch(desc.mBitsPerChannel)
326                 {
327                   case 16:
328                     if (desc.mFormatFlags & kAudioFormatFlagIsBigEndian)
329                       format = AE_FMT_S16BE;
330                     else
331                     {
332                       // if it is no digital stream per definition
333                       // check if the device name suggests that it is digital
334                       // (some hackintonshs are not so smart in announcing correct
335                       // ca devices ...
336                       if (!isDigital)
337                       {
338                         std::string devNameLower = device.m_deviceName;
339                         StringUtils::ToLower(devNameLower);                       
340                         isDigital = devNameLower.find("digital") != std::string::npos;
341                       }
342
343                       /* Passthrough is possible with a 2ch digital output */
344                       if (desc.mChannelsPerFrame == 2 && isDigital)
345                       {
346                         if (desc.mSampleRate == 48000)
347                         {
348                           if (!HasDataFormat(device.m_dataFormats, AE_FMT_AC3))
349                             device.m_dataFormats.push_back(AE_FMT_AC3);
350                           if (!HasDataFormat(device.m_dataFormats, AE_FMT_DTS))
351                             device.m_dataFormats.push_back(AE_FMT_DTS);
352                           hasPassthroughFormats = true;
353                         }
354                         else if (desc.mSampleRate == 192000)
355                         {
356                           if (!HasDataFormat(device.m_dataFormats, AE_FMT_EAC3))
357                             device.m_dataFormats.push_back(AE_FMT_EAC3);
358                           hasPassthroughFormats = true;
359                         }
360                       }
361                       format = AE_FMT_S16LE;
362                     }
363                     break;
364                   case 24:
365                     if (desc.mFormatFlags & kAudioFormatFlagIsBigEndian)
366                       format = AE_FMT_S24BE3;
367                     else
368                       format = AE_FMT_S24LE3;
369                     break;
370                   case 32:
371                     if (desc.mFormatFlags & kAudioFormatFlagIsFloat)
372                       format = AE_FMT_FLOAT;
373                     else
374                     {
375                       if (desc.mFormatFlags & kAudioFormatFlagIsBigEndian)
376                         format = AE_FMT_S32BE;
377                       else
378                         format = AE_FMT_S32LE;
379                     }
380                     break;
381                 }
382                 
383                 if (numMaxChannels < desc.mChannelsPerFrame)
384                   numMaxChannels = desc.mChannelsPerFrame;
385                 
386                 if (format != AE_FMT_INVALID && !HasDataFormat(device.m_dataFormats, format))
387                   device.m_dataFormats.push_back(format);
388                 break;
389             }
390
391             // add sample rate info
392             // for devices which return kAudioStreamAnyRatee
393             // we add 44.1khz and 48khz - user can use
394             // the "fixed" audio config to force one of them
395             if (desc.mSampleRate == kAudioStreamAnyRate)
396             {
397               CLog::Log(LOGINFO, "%s reported samplerate is kAudioStreamAnyRate adding 44.1khz and 48khz", __FUNCTION__);
398               desc.mSampleRate = 44100;
399               if (!HasSampleRate(device.m_sampleRates, desc.mSampleRate))
400                 device.m_sampleRates.push_back(desc.mSampleRate);
401               desc.mSampleRate = 48000;
402             }
403
404             if (!HasSampleRate(device.m_sampleRates, desc.mSampleRate))
405               device.m_sampleRates.push_back(desc.mSampleRate);
406           }
407         }
408       }
409     }
410
411     
412     // flag indicating that the device name "sounds" like HDMI
413     bool hasHdmiName = device.m_deviceName.find("HDMI") != std::string::npos;
414     // flag indicating that the device name "sounds" like DisplayPort
415     bool hasDisplayPortName = device.m_deviceName.find("DisplayPort") != std::string::npos;
416     
417     // decide the type of the device based on the discovered information
418     // in the streams
419     // device defaults to PCM (see start of the while loop)
420     // it can be HDMI, DisplayPort or Optical
421     // for all of those types it needs to support
422     // passthroughformats and needs to be a digital port
423     if (hasPassthroughFormats && isDigital)
424     {
425       // if the max number of channels was more then 2
426       // this can be HDMI or DisplayPort or Thunderbolt
427       if (numMaxChannels > 2)
428       {
429         // either the devicename suggests its HDMI
430         // or CA reported the terminalType as HDMI
431         if (hasHdmiName || caTerminalType == kIOAudioDeviceTransportTypeHdmi)
432           device.m_deviceType = AE_DEVTYPE_HDMI;
433
434         // either the devicename suggests its DisplayPort
435         // or CA reported the terminalType as DisplayPort or Thunderbolt
436         if (hasDisplayPortName || caTerminalType == kIOAudioDeviceTransportTypeDisplayPort || caTerminalType == kIOAudioDeviceTransportTypeThunderbolt)
437           device.m_deviceType = AE_DEVTYPE_DP;
438       }
439       else// treat all other digital passthrough devices as optical
440         device.m_deviceType = AE_DEVTYPE_IEC958;
441
442       //treat all other digital devices as HDMI to let options open to the user
443       if (device.m_deviceType == AE_DEVTYPE_PCM)
444         device.m_deviceType = AE_DEVTYPE_HDMI;
445     }
446
447     // devicename based overwrites from former code - maybe FIXME at some point when we
448     // are sure that the upper detection does its job in all[tm] use cases
449     if (hasHdmiName)
450       device.m_deviceType = AE_DEVTYPE_HDMI;
451     if (hasDisplayPortName)
452       device.m_deviceType = AE_DEVTYPE_DP;
453       
454     //get channel map to match the devices channel layout as set in audio-midi-setup
455     GetAEChannelMap(caDevice, device.m_channels, caDevice.GetTotalOutputChannels());
456     
457     list.push_back(std::make_pair(deviceID, device));
458     //in the first place of the list add the default device
459     //with name "default" - if this is selected
460     //we will output to whatever osx claims to be default
461     //(allows transition from headphones to speaker and stuff
462     //like that
463     if(defaultDeviceName == device.m_deviceName)
464     {
465       device.m_deviceName = "default";
466       device.m_displayName = "Default";
467       list.insert(list.begin(), std::make_pair(deviceID, device));
468     }
469
470     deviceIDList.pop_front();
471   }
472 }
473
474 /* static, threadsafe access to the device list */
475 static CADeviceList     s_devices;
476 static CCriticalSection s_devicesLock;
477
478 static void EnumerateDevices()
479 {
480   CADeviceList devices;
481   EnumerateDevices(devices);
482   {
483     CSingleLock lock(s_devicesLock);
484     s_devices = devices;
485   }
486 }
487
488 static CADeviceList GetDevices()
489 {
490   CADeviceList list;
491   {
492     CSingleLock lock(s_devicesLock);
493     list = s_devices;
494   }
495   return list;
496 }
497
498 OSStatus deviceChangedCB(AudioObjectID                       inObjectID,
499                          UInt32                              inNumberAddresses,
500                          const AudioObjectPropertyAddress    inAddresses[],
501                          void*                               inClientData)
502 {
503   bool deviceChanged = false;
504   static AudioDeviceID oldDefaultDevice = 0;
505   AudioDeviceID currentDefaultOutputDevice = 0;
506
507   for (unsigned int i = 0; i < inNumberAddresses; i++)
508   {
509     switch (inAddresses[i].mSelector)
510     {
511       case kAudioHardwarePropertyDefaultOutputDevice:
512         currentDefaultOutputDevice = CCoreAudioHardware::GetDefaultOutputDevice();
513         // This listener is called on every change of the hardware
514         // device. So check if the default device has really changed.
515         if (oldDefaultDevice != currentDefaultOutputDevice)
516         {
517           deviceChanged = true;
518           oldDefaultDevice = currentDefaultOutputDevice;
519         }
520         break;
521       default:
522         deviceChanged = true;
523         break;
524     }
525     if (deviceChanged)
526       break;
527   }
528
529   if  (deviceChanged)
530   {
531     CLog::Log(LOGDEBUG, "CoreAudio: audiodevicelist changed - reenumerating");
532     CAEFactory::DeviceChange();
533     CLog::Log(LOGDEBUG, "CoreAudio: audiodevicelist changed - done");
534   }
535   return noErr;
536 }
537
538 ////////////////////////////////////////////////////////////////////////////////////////////
539 CAESinkDARWINOSX::CAESinkDARWINOSX()
540 : m_latentFrames(0), m_outputBitstream(false), m_outputBuffer(NULL), m_planar(false), m_planarBuffer(NULL), m_buffer(NULL)
541 {
542   // By default, kAudioHardwarePropertyRunLoop points at the process's main thread on SnowLeopard,
543   // If your process lacks such a run loop, you can set kAudioHardwarePropertyRunLoop to NULL which
544   // tells the HAL to run it's own thread for notifications (which was the default prior to SnowLeopard).
545   // So tell the HAL to use its own thread for similar behavior under all supported versions of OSX.
546   CFRunLoopRef theRunLoop = NULL;
547   AudioObjectPropertyAddress theAddress = {
548     kAudioHardwarePropertyRunLoop,
549     kAudioObjectPropertyScopeGlobal,
550     kAudioObjectPropertyElementMaster
551   };
552   OSStatus theError = AudioObjectSetPropertyData(kAudioObjectSystemObject,
553                                                  &theAddress, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop);
554   if (theError != noErr)
555   {
556     CLog::Log(LOGERROR, "CCoreAudioAE::constructor: kAudioHardwarePropertyRunLoop error.");
557   }
558   CCoreAudioDevice::RegisterDeviceChangedCB(true, deviceChangedCB, this);
559   CCoreAudioDevice::RegisterDefaultOutputDeviceChangedCB(true, deviceChangedCB, this);
560   m_started = false;
561   m_planar = false;
562 }
563
564 CAESinkDARWINOSX::~CAESinkDARWINOSX()
565 {
566   CCoreAudioDevice::RegisterDeviceChangedCB(false, deviceChangedCB, this);
567   CCoreAudioDevice::RegisterDefaultOutputDeviceChangedCB(false, deviceChangedCB, this);
568 }
569
570 float scoreSampleRate(Float64 destinationRate, unsigned int sourceRate)
571 {
572   float score = 0;
573   double intPortion;
574   double fracPortion = modf(destinationRate / sourceRate, &intPortion);
575
576   score += (1 - fracPortion) * 1000;      // prefer sample rates that are multiples of the source sample rate
577   score += (intPortion == 1.0) ? 500 : 0;   // prefer exact matches over other multiples
578   score += (intPortion > 1 && intPortion < 100) ? (100 - intPortion) / 100 * 100 : 0; // prefer smaller multiples otherwise
579
580   return score;
581 }
582
583 float ScoreStream(const AudioStreamBasicDescription &desc, const AEAudioFormat &format)
584 {
585   float score = 0;
586   if (format.m_dataFormat == AE_FMT_AC3 ||
587       format.m_dataFormat == AE_FMT_DTS)
588   {
589     if (desc.mFormatID == kAudioFormat60958AC3 ||
590         desc.mFormatID == 'IAC3' ||
591         desc.mFormatID == kAudioFormatAC3)
592     {
593       if (desc.mSampleRate == format.m_sampleRate &&
594           desc.mBitsPerChannel == CAEUtil::DataFormatToBits(format.m_dataFormat) &&
595           desc.mChannelsPerFrame == format.m_channelLayout.Count())
596       {
597         // perfect match
598         score = FLT_MAX;
599       }
600     }
601   }
602   if (format.m_dataFormat == AE_FMT_AC3 ||
603       format.m_dataFormat == AE_FMT_DTS ||
604       format.m_dataFormat == AE_FMT_EAC3)
605   { // we should be able to bistreaming in PCM if the samplerate, bitdepth and channels match
606     if (desc.mSampleRate       == format.m_sampleRate                            &&
607         desc.mBitsPerChannel   == CAEUtil::DataFormatToBits(format.m_dataFormat) &&
608         desc.mChannelsPerFrame == format.m_channelLayout.Count()                 &&
609         desc.mFormatID         == kAudioFormatLinearPCM)
610     {
611       score = FLT_MAX / 2;
612     }
613   }
614   else
615   { // non-passthrough, whatever works is fine
616     if (desc.mFormatID == kAudioFormatLinearPCM)
617     {
618       score += scoreSampleRate(desc.mSampleRate, format.m_sampleRate);
619
620       if (desc.mChannelsPerFrame == format.m_channelLayout.Count())
621         score += 5;
622       else if (desc.mChannelsPerFrame > format.m_channelLayout.Count())
623         score += 1;
624       if (format.m_dataFormat == AE_FMT_FLOAT)
625       { // for float, prefer the highest bitdepth we have
626         if (desc.mBitsPerChannel >= 16)
627           score += (desc.mBitsPerChannel / 8);
628       }
629       else
630       {
631         if (desc.mBitsPerChannel == CAEUtil::DataFormatToBits(format.m_dataFormat))
632           score += 5;
633         else if (desc.mBitsPerChannel == CAEUtil::DataFormatToBits(format.m_dataFormat))
634           score += 1;
635       }
636     }
637   }
638   return score;
639 }
640
641 bool CAESinkDARWINOSX::Initialize(AEAudioFormat &format, std::string &device)
642 {
643   AudioDeviceID deviceID = 0;
644   CADeviceList devices = GetDevices();
645   if (StringUtils::EqualsNoCase(device, "default"))
646   {
647     CCoreAudioHardware::GetOutputDeviceName(device);
648     deviceID = CCoreAudioHardware::GetDefaultOutputDevice();
649     CLog::Log(LOGNOTICE, "%s: Opening default device %s", __PRETTY_FUNCTION__, device.c_str());
650   }
651   else
652   {
653     for (size_t i = 0; i < devices.size(); i++)
654     {
655       if (device.find(devices[i].second.m_deviceName) != std::string::npos)
656       {
657         deviceID = devices[i].first;
658         break;
659       }
660     }
661   }
662
663   if (!deviceID)
664   {
665     CLog::Log(LOGERROR, "%s: Unable to find device %s", __FUNCTION__, device.c_str());
666     return false;
667   }
668
669   m_device.Open(deviceID);
670
671   // Fetch a list of the streams defined by the output device
672   AudioStreamIdList streams;
673   m_device.GetStreams(&streams);
674
675   CLog::Log(LOGDEBUG, "%s: Finding stream for format %s", __FUNCTION__, CAEUtil::DataFormatToStr(format.m_dataFormat));
676
677   bool                        passthrough  = false;
678   UInt32                      outputIndex  = 0;
679   UInt32                      numOutputChannels = 0;
680   float                       outputScore  = 0;
681   AudioStreamBasicDescription outputFormat = {0};
682   AudioStreamID               outputStream = 0;
683
684   /* The theory is to score based on
685    1. Matching passthrough characteristics (i.e. passthrough flag)
686    2. Matching sample rate.
687    3. Matching bits per channel (or higher).
688    4. Matching number of channels (or higher).
689    */
690   UInt32 index = 0;
691   for (AudioStreamIdList::const_iterator i = streams.begin(); i != streams.end(); ++i)
692   {
693     // Probe physical formats
694     StreamFormatList formats;
695     CCoreAudioStream::GetAvailablePhysicalFormats(*i, &formats);
696     for (StreamFormatList::const_iterator j = formats.begin(); j != formats.end(); ++j)
697     {
698       AudioStreamBasicDescription desc = j->mFormat;
699
700       // for devices with kAudioStreamAnyRate
701       // assume that the user uses a fixed config
702       // and knows what he is doing - so we use
703       // the requested samplerate here
704       if (desc.mSampleRate == kAudioStreamAnyRate)
705         desc.mSampleRate = format.m_sampleRate;
706
707       float score = ScoreStream(desc, format);
708
709       std::string formatString;
710       CLog::Log(LOGDEBUG, "%s: Physical Format: %s rated %f", __FUNCTION__, StreamDescriptionToString(desc, formatString), score);
711
712       if (score > outputScore)
713       {
714         passthrough  = score > 10000;
715         outputScore  = score;
716         outputFormat = desc;
717         outputStream = *i;
718         outputIndex  = index;
719       }
720     }
721     index++;
722   }
723
724   m_planar = false;
725   numOutputChannels = outputFormat.mChannelsPerFrame;
726   if (streams.size() > 1 && outputFormat.mChannelsPerFrame == 1)
727   {
728     numOutputChannels = std::min((size_t)format.m_channelLayout.Count(), streams.size());
729     m_planar = true;
730     CLog::Log(LOGDEBUG, "%s Found planar audio with %u channels using %u of them.", __FUNCTION__, (unsigned int)streams.size(), (unsigned int)numOutputChannels);
731   }
732
733   if (!outputFormat.mFormatID)
734   {
735     CLog::Log(LOGERROR, "%s, Unable to find suitable stream", __FUNCTION__);
736     return false;
737   }
738
739   /* Update our AE format */
740   format.m_sampleRate    = outputFormat.mSampleRate;
741   
742   m_outputBitstream   = passthrough && outputFormat.mFormatID == kAudioFormatLinearPCM;
743
744   std::string formatString;
745   CLog::Log(LOGDEBUG, "%s: Selected stream[%u] - id: 0x%04X, Physical Format: %s %s", __FUNCTION__, (unsigned int)outputIndex, (unsigned int)outputStream, StreamDescriptionToString(outputFormat, formatString), m_outputBitstream ? "bitstreamed passthrough" : "");
746
747   SetHogMode(passthrough);
748
749   // Configure the output stream object
750   m_outputStream.Open(outputStream);
751
752   AudioStreamBasicDescription virtualFormat, previousPhysicalFormat;
753   m_outputStream.GetVirtualFormat(&virtualFormat);
754   m_outputStream.GetPhysicalFormat(&previousPhysicalFormat);
755   CLog::Log(LOGDEBUG, "%s: Previous Virtual Format: %s", __FUNCTION__, StreamDescriptionToString(virtualFormat, formatString));
756   CLog::Log(LOGDEBUG, "%s: Previous Physical Format: %s", __FUNCTION__, StreamDescriptionToString(previousPhysicalFormat, formatString));
757
758   m_outputStream.SetPhysicalFormat(&outputFormat); // Set the active format (the old one will be reverted when we close)
759   m_outputStream.GetVirtualFormat(&virtualFormat);
760   CLog::Log(LOGDEBUG, "%s: New Virtual Format: %s", __FUNCTION__, StreamDescriptionToString(virtualFormat, formatString));
761   CLog::Log(LOGDEBUG, "%s: New Physical Format: %s", __FUNCTION__, StreamDescriptionToString(outputFormat, formatString));
762
763   // update the channel map based on the new stream format
764   GetAEChannelMap(m_device, format.m_channelLayout, numOutputChannels);
765
766
767   m_latentFrames = m_device.GetNumLatencyFrames();
768   m_latentFrames += m_outputStream.GetNumLatencyFrames();
769
770   /* TODO: Should we use the virtual format to determine our data format? */
771   format.m_frameSize     = format.m_channelLayout.Count() * (CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3);
772   format.m_frames        = m_device.GetBufferSize();
773   format.m_frameSamples  = format.m_frames * format.m_channelLayout.Count();
774
775   if (m_outputBitstream)
776   {
777     m_outputBuffer = new int16_t[format.m_frameSamples];
778     /* TODO: Do we need this? */
779     m_device.SetNominalSampleRate(format.m_sampleRate);
780   }
781
782   if (m_planar)
783     m_planarBuffer = new float[format.m_frameSamples];
784
785   unsigned int num_buffers = 4;
786   m_buffer = new AERingBuffer(num_buffers * format.m_frames * format.m_frameSize);
787   CLog::Log(LOGDEBUG, "%s: using buffer size: %u (%f ms)", __FUNCTION__, m_buffer->GetMaxSize(), (float)m_buffer->GetMaxSize() / (format.m_sampleRate * format.m_frameSize));
788
789   m_format = format;
790   if (passthrough)
791     format.m_dataFormat = AE_FMT_S16NE;
792   else
793     format.m_dataFormat = AE_FMT_FLOAT;
794
795   // Register for data request callbacks from the driver and start
796   m_device.AddIOProc(renderCallback, this);
797   m_device.Start();
798   return true;
799 }
800
801 void CAESinkDARWINOSX::SetHogMode(bool on)
802 {
803   // TODO: Auto hogging sets this for us. Figure out how/when to turn it off or use it
804   // It appears that leaving this set will aslo restore the previous stream format when the
805   // Application exits. If auto hogging is set and we try to set hog mode, we will deadlock
806   // From the SDK docs: "If the AudioDevice is in a non-mixable mode, the HAL will automatically take hog mode on behalf of the first process to start an IOProc."
807
808   // Lock down the device.  This MUST be done PRIOR to switching to a non-mixable format, if it is done at all
809   // If it is attempted after the format change, there is a high likelihood of a deadlock
810   // We may need to do this sooner to enable mix-disable (i.e. before setting the stream format)
811   if (on)
812   {
813     // Auto-Hog does not always un-hog the device when changing back to a mixable mode.
814     // Handle this on our own until it is fixed.
815     CCoreAudioHardware::SetAutoHogMode(false);
816     bool autoHog = CCoreAudioHardware::GetAutoHogMode();
817     CLog::Log(LOGDEBUG, " CoreAudioRenderer::InitializeEncoded: "
818               "Auto 'hog' mode is set to '%s'.", autoHog ? "On" : "Off");
819     if (autoHog)
820       return;
821   }
822   m_device.SetHogStatus(on);
823   m_device.SetMixingSupport(!on);
824 }
825
826 void CAESinkDARWINOSX::Deinitialize()
827 {
828   m_device.Stop();
829   m_device.RemoveIOProc();
830
831   m_outputStream.Close();
832   m_device.Close();
833   if (m_buffer)
834   {
835     delete m_buffer;
836     m_buffer = NULL;
837   }
838   m_outputBitstream = false;
839
840   delete[] m_outputBuffer;
841   m_outputBuffer = NULL;
842
843   m_planar = false;
844   delete[] m_planarBuffer;
845   m_planarBuffer = NULL;
846
847   m_started = false;
848 }
849
850 bool CAESinkDARWINOSX::IsCompatible(const AEAudioFormat &format, const std::string &device)
851 {
852   return ((m_format.m_sampleRate    == format.m_sampleRate) &&
853           (m_format.m_dataFormat    == format.m_dataFormat) &&
854           (m_format.m_channelLayout == format.m_channelLayout));
855 }
856
857 double CAESinkDARWINOSX::GetDelay()
858 {
859   if (m_buffer)
860   {
861     // Calculate the duration of the data in the cache
862     double delay = (double)m_buffer->GetReadSize() / (double)m_format.m_frameSize;
863     delay += (double)m_latentFrames;
864     delay /= (double)m_format.m_sampleRate;
865     return delay;
866   }
867   return 0.0;
868 }
869
870 double CAESinkDARWINOSX::GetCacheTotal()
871 {
872   return (double)m_buffer->GetMaxSize() / (double)(m_format.m_frameSize * m_format.m_sampleRate);
873 }
874
875 CCriticalSection mutex;
876 XbmcThreads::ConditionVariable condVar;
877
878 unsigned int CAESinkDARWINOSX::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio, bool blocking)
879 {
880   if (m_buffer->GetWriteSize() < frames * m_format.m_frameSize)
881   { // no space to write - wait for a bit
882     CSingleLock lock(mutex);
883     unsigned int timeout = 900 * frames / m_format.m_sampleRate;
884     if (!m_started)
885       timeout = 4500;
886
887     // we are using a timer here for beeing sure for timeouts
888     // condvar can be woken spuriously as signaled
889     XbmcThreads::EndTime timer(timeout);
890     condVar.wait(mutex, timeout);
891     if (!m_started && timer.IsTimePast())
892     {
893       CLog::Log(LOGERROR, "%s engine didn't start in %d ms!", __FUNCTION__, timeout);
894       return INT_MAX;    
895     }
896   }
897
898   unsigned int write_frames = std::min(frames, m_buffer->GetWriteSize() / m_format.m_frameSize);
899   if (write_frames)
900     m_buffer->Write(data, write_frames * m_format.m_frameSize);
901
902   return write_frames;
903 }
904
905 void CAESinkDARWINOSX::Drain()
906 {
907   int bytes = m_buffer->GetReadSize();
908   int totalBytes = bytes;
909   int maxNumTimeouts = 3;
910   unsigned int timeout = 900 * bytes / (m_format.m_sampleRate * m_format.m_frameSize);
911   while (bytes && maxNumTimeouts > 0)
912   {
913     CSingleLock lock(mutex);
914     XbmcThreads::EndTime timer(timeout);
915     condVar.wait(mutex, timeout);
916
917     bytes = m_buffer->GetReadSize();
918     // if we timeout and don't
919     // consum bytes - decrease maxNumTimeouts
920     if (timer.IsTimePast() && bytes == totalBytes)
921       maxNumTimeouts--;
922     totalBytes = bytes;
923   }
924 }
925
926 void CAESinkDARWINOSX::EnumerateDevicesEx(AEDeviceInfoList &list, bool force)
927 {
928   EnumerateDevices();
929   list.clear();
930   for (CADeviceList::const_iterator i = s_devices.begin(); i != s_devices.end(); ++i)
931     list.push_back(i->second);
932 }
933
934 inline void LogLevel(unsigned int got, unsigned int wanted)
935 {
936   static unsigned int lastReported = INT_MAX;
937   if (got != wanted)
938   {
939     if (got != lastReported)
940     {
941       CLog::Log(LOGWARNING, "DARWINOSX: %sflow (%u vs %u bytes)", got > wanted ? "over" : "under", got, wanted);
942       lastReported = got;
943     }    
944   }
945   else
946     lastReported = INT_MAX; // indicate we were good at least once
947 }
948
949 OSStatus CAESinkDARWINOSX::renderCallback(AudioDeviceID inDevice, const AudioTimeStamp* inNow, const AudioBufferList* inInputData, const AudioTimeStamp* inInputTime, AudioBufferList* outOutputData, const AudioTimeStamp* inOutputTime, void* inClientData)
950 {
951   CAESinkDARWINOSX *sink = (CAESinkDARWINOSX*)inClientData;
952
953   sink->m_started = true;
954   if (sink->m_planar)
955   {
956     unsigned int channels = std::min((unsigned int)outOutputData->mNumberBuffers, sink->m_format.m_channelLayout.Count());
957     unsigned int wanted = outOutputData->mBuffers[0].mDataByteSize;
958     unsigned int bytes = std::min(sink->m_buffer->GetReadSize() / channels, wanted);
959     sink->m_buffer->Read((unsigned char *)sink->m_planarBuffer, bytes * channels);
960     // transform from interleaved to planar
961     const float *src = sink->m_planarBuffer;
962     for (unsigned int i = 0; i < bytes / sizeof(float); i++)
963     {
964       for (unsigned int j = 0; j < channels; j++)
965       {
966         float *dst = (float *)outOutputData->mBuffers[j].mData;
967         dst[i] = *src++;
968       }
969     }
970     LogLevel(bytes, wanted);
971     // tell the sink we're good for more data
972     condVar.notifyAll();
973   }
974   else
975   {
976     for (unsigned int i = 0; i < outOutputData->mNumberBuffers; i++)
977     {
978       // NULL indicates a disabled stream
979       // skip it...
980       if (outOutputData->mBuffers[i].mData == NULL)
981         continue;
982
983       if (sink->m_outputBitstream)
984       {
985         /* HACK for bitstreaming AC3/DTS via PCM.
986          We reverse the float->S16LE conversion done in the stream or device */
987         static const float mul = 1.0f / (INT16_MAX + 1);
988
989         unsigned int wanted = std::min(outOutputData->mBuffers[i].mDataByteSize / sizeof(float), (size_t)sink->m_format.m_frameSamples)  * sizeof(int16_t);
990         if (wanted <= sink->m_buffer->GetReadSize())
991         {
992           sink->m_buffer->Read((unsigned char *)sink->m_outputBuffer, wanted);
993           int16_t *src = sink->m_outputBuffer;
994           float  *dest = (float*)outOutputData->mBuffers[i].mData;
995           for (unsigned int i = 0; i < wanted / 2; i++)
996             *dest++ = *src++ * mul;
997         }
998       }
999       else
1000       {
1001         /* buffers appear to come from CA already zero'd, so just copy what is wanted */
1002         unsigned int wanted = outOutputData->mBuffers[i].mDataByteSize;
1003         unsigned int bytes = std::min(sink->m_buffer->GetReadSize(), wanted);
1004         sink->m_buffer->Read((unsigned char*)outOutputData->mBuffers[i].mData, bytes);
1005         LogLevel(bytes, wanted);
1006       }
1007
1008       // tell the sink we're good for more data
1009       condVar.notifyAll();
1010     }
1011   }
1012   return noErr;
1013 }