ActiveAE: use keep alive timer when stream is paused
[vuplus_xbmc] / xbmc / cores / AudioEngine / Engines / ActiveAE / ActiveAESink.cpp
1 /*
2  *      Copyright (C) 2010-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include <sstream>
22
23 #include "ActiveAESink.h"
24 #include "cores/AudioEngine/Utils/AEUtil.h"
25 #include "utils/EndianSwap.h"
26 #include "ActiveAE.h"
27
28 #include "settings/Settings.h"
29
30 using namespace ActiveAE;
31
32 CActiveAESink::CActiveAESink(CEvent *inMsgEvent) :
33   CThread("AESink"),
34   m_controlPort("SinkControlPort", inMsgEvent, &m_outMsgEvent),
35   m_dataPort("SinkDataPort", inMsgEvent, &m_outMsgEvent)
36 {
37   m_inMsgEvent = inMsgEvent;
38   m_sink = NULL;
39   m_stats = NULL;
40   m_convertBuffer = NULL;
41   m_volume = 0.0;
42 }
43
44 void CActiveAESink::Start()
45 {
46   if (!IsRunning())
47   {
48     Create();
49     SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
50   }
51 }
52
53 void CActiveAESink::Dispose()
54 {
55   m_bStop = true;
56   m_outMsgEvent.Set();
57   StopThread();
58   m_controlPort.Purge();
59   m_dataPort.Purge();
60
61   if (m_sink)
62   {
63     m_sink->Drain();
64     m_sink->Deinitialize();
65     delete m_sink;
66     m_sink = NULL;
67   }
68
69   delete m_sampleOfSilence.pkt;
70   m_sampleOfSilence.pkt = NULL;
71
72   if (m_convertBuffer)
73   {
74     _aligned_free(m_convertBuffer);
75     m_convertBuffer = NULL;
76   }
77 }
78
79 AEDeviceType CActiveAESink::GetDeviceType(const std::string &device)
80 {
81   std::string dev = device;
82   std::string dri;
83   CAESinkFactory::ParseDevice(dev, dri);
84   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
85   {
86     for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
87     {
88       CAEDeviceInfo& info = *itt2;
89       if (info.m_deviceName == dev)
90         return info.m_deviceType;
91     }
92   }
93   return AE_DEVTYPE_PCM;
94 }
95
96 bool CActiveAESink::HasPassthroughDevice()
97 {
98   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
99   {
100     for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
101     {
102       CAEDeviceInfo& info = *itt2;
103       if (info.m_deviceType != AE_DEVTYPE_PCM)
104         return true;
105     }
106   }
107   return false;
108 }
109
110 bool CActiveAESink::SupportsFormat(const std::string &device, AEDataFormat format)
111 {
112   std::string dev = device;
113   std::string dri;
114   CAESinkFactory::ParseDevice(dev, dri);
115   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
116   {
117     if (dri == itt->m_sinkName)
118     {
119       for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
120       {
121         CAEDeviceInfo& info = *itt2;
122         if (info.m_deviceName == dev)
123         {
124           AEDataFormatList::iterator itt3;
125           itt3 = find(info.m_dataFormats.begin(), info.m_dataFormats.end(), format);
126           if (itt3 != info.m_dataFormats.end())
127             return true;
128           else
129             return false;
130         }
131       }
132     }
133   }
134   return false;
135 }
136
137 enum SINK_STATES
138 {
139   S_TOP = 0,                      // 0
140   S_TOP_UNCONFIGURED,             // 1
141   S_TOP_CONFIGURED,               // 2
142   S_TOP_CONFIGURED_SUSPEND,       // 3
143   S_TOP_CONFIGURED_IDLE,          // 4
144   S_TOP_CONFIGURED_PLAY,          // 5
145   S_TOP_CONFIGURED_SILENCE,       // 6
146 };
147
148 int SINK_parentStates[] = {
149     -1,
150     0, //TOP_UNCONFIGURED
151     0, //TOP_CONFIGURED
152     2, //TOP_CONFIGURED_SUSPEND
153     2, //TOP_CONFIGURED_IDLE
154     2, //TOP_CONFIGURED_PLAY
155     2, //TOP_CONFIGURED_SILENCE
156 };
157
158 void CActiveAESink::StateMachine(int signal, Protocol *port, Message *msg)
159 {
160   for (int state = m_state; ; state = SINK_parentStates[state])
161   {
162     switch (state)
163     {
164     case S_TOP: // TOP
165       if (port == &m_controlPort)
166       {
167         switch (signal)
168         {
169         case CSinkControlProtocol::CONFIGURE:
170           SinkConfig *data;
171           data = (SinkConfig*)msg->data;
172           if (data)
173           {
174             m_requestedFormat = data->format;
175             m_stats = data->stats;
176             m_device = *(data->device);
177           }
178           m_extError = false;
179           m_extSilenceTimer = 0;
180           m_extStreaming = false;
181           ReturnBuffers();
182           OpenSink();
183
184           if (!m_extError)
185           {
186             SinkReply reply;
187             reply.format = m_sinkFormat;
188             reply.cacheTotal = m_sink->GetCacheTotal();
189             reply.latency = m_sink->GetLatency();
190             reply.hasVolume = m_sink->HasVolume();
191             m_state = S_TOP_CONFIGURED_IDLE;
192             m_extTimeout = 10000;
193             msg->Reply(CSinkControlProtocol::ACC, &reply, sizeof(SinkReply));
194           }
195           else
196           {
197             m_state = S_TOP_UNCONFIGURED;
198             msg->Reply(CSinkControlProtocol::ERR);
199           }
200           return;
201
202         case CSinkControlProtocol::UNCONFIGURE:
203           ReturnBuffers();
204           if (m_sink)
205           {
206             m_sink->Drain();
207             m_sink->Deinitialize();
208             delete m_sink;
209             m_sink = NULL;
210           }
211           m_state = S_TOP_UNCONFIGURED;
212           msg->Reply(CSinkControlProtocol::ACC);
213           return;
214
215         case CSinkControlProtocol::FLUSH:
216           ReturnBuffers();
217           msg->Reply(CSinkControlProtocol::ACC);
218           return;
219
220         case CSinkControlProtocol::APPFOCUSED:
221           m_extAppFocused = *(bool*)msg->data;
222           SetSilenceTimer();
223           m_extTimeout = 0;
224           return;
225
226         default:
227           break;
228         }
229       }
230       else if (port == &m_dataPort)
231       {
232         switch (signal)
233         {
234         case CSinkDataProtocol::DRAIN:
235           msg->Reply(CSinkDataProtocol::ACC);
236           m_state = S_TOP_UNCONFIGURED;
237           m_extTimeout = 0;
238           return;
239         default:
240           break;
241         }
242       }
243       {
244         std::string portName = port == NULL ? "timer" : port->portName;
245         CLog::Log(LOGWARNING, "CActiveAESink::%s - signal: %d form port: %s not handled for state: %d", __FUNCTION__, signal, portName.c_str(), m_state);
246       }
247       return;
248
249     case S_TOP_UNCONFIGURED:
250       if (port == NULL) // timeout
251       {
252         switch (signal)
253         {
254         case CSinkControlProtocol::TIMEOUT:
255           m_extTimeout = 1000;
256           return;
257         default:
258           break;
259         }
260       }
261       else if (port == &m_dataPort)
262       {
263         switch (signal)
264         {
265         case CSinkDataProtocol::SAMPLE:
266           CSampleBuffer *samples;
267           int timeout;
268           samples = *((CSampleBuffer**)msg->data);
269           timeout = 1000*samples->pkt->nb_samples/samples->pkt->config.sample_rate;
270           Sleep(timeout);
271           msg->Reply(CSinkDataProtocol::RETURNSAMPLE, &samples, sizeof(CSampleBuffer*));
272           m_extTimeout = 0;
273           return;
274         default:
275           break;
276         }
277       }
278       break;
279
280     case S_TOP_CONFIGURED:
281       if (port == &m_controlPort)
282       {
283         switch (signal)
284         {
285         case CSinkControlProtocol::STREAMING:
286           m_extStreaming = *(bool*)msg->data;
287           SetSilenceTimer();
288           if (!m_extSilenceTimer.IsTimePast())
289           {
290             m_state = S_TOP_CONFIGURED_SILENCE;
291           }
292           m_extTimeout = 0;
293           return;
294         case CSinkControlProtocol::VOLUME:
295           m_volume = *(float*)msg->data;
296           m_sink->SetVolume(m_volume);
297           return;
298         default:
299           break;
300         }
301       }
302       else if (port == &m_dataPort)
303       {
304         switch (signal)
305         {
306         case CSinkDataProtocol::DRAIN:
307           m_sink->Drain();
308           msg->Reply(CSinkDataProtocol::ACC);
309           m_state = S_TOP_CONFIGURED_IDLE;
310           m_extTimeout = 10000;
311           return;
312         case CSinkDataProtocol::SAMPLE:
313           CSampleBuffer *samples;
314           unsigned int delay;
315           samples = *((CSampleBuffer**)msg->data);
316           delay = OutputSamples(samples);
317           msg->Reply(CSinkDataProtocol::RETURNSAMPLE, &samples, sizeof(CSampleBuffer*));
318           if (m_extError)
319           {
320             m_sink->Deinitialize();
321             delete m_sink;
322             m_sink = NULL;
323             m_state = S_TOP_CONFIGURED_SUSPEND;
324             m_extTimeout = 0;
325           }
326           else
327           {
328             m_state = S_TOP_CONFIGURED_PLAY;
329             m_extTimeout = delay / 2;
330             m_extSilenceTimer.Set(m_extSilenceTimeout);
331           }
332           return;
333         default:
334           break;
335         }
336       }
337       break;
338
339     case S_TOP_CONFIGURED_SUSPEND:
340       if (port == &m_controlPort)
341       {
342         switch (signal)
343         {
344         case CSinkControlProtocol::STREAMING:
345           m_extStreaming = *(bool*)msg->data;
346           SetSilenceTimer();
347           m_extTimeout = 0;
348           return;
349         case CSinkControlProtocol::VOLUME:
350           m_volume = *(float*)msg->data;
351           return;
352         default:
353           break;
354         }
355       }
356       else if (port == &m_dataPort)
357       {
358         switch (signal)
359         {
360         case CSinkDataProtocol::SAMPLE:
361           m_extError = false;
362           OpenSink();
363           OutputSamples(&m_sampleOfSilence);
364           m_state = S_TOP_CONFIGURED_PLAY;
365           m_extTimeout = 0;
366           m_bStateMachineSelfTrigger = true;
367           return;
368         case CSinkDataProtocol::DRAIN:
369           msg->Reply(CSinkDataProtocol::ACC);
370           return;
371         default:
372           break;
373         }
374       }
375       else if (port == NULL) // timeout
376       {
377         switch (signal)
378         {
379         case CSinkControlProtocol::TIMEOUT:
380           m_extTimeout = 10000;
381           return;
382         default:
383           break;
384         }
385       }
386       break;
387
388     case S_TOP_CONFIGURED_IDLE:
389       if (port == &m_dataPort)
390       {
391         switch (signal)
392         {
393         case CSinkDataProtocol::SAMPLE:
394           OutputSamples(&m_sampleOfSilence);
395           m_state = S_TOP_CONFIGURED_PLAY;
396           m_extTimeout = 0;
397           m_bStateMachineSelfTrigger = true;
398           return;
399         default:
400           break;
401         }
402       }
403       else if (port == NULL) // timeout
404       {
405         switch (signal)
406         {
407         case CSinkControlProtocol::TIMEOUT:
408           m_sink->Deinitialize();
409           delete m_sink;
410           m_sink = NULL;
411           m_state = S_TOP_CONFIGURED_SUSPEND;
412           m_extTimeout = 10000;
413           return;
414         default:
415           break;
416         }
417       }
418       break;
419
420     case S_TOP_CONFIGURED_PLAY:
421       if (port == NULL) // timeout
422       {
423         switch (signal)
424         {
425         case CSinkControlProtocol::TIMEOUT:
426           if (!m_extSilenceTimer.IsTimePast())
427           {
428             m_state = S_TOP_CONFIGURED_SILENCE;
429             m_extTimeout = 0;
430           }
431           else
432           {
433             m_sink->Drain();
434             m_state = S_TOP_CONFIGURED_IDLE;
435             if (m_extAppFocused)
436               m_extTimeout = 10000;
437             else
438               m_extTimeout = 0;
439           }
440           return;
441         default:
442           break;
443         }
444       }
445       break;
446
447     case S_TOP_CONFIGURED_SILENCE:
448       if (port == NULL) // timeout
449       {
450         switch (signal)
451         {
452         case CSinkControlProtocol::TIMEOUT:
453           OutputSamples(&m_sampleOfSilence);
454           if (m_extError)
455           {
456             m_sink->Deinitialize();
457             delete m_sink;
458             m_sink = NULL;
459             m_state = S_TOP_CONFIGURED_SUSPEND;
460           }
461           else
462             m_state = S_TOP_CONFIGURED_PLAY;
463           m_extTimeout = 0;
464           return;
465         default:
466           break;
467         }
468       }
469       break;
470
471     default: // we are in no state, should not happen
472       CLog::Log(LOGERROR, "CActiveAESink::%s - no valid state: %d", __FUNCTION__, m_state);
473       return;
474     }
475   } // for
476 }
477
478 void CActiveAESink::Process()
479 {
480   Message *msg = NULL;
481   Protocol *port = NULL;
482   bool gotMsg;
483   XbmcThreads::EndTime timer;
484
485   m_state = S_TOP_UNCONFIGURED;
486   m_extTimeout = 1000;
487   m_bStateMachineSelfTrigger = false;
488   m_extAppFocused = true;
489
490   while (!m_bStop)
491   {
492     gotMsg = false;
493     timer.Set(m_extTimeout);
494
495     if (m_bStateMachineSelfTrigger)
496     {
497       m_bStateMachineSelfTrigger = false;
498       // self trigger state machine
499       StateMachine(msg->signal, port, msg);
500       if (!m_bStateMachineSelfTrigger)
501       {
502         msg->Release();
503         msg = NULL;
504       }
505       continue;
506     }
507     // check control port
508     else if (m_controlPort.ReceiveOutMessage(&msg))
509     {
510       gotMsg = true;
511       port = &m_controlPort;
512     }
513     // check data port
514     else if (m_dataPort.ReceiveOutMessage(&msg))
515     {
516       gotMsg = true;
517       port = &m_dataPort;
518     }
519
520     if (gotMsg)
521     {
522       StateMachine(msg->signal, port, msg);
523       if (!m_bStateMachineSelfTrigger)
524       {
525         msg->Release();
526         msg = NULL;
527       }
528       continue;
529     }
530
531     // wait for message
532     else if (m_outMsgEvent.WaitMSec(m_extTimeout))
533     {
534       m_extTimeout = timer.MillisLeft();
535       continue;
536     }
537     // time out
538     else
539     {
540       msg = m_controlPort.GetMessage();
541       msg->signal = CSinkControlProtocol::TIMEOUT;
542       port = 0;
543       // signal timeout to state machine
544       StateMachine(msg->signal, port, msg);
545       if (!m_bStateMachineSelfTrigger)
546       {
547         msg->Release();
548         msg = NULL;
549       }
550     }
551   }
552 }
553
554 void CActiveAESink::EnumerateSinkList(bool force)
555 {
556   if (!m_sinkInfoList.empty() && !force)
557     return;
558
559   unsigned int c_retry = 4;
560   m_sinkInfoList.clear();
561   CAESinkFactory::EnumerateEx(m_sinkInfoList);
562   while(m_sinkInfoList.size() == 0 && c_retry > 0)
563   {
564     CLog::Log(LOGNOTICE, "No Devices found - retry: %d", c_retry);
565     Sleep(1500);
566     c_retry--;
567     // retry the enumeration
568     CAESinkFactory::EnumerateEx(m_sinkInfoList, true);
569   }
570   CLog::Log(LOGNOTICE, "Found %lu Lists of Devices", m_sinkInfoList.size());
571   PrintSinks();
572 }
573
574 void CActiveAESink::PrintSinks()
575 {
576   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
577   {
578     CLog::Log(LOGNOTICE, "Enumerated %s devices:", itt->m_sinkName.c_str());
579     int count = 0;
580     for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
581     {
582       CLog::Log(LOGNOTICE, "    Device %d", ++count);
583       CAEDeviceInfo& info = *itt2;
584       std::stringstream ss((std::string)info);
585       std::string line;
586       while(std::getline(ss, line, '\n'))
587         CLog::Log(LOGNOTICE, "        %s", line.c_str());
588     }
589   }
590 }
591
592 void CActiveAESink::EnumerateOutputDevices(AEDeviceList &devices, bool passthrough)
593 {
594   EnumerateSinkList(false);
595
596   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
597   {
598     AESinkInfo sinkInfo = *itt;
599     for (AEDeviceInfoList::iterator itt2 = sinkInfo.m_deviceInfoList.begin(); itt2 != sinkInfo.m_deviceInfoList.end(); ++itt2)
600     {
601       CAEDeviceInfo devInfo = *itt2;
602       if (passthrough && devInfo.m_deviceType == AE_DEVTYPE_PCM)
603         continue;
604
605       std::string device = sinkInfo.m_sinkName + ":" + devInfo.m_deviceName;
606
607       std::stringstream ss;
608
609       /* add the sink name if we have more then one sink type */
610       if (m_sinkInfoList.size() > 1)
611         ss << sinkInfo.m_sinkName << ": ";
612
613       ss << devInfo.m_displayName;
614       if (!devInfo.m_displayNameExtra.empty())
615         ss << ", " << devInfo.m_displayNameExtra;
616
617       devices.push_back(AEDevice(ss.str(), device));
618     }
619   }
620 }
621
622 std::string CActiveAESink::GetDefaultDevice(bool passthrough)
623 {
624   EnumerateSinkList(false);
625
626   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
627   {
628     AESinkInfo sinkInfo = *itt;
629     for (AEDeviceInfoList::iterator itt2 = sinkInfo.m_deviceInfoList.begin(); itt2 != sinkInfo.m_deviceInfoList.end(); ++itt2)
630     {
631       CAEDeviceInfo devInfo = *itt2;
632       if (passthrough && devInfo.m_deviceType == AE_DEVTYPE_PCM)
633         continue;
634
635       std::string device = sinkInfo.m_sinkName + ":" + devInfo.m_deviceName;
636       return device;
637     }
638   }
639   return "default";
640 }
641
642 void CActiveAESink::GetDeviceFriendlyName(std::string &device)
643 {
644   m_deviceFriendlyName = "Device not found";
645   /* Match the device and find its friendly name */
646   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
647   {
648     AESinkInfo sinkInfo = *itt;
649     for (AEDeviceInfoList::iterator itt2 = sinkInfo.m_deviceInfoList.begin(); itt2 != sinkInfo.m_deviceInfoList.end(); ++itt2)
650     {
651       CAEDeviceInfo& devInfo = *itt2;
652       if (devInfo.m_deviceName == device)
653       {
654         m_deviceFriendlyName = devInfo.m_displayName;
655         break;
656       }
657     }
658   }
659   return;
660 }
661
662 void CActiveAESink::OpenSink()
663 {
664   // we need a copy of m_device here because ParseDevice and CreateDevice write back
665   // into this variable
666   std::string device = m_device;
667   std::string driver;
668   bool passthrough = AE_IS_RAW(m_requestedFormat.m_dataFormat);
669
670   CAESinkFactory::ParseDevice(device, driver);
671   if (driver.empty() && m_sink)
672     driver = m_sink->GetName();
673
674   CLog::Log(LOGINFO, "CActiveAESink::OpenSink - initialize sink");
675
676   if (m_sink)
677   {
678     m_sink->Drain();
679     m_sink->Deinitialize();
680     delete m_sink;
681     m_sink = NULL;
682   }
683
684   // get the display name of the device
685   GetDeviceFriendlyName(device);
686
687   // if we already have a driver, prepend it to the device string
688   if (!driver.empty())
689     device = driver + ":" + device;
690
691   // WARNING: this changes format and does not use passthrough
692   m_sinkFormat = m_requestedFormat;
693   CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - trying to open device %s", device.c_str());
694   m_sink = CAESinkFactory::Create(device, m_sinkFormat, passthrough);
695
696   // try first device in out list
697   if (!m_sink && !m_sinkInfoList.empty())
698   {
699     driver = m_sinkInfoList.front().m_sinkName;
700     device = m_sinkInfoList.front().m_deviceInfoList.front().m_deviceName;
701     GetDeviceFriendlyName(device);
702     if (!driver.empty())
703       device = driver + ":" + device;
704     m_sinkFormat = m_requestedFormat;
705     CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - trying to open device %s", device.c_str());
706     m_sink = CAESinkFactory::Create(device, m_sinkFormat, passthrough);
707   }
708
709   // open NULL sink
710   // TODO: should not be required by ActiveAE
711   if (!m_sink)
712   {
713     device = "NULL:NULL";
714     m_sinkFormat = m_requestedFormat;
715     CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - open NULL sink");
716     m_sink = CAESinkFactory::Create(device, m_sinkFormat, passthrough);
717   }
718
719   if (!m_sink)
720   {
721     CLog::Log(LOGERROR, "CActiveAESink::OpenSink - no sink was returned");
722     m_extError = true;
723     return;
724   }
725
726   m_sink->SetVolume(m_volume);
727
728 #ifdef WORDS_BIGENDIAN
729   if (m_sinkFormat.m_dataFormat == AE_FMT_S16BE)
730     m_sinkFormat.m_dataFormat = AE_FMT_S16NE;
731   else if (m_sinkFormat.m_dataFormat == AE_FMT_S32BE)
732     m_sinkFormat.m_dataFormat = AE_FMT_S32NE;
733 #else
734   if (m_sinkFormat.m_dataFormat == AE_FMT_S16LE)
735     m_sinkFormat.m_dataFormat = AE_FMT_S16NE;
736   else if (m_sinkFormat.m_dataFormat == AE_FMT_S32LE)
737     m_sinkFormat.m_dataFormat = AE_FMT_S32NE;
738 #endif
739
740   CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - %s Initialized:", m_sink->GetName());
741   CLog::Log(LOGDEBUG, "  Output Device : %s", m_deviceFriendlyName.c_str());
742   CLog::Log(LOGDEBUG, "  Sample Rate   : %d", m_sinkFormat.m_sampleRate);
743   CLog::Log(LOGDEBUG, "  Sample Format : %s", CAEUtil::DataFormatToStr(m_sinkFormat.m_dataFormat));
744   CLog::Log(LOGDEBUG, "  Channel Count : %d", m_sinkFormat.m_channelLayout.Count());
745   CLog::Log(LOGDEBUG, "  Channel Layout: %s", ((std::string)m_sinkFormat.m_channelLayout).c_str());
746   CLog::Log(LOGDEBUG, "  Frames        : %d", m_sinkFormat.m_frames);
747   CLog::Log(LOGDEBUG, "  Frame Samples : %d", m_sinkFormat.m_frameSamples);
748   CLog::Log(LOGDEBUG, "  Frame Size    : %d", m_sinkFormat.m_frameSize);
749
750   // init sample of silence
751   SampleConfig config;
752   config.fmt = CActiveAEResample::GetAVSampleFormat(m_sinkFormat.m_dataFormat);
753   config.bits_per_sample = CAEUtil::DataFormatToUsedBits(m_sinkFormat.m_dataFormat);
754   config.channel_layout = CActiveAEResample::GetAVChannelLayout(m_sinkFormat.m_channelLayout);
755   config.channels = m_sinkFormat.m_channelLayout.Count();
756   config.sample_rate = m_sinkFormat.m_sampleRate;
757
758   // init sample of silence/noise
759   delete m_sampleOfSilence.pkt;
760   m_sampleOfSilence.pkt = new CSoundPacket(config, m_sinkFormat.m_frames);
761   m_sampleOfSilence.pkt->nb_samples = m_sampleOfSilence.pkt->max_nb_samples;
762   if (!passthrough)
763     GenerateNoise();
764
765   if (m_convertBuffer)
766   {
767     _aligned_free(m_convertBuffer);
768     m_convertBuffer = NULL;
769   }
770   m_convertFn = NULL;
771   m_convertState = CHECK_CONVERT;
772 }
773
774 void CActiveAESink::ReturnBuffers()
775 {
776   Message *msg = NULL;
777   CSampleBuffer *samples;
778   while (m_dataPort.ReceiveOutMessage(&msg))
779   {
780     if (msg->signal == CSinkDataProtocol::SAMPLE)
781     {
782       samples = *((CSampleBuffer**)msg->data);
783       msg->Reply(CSinkDataProtocol::RETURNSAMPLE, &samples, sizeof(CSampleBuffer*));
784     }
785   }
786 }
787
788 unsigned int CActiveAESink::OutputSamples(CSampleBuffer* samples)
789 {
790   uint8_t *buffer = samples->pkt->data[0];
791   unsigned int frames = samples->pkt->nb_samples;
792   unsigned int maxFrames;
793   int retry = 0;
794   unsigned int written = 0;
795   double sinkDelay = 0.0;
796
797   switch(m_convertState)
798   {
799   case SKIP_CONVERT:
800     break;
801   case NEED_CONVERT:
802     EnsureConvertBuffer(samples);
803     buffer = Convert(samples);
804     break;
805   case NEED_BYTESWAP:
806     Endian_Swap16_buf((uint16_t *)buffer, (uint16_t *)buffer, frames * samples->pkt->config.channels);
807     break;
808   case CHECK_CONVERT:
809     ConvertInit(samples);
810     if (m_convertState == NEED_CONVERT)
811       buffer = Convert(samples);
812     else if (m_convertState == NEED_BYTESWAP)
813       Endian_Swap16_buf((uint16_t *)buffer, (uint16_t *)buffer, frames * samples->pkt->config.channels);
814     break;
815   default:
816     break;
817   }
818
819   while(frames > 0)
820   {
821     maxFrames = std::min(frames, m_sinkFormat.m_frames);
822     written = m_sink->AddPackets(buffer, maxFrames, true, true);
823     if (written == 0)
824     {
825       Sleep(500*m_sinkFormat.m_frames/m_sinkFormat.m_sampleRate);
826       retry++;
827       if (retry > 4)
828       {
829         m_extError = true;
830         CLog::Log(LOGERROR, "CActiveAESink::OutputSamples - failed");
831         m_stats->UpdateSinkDelay(0, frames);
832         return 0;
833       }
834       else
835         continue;
836     }
837     else if (written > maxFrames)
838     {
839       m_extError = true;
840       CLog::Log(LOGERROR, "CActiveAESink::OutputSamples - sink returned error");
841       m_stats->UpdateSinkDelay(0, samples->pool ? maxFrames : 0);
842       return 0;
843     }
844     frames -= written;
845     buffer += written*m_sinkFormat.m_frameSize;
846     sinkDelay = m_sink->GetDelay();
847     m_stats->UpdateSinkDelay(sinkDelay, samples->pool ? written : 0);
848   }
849   return sinkDelay*1000;
850 }
851
852 void CActiveAESink::ConvertInit(CSampleBuffer* samples)
853 {
854   if (CActiveAEResample::GetAESampleFormat(samples->pkt->config.fmt, samples->pkt->config.bits_per_sample) != m_sinkFormat.m_dataFormat)
855   {
856     m_convertFn = CAEConvert::FrFloat(m_sinkFormat.m_dataFormat);
857     if (m_convertBuffer)
858       _aligned_free(m_convertBuffer);
859     m_convertBufferSampleSize = samples->pkt->max_nb_samples;
860     m_convertBuffer = (uint8_t*)_aligned_malloc(samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize, 16);
861     memset(m_convertBuffer, 0, samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize);
862     m_convertState = NEED_CONVERT;
863   }
864   else if (AE_IS_RAW(m_requestedFormat.m_dataFormat) && CAEUtil::S16NeedsByteSwap(AE_FMT_S16NE, m_sinkFormat.m_dataFormat))
865   {
866     m_convertState = NEED_BYTESWAP;
867   }
868   else
869     m_convertState = SKIP_CONVERT;
870 }
871
872 void CActiveAESink::EnsureConvertBuffer(CSampleBuffer* samples)
873 {
874   if (!m_convertBuffer)
875     return;
876
877   if (samples->pkt->max_nb_samples <= m_convertBufferSampleSize)
878     return;
879
880   _aligned_free(m_convertBuffer);
881   m_convertBufferSampleSize = samples->pkt->max_nb_samples;
882   m_convertBuffer = (uint8_t*)_aligned_malloc(samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize, 16);
883   memset(m_convertBuffer, 0, samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize);
884 }
885
886 uint8_t* CActiveAESink::Convert(CSampleBuffer* samples)
887 {
888   m_convertFn((float*)samples->pkt->data[0], samples->pkt->nb_samples * samples->pkt->config.channels, m_convertBuffer);
889   return m_convertBuffer;
890 }
891
892 #define PI 3.1415926536f
893
894 void CActiveAESink::GenerateNoise()
895 {
896   int nb_floats = m_sinkFormat.m_frames*m_sinkFormat.m_channelLayout.Count();
897   float *noise = (float*)_aligned_malloc(nb_floats*sizeof(float), 16);
898
899   float R1, R2;
900   for(int i=0; i<nb_floats;i++)
901   {
902     do
903     {
904       R1 = (float) rand() / (float) RAND_MAX;
905       R2 = (float) rand() / (float) RAND_MAX;
906     }
907     while(R1 == 0.0f);
908     
909     noise[i] = (float) sqrt( -2.0f * log( R1 )) * cos( 2.0f * PI * R2 ) * 0.00001f;
910   }
911
912   AEDataFormat fmt = CActiveAEResample::GetAESampleFormat(m_sampleOfSilence.pkt->config.fmt, m_sampleOfSilence.pkt->config.bits_per_sample);
913   CAEConvert::AEConvertFrFn convertFn = CAEConvert::FrFloat(fmt);
914   convertFn(noise, nb_floats, m_sampleOfSilence.pkt->data[0]);
915   _aligned_free(noise);
916 }
917
918 void CActiveAESink::SetSilenceTimer()
919 {
920   if (m_extStreaming)
921     m_extSilenceTimeout = XbmcThreads::EndTime::InfiniteValue;
922   else if (m_extAppFocused)
923     m_extSilenceTimeout = CSettings::Get().GetInt("audiooutput.streamsilence") * 60000;
924   else
925     m_extSilenceTimeout = 0;
926   m_extSilenceTimer.Set(m_extSilenceTimeout);
927 }