ActiveAE: Wait at least c_retry * 1500
[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           ReturnBuffers();
181           OpenSink();
182
183           if (!m_extError)
184           {
185             SinkReply reply;
186             reply.format = m_sinkFormat;
187             reply.cacheTotal = m_sink->GetCacheTotal();
188             reply.latency = m_sink->GetLatency();
189             reply.hasVolume = m_sink->HasVolume();
190             m_state = S_TOP_CONFIGURED_IDLE;
191             m_extTimeout = 10000;
192             msg->Reply(CSinkControlProtocol::ACC, &reply, sizeof(SinkReply));
193           }
194           else
195           {
196             m_state = S_TOP_UNCONFIGURED;
197             msg->Reply(CSinkControlProtocol::ERR);
198           }
199           return;
200
201         case CSinkControlProtocol::UNCONFIGURE:
202           ReturnBuffers();
203           if (m_sink)
204           {
205             m_sink->Drain();
206             m_sink->Deinitialize();
207             delete m_sink;
208             m_sink = NULL;
209           }
210           m_state = S_TOP_UNCONFIGURED;
211           msg->Reply(CSinkControlProtocol::ACC);
212           return;
213
214         case CSinkControlProtocol::FLUSH:
215           ReturnBuffers();
216           msg->Reply(CSinkControlProtocol::ACC);
217           return;
218
219         default:
220           break;
221         }
222       }
223       else if (port == &m_dataPort)
224       {
225         switch (signal)
226         {
227         case CSinkDataProtocol::DRAIN:
228           msg->Reply(CSinkDataProtocol::ACC);
229           m_state = S_TOP_UNCONFIGURED;
230           m_extTimeout = 0;
231           return;
232         default:
233           break;
234         }
235       }
236       {
237         std::string portName = port == NULL ? "timer" : port->portName;
238         CLog::Log(LOGWARNING, "CActiveAESink::%s - signal: %d form port: %s not handled for state: %d", __FUNCTION__, signal, portName.c_str(), m_state);
239       }
240       return;
241
242     case S_TOP_UNCONFIGURED:
243       if (port == NULL) // timeout
244       {
245         switch (signal)
246         {
247         case CSinkControlProtocol::TIMEOUT:
248           m_extTimeout = 1000;
249           return;
250         default:
251           break;
252         }
253       }
254       else if (port == &m_dataPort)
255       {
256         switch (signal)
257         {
258         case CSinkDataProtocol::SAMPLE:
259           CSampleBuffer *samples;
260           int timeout;
261           samples = *((CSampleBuffer**)msg->data);
262           timeout = 1000*samples->pkt->nb_samples/samples->pkt->config.sample_rate;
263           Sleep(timeout);
264           msg->Reply(CSinkDataProtocol::RETURNSAMPLE, &samples, sizeof(CSampleBuffer*));
265           m_extTimeout = 0;
266           return;
267         default:
268           break;
269         }
270       }
271       break;
272
273     case S_TOP_CONFIGURED:
274       if (port == &m_controlPort)
275       {
276         switch (signal)
277         {
278         case CSinkControlProtocol::SILENCEMODE:
279           bool silencemode;
280           silencemode = *(bool*)msg->data;
281           if (silencemode)
282             m_extSilenceTimeout = XbmcThreads::EndTime::InfiniteValue;
283           else
284             m_extSilenceTimeout = CSettings::Get().GetInt("audiooutput.streamsilence") * 60000;
285           m_extSilenceTimer.Set(m_extSilenceTimeout);
286           if (!m_extSilenceTimer.IsTimePast())
287           {
288             m_state = S_TOP_CONFIGURED_SILENCE;
289             m_extTimeout = 0;
290           }
291           return;
292         case CSinkControlProtocol::VOLUME:
293           m_volume = *(float*)msg->data;
294           m_sink->SetVolume(m_volume);
295           return;
296         default:
297           break;
298         }
299       }
300       else if (port == &m_dataPort)
301       {
302         switch (signal)
303         {
304         case CSinkDataProtocol::DRAIN:
305           m_sink->Drain();
306           msg->Reply(CSinkDataProtocol::ACC);
307           m_state = S_TOP_CONFIGURED_IDLE;
308           m_extTimeout = 10000;
309           return;
310         case CSinkDataProtocol::SAMPLE:
311           CSampleBuffer *samples;
312           unsigned int delay;
313           samples = *((CSampleBuffer**)msg->data);
314           delay = OutputSamples(samples);
315           msg->Reply(CSinkDataProtocol::RETURNSAMPLE, &samples, sizeof(CSampleBuffer*));
316           if (m_extError)
317           {
318             m_sink->Deinitialize();
319             delete m_sink;
320             m_sink = NULL;
321             m_state = S_TOP_CONFIGURED_SUSPEND;
322             m_extTimeout = 0;
323           }
324           else
325           {
326             m_state = S_TOP_CONFIGURED_PLAY;
327             m_extTimeout = delay / 2;
328             m_extSilenceTimer.Set(m_extSilenceTimeout);
329           }
330           return;
331         default:
332           break;
333         }
334       }
335       break;
336
337     case S_TOP_CONFIGURED_SUSPEND:
338       if (port == &m_controlPort)
339       {
340         switch (signal)
341         {
342         case CSinkControlProtocol::SILENCEMODE:
343           return;
344         case CSinkControlProtocol::VOLUME:
345           m_volume = *(float*)msg->data;
346           return;
347         default:
348           break;
349         }
350       }
351       else if (port == &m_dataPort)
352       {
353         switch (signal)
354         {
355         case CSinkDataProtocol::SAMPLE:
356           m_extError = false;
357           OpenSink();
358           OutputSamples(&m_sampleOfSilence);
359           m_state = S_TOP_CONFIGURED_PLAY;
360           m_extTimeout = 0;
361           m_bStateMachineSelfTrigger = true;
362           return;
363         case CSinkDataProtocol::DRAIN:
364           msg->Reply(CSinkDataProtocol::ACC);
365           return;
366         default:
367           break;
368         }
369       }
370       else if (port == NULL) // timeout
371       {
372         switch (signal)
373         {
374         case CSinkControlProtocol::TIMEOUT:
375           m_extTimeout = 10000;
376           return;
377         default:
378           break;
379         }
380       }
381       break;
382
383     case S_TOP_CONFIGURED_IDLE:
384       if (port == &m_dataPort)
385       {
386         switch (signal)
387         {
388         case CSinkDataProtocol::SAMPLE:
389           OutputSamples(&m_sampleOfSilence);
390           m_state = S_TOP_CONFIGURED_PLAY;
391           m_extTimeout = 0;
392           m_bStateMachineSelfTrigger = true;
393           return;
394         default:
395           break;
396         }
397       }
398       else if (port == NULL) // timeout
399       {
400         switch (signal)
401         {
402         case CSinkControlProtocol::TIMEOUT:
403           m_sink->Deinitialize();
404           delete m_sink;
405           m_sink = NULL;
406           m_state = S_TOP_CONFIGURED_SUSPEND;
407           m_extTimeout = 10000;
408           return;
409         default:
410           break;
411         }
412       }
413       break;
414
415     case S_TOP_CONFIGURED_PLAY:
416       if (port == NULL) // timeout
417       {
418         switch (signal)
419         {
420         case CSinkControlProtocol::TIMEOUT:
421           if (!m_extSilenceTimer.IsTimePast())
422           {
423             m_state = S_TOP_CONFIGURED_SILENCE;
424             m_extTimeout = 0;
425           }
426           else
427           {
428             m_sink->Drain();
429             m_state = S_TOP_CONFIGURED_IDLE;
430             m_extTimeout = 10000;
431           }
432           return;
433         default:
434           break;
435         }
436       }
437       break;
438
439     case S_TOP_CONFIGURED_SILENCE:
440       if (port == NULL) // timeout
441       {
442         switch (signal)
443         {
444         case CSinkControlProtocol::TIMEOUT:
445           OutputSamples(&m_sampleOfSilence);
446           if (m_extError)
447           {
448             m_sink->Deinitialize();
449             delete m_sink;
450             m_sink = NULL;
451             m_state = S_TOP_CONFIGURED_SUSPEND;
452           }
453           else
454             m_state = S_TOP_CONFIGURED_PLAY;
455           m_extTimeout = 0;
456           return;
457         default:
458           break;
459         }
460       }
461       break;
462
463     default: // we are in no state, should not happen
464       CLog::Log(LOGERROR, "CActiveAESink::%s - no valid state: %d", __FUNCTION__, m_state);
465       return;
466     }
467   } // for
468 }
469
470 void CActiveAESink::Process()
471 {
472   Message *msg = NULL;
473   Protocol *port = NULL;
474   bool gotMsg;
475   XbmcThreads::EndTime timer;
476
477   m_state = S_TOP_UNCONFIGURED;
478   m_extTimeout = 1000;
479   m_bStateMachineSelfTrigger = false;
480
481   while (!m_bStop)
482   {
483     gotMsg = false;
484     timer.Set(m_extTimeout);
485
486     if (m_bStateMachineSelfTrigger)
487     {
488       m_bStateMachineSelfTrigger = false;
489       // self trigger state machine
490       StateMachine(msg->signal, port, msg);
491       if (!m_bStateMachineSelfTrigger)
492       {
493         msg->Release();
494         msg = NULL;
495       }
496       continue;
497     }
498     // check control port
499     else if (m_controlPort.ReceiveOutMessage(&msg))
500     {
501       gotMsg = true;
502       port = &m_controlPort;
503     }
504     // check data port
505     else if (m_dataPort.ReceiveOutMessage(&msg))
506     {
507       gotMsg = true;
508       port = &m_dataPort;
509     }
510
511     if (gotMsg)
512     {
513       StateMachine(msg->signal, port, msg);
514       if (!m_bStateMachineSelfTrigger)
515       {
516         msg->Release();
517         msg = NULL;
518       }
519       continue;
520     }
521
522     // wait for message
523     else if (m_outMsgEvent.WaitMSec(m_extTimeout))
524     {
525       m_extTimeout = timer.MillisLeft();
526       continue;
527     }
528     // time out
529     else
530     {
531       msg = m_controlPort.GetMessage();
532       msg->signal = CSinkControlProtocol::TIMEOUT;
533       port = 0;
534       // signal timeout to state machine
535       StateMachine(msg->signal, port, msg);
536       if (!m_bStateMachineSelfTrigger)
537       {
538         msg->Release();
539         msg = NULL;
540       }
541     }
542   }
543 }
544
545 void CActiveAESink::EnumerateSinkList(bool force)
546 {
547   if (!m_sinkInfoList.empty() && !force)
548     return;
549
550   unsigned int c_retry = 4;
551   m_sinkInfoList.clear();
552   CAESinkFactory::EnumerateEx(m_sinkInfoList);
553   while(m_sinkInfoList.size() == 0 && c_retry > 0)
554   {
555     CLog::Log(LOGNOTICE, "No Devices found - retry: %d", c_retry);
556     Sleep(1500);
557     c_retry--;
558     // retry the enumeration
559     CAESinkFactory::EnumerateEx(m_sinkInfoList, true);
560   }
561   CLog::Log(LOGNOTICE, "Found %lu Lists of Devices", m_sinkInfoList.size());
562   PrintSinks();
563 }
564
565 void CActiveAESink::PrintSinks()
566 {
567   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
568   {
569     CLog::Log(LOGNOTICE, "Enumerated %s devices:", itt->m_sinkName.c_str());
570     int count = 0;
571     for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
572     {
573       CLog::Log(LOGNOTICE, "    Device %d", ++count);
574       CAEDeviceInfo& info = *itt2;
575       std::stringstream ss((std::string)info);
576       std::string line;
577       while(std::getline(ss, line, '\n'))
578         CLog::Log(LOGNOTICE, "        %s", line.c_str());
579     }
580   }
581 }
582
583 void CActiveAESink::EnumerateOutputDevices(AEDeviceList &devices, bool passthrough)
584 {
585   EnumerateSinkList(false);
586
587   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
588   {
589     AESinkInfo sinkInfo = *itt;
590     for (AEDeviceInfoList::iterator itt2 = sinkInfo.m_deviceInfoList.begin(); itt2 != sinkInfo.m_deviceInfoList.end(); ++itt2)
591     {
592       CAEDeviceInfo devInfo = *itt2;
593       if (passthrough && devInfo.m_deviceType == AE_DEVTYPE_PCM)
594         continue;
595
596       std::string device = sinkInfo.m_sinkName + ":" + devInfo.m_deviceName;
597
598       std::stringstream ss;
599
600       /* add the sink name if we have more then one sink type */
601       if (m_sinkInfoList.size() > 1)
602         ss << sinkInfo.m_sinkName << ": ";
603
604       ss << devInfo.m_displayName;
605       if (!devInfo.m_displayNameExtra.empty())
606         ss << ", " << devInfo.m_displayNameExtra;
607
608       devices.push_back(AEDevice(ss.str(), device));
609     }
610   }
611 }
612
613 std::string CActiveAESink::GetDefaultDevice(bool passthrough)
614 {
615   EnumerateSinkList(false);
616
617   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
618   {
619     AESinkInfo sinkInfo = *itt;
620     for (AEDeviceInfoList::iterator itt2 = sinkInfo.m_deviceInfoList.begin(); itt2 != sinkInfo.m_deviceInfoList.end(); ++itt2)
621     {
622       CAEDeviceInfo devInfo = *itt2;
623       if (passthrough && devInfo.m_deviceType == AE_DEVTYPE_PCM)
624         continue;
625
626       std::string device = sinkInfo.m_sinkName + ":" + devInfo.m_deviceName;
627       return device;
628     }
629   }
630   return "default";
631 }
632
633 void CActiveAESink::GetDeviceFriendlyName(std::string &device)
634 {
635   m_deviceFriendlyName = "Device not found";
636   /* Match the device and find its friendly name */
637   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
638   {
639     AESinkInfo sinkInfo = *itt;
640     for (AEDeviceInfoList::iterator itt2 = sinkInfo.m_deviceInfoList.begin(); itt2 != sinkInfo.m_deviceInfoList.end(); ++itt2)
641     {
642       CAEDeviceInfo& devInfo = *itt2;
643       if (devInfo.m_deviceName == device)
644       {
645         m_deviceFriendlyName = devInfo.m_displayName;
646         break;
647       }
648     }
649   }
650   return;
651 }
652
653 void CActiveAESink::OpenSink()
654 {
655   // we need a copy of m_device here because ParseDevice and CreateDevice write back
656   // into this variable
657   std::string device = m_device;
658   std::string driver;
659   bool passthrough = AE_IS_RAW(m_requestedFormat.m_dataFormat);
660
661   CAESinkFactory::ParseDevice(device, driver);
662   if (driver.empty() && m_sink)
663     driver = m_sink->GetName();
664
665   CLog::Log(LOGINFO, "CActiveAESink::OpenSink - initialize sink");
666
667   if (m_sink)
668   {
669     m_sink->Drain();
670     m_sink->Deinitialize();
671     delete m_sink;
672     m_sink = NULL;
673   }
674
675   // get the display name of the device
676   GetDeviceFriendlyName(device);
677
678   // if we already have a driver, prepend it to the device string
679   if (!driver.empty())
680     device = driver + ":" + device;
681
682   // WARNING: this changes format and does not use passthrough
683   m_sinkFormat = m_requestedFormat;
684   CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - trying to open device %s", device.c_str());
685   m_sink = CAESinkFactory::Create(device, m_sinkFormat, passthrough);
686
687   // try first device in out list
688   if (!m_sink && !m_sinkInfoList.empty())
689   {
690     driver = m_sinkInfoList.front().m_sinkName;
691     device = m_sinkInfoList.front().m_deviceInfoList.front().m_deviceName;
692     GetDeviceFriendlyName(device);
693     if (!driver.empty())
694       device = driver + ":" + device;
695     m_sinkFormat = m_requestedFormat;
696     CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - trying to open device %s", device.c_str());
697     m_sink = CAESinkFactory::Create(device, m_sinkFormat, passthrough);
698   }
699
700   // open NULL sink
701   // TODO: should not be required by ActiveAE
702   if (!m_sink)
703   {
704     device = "NULL:NULL";
705     m_sinkFormat = m_requestedFormat;
706     CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - open NULL sink");
707     m_sink = CAESinkFactory::Create(device, m_sinkFormat, passthrough);
708   }
709
710   if (!m_sink)
711   {
712     CLog::Log(LOGERROR, "CActiveAESink::OpenSink - no sink was returned");
713     m_extError = true;
714     return;
715   }
716
717   m_sink->SetVolume(m_volume);
718
719 #ifdef WORDS_BIGENDIAN
720   if (m_sinkFormat.m_dataFormat == AE_FMT_S16BE)
721     m_sinkFormat.m_dataFormat = AE_FMT_S16NE;
722   else if (m_sinkFormat.m_dataFormat == AE_FMT_S32BE)
723     m_sinkFormat.m_dataFormat = AE_FMT_S32NE;
724 #else
725   if (m_sinkFormat.m_dataFormat == AE_FMT_S16LE)
726     m_sinkFormat.m_dataFormat = AE_FMT_S16NE;
727   else if (m_sinkFormat.m_dataFormat == AE_FMT_S32LE)
728     m_sinkFormat.m_dataFormat = AE_FMT_S32NE;
729 #endif
730
731   CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - %s Initialized:", m_sink->GetName());
732   CLog::Log(LOGDEBUG, "  Output Device : %s", m_deviceFriendlyName.c_str());
733   CLog::Log(LOGDEBUG, "  Sample Rate   : %d", m_sinkFormat.m_sampleRate);
734   CLog::Log(LOGDEBUG, "  Sample Format : %s", CAEUtil::DataFormatToStr(m_sinkFormat.m_dataFormat));
735   CLog::Log(LOGDEBUG, "  Channel Count : %d", m_sinkFormat.m_channelLayout.Count());
736   CLog::Log(LOGDEBUG, "  Channel Layout: %s", ((std::string)m_sinkFormat.m_channelLayout).c_str());
737   CLog::Log(LOGDEBUG, "  Frames        : %d", m_sinkFormat.m_frames);
738   CLog::Log(LOGDEBUG, "  Frame Samples : %d", m_sinkFormat.m_frameSamples);
739   CLog::Log(LOGDEBUG, "  Frame Size    : %d", m_sinkFormat.m_frameSize);
740
741   // init sample of silence
742   SampleConfig config;
743   config.fmt = CActiveAEResample::GetAVSampleFormat(m_sinkFormat.m_dataFormat);
744   config.bits_per_sample = CAEUtil::DataFormatToUsedBits(m_sinkFormat.m_dataFormat);
745   config.channel_layout = CActiveAEResample::GetAVChannelLayout(m_sinkFormat.m_channelLayout);
746   config.channels = m_sinkFormat.m_channelLayout.Count();
747   config.sample_rate = m_sinkFormat.m_sampleRate;
748
749   // init sample of silence/noise
750   delete m_sampleOfSilence.pkt;
751   m_sampleOfSilence.pkt = new CSoundPacket(config, m_sinkFormat.m_frames);
752   m_sampleOfSilence.pkt->nb_samples = m_sampleOfSilence.pkt->max_nb_samples;
753   if (!passthrough)
754     GenerateNoise();
755
756   if (m_convertBuffer)
757   {
758     _aligned_free(m_convertBuffer);
759     m_convertBuffer = NULL;
760   }
761   m_convertFn = NULL;
762   m_convertState = CHECK_CONVERT;
763 }
764
765 void CActiveAESink::ReturnBuffers()
766 {
767   Message *msg = NULL;
768   CSampleBuffer *samples;
769   while (m_dataPort.ReceiveOutMessage(&msg))
770   {
771     if (msg->signal == CSinkDataProtocol::SAMPLE)
772     {
773       samples = *((CSampleBuffer**)msg->data);
774       msg->Reply(CSinkDataProtocol::RETURNSAMPLE, &samples, sizeof(CSampleBuffer*));
775     }
776   }
777 }
778
779 unsigned int CActiveAESink::OutputSamples(CSampleBuffer* samples)
780 {
781   uint8_t *buffer = samples->pkt->data[0];
782   unsigned int frames = samples->pkt->nb_samples;
783   unsigned int maxFrames;
784   int retry = 0;
785   unsigned int written = 0;
786   double sinkDelay = 0.0;
787
788   switch(m_convertState)
789   {
790   case SKIP_CONVERT:
791     break;
792   case NEED_CONVERT:
793     EnsureConvertBuffer(samples);
794     buffer = Convert(samples);
795     break;
796   case NEED_BYTESWAP:
797     Endian_Swap16_buf((uint16_t *)buffer, (uint16_t *)buffer, frames * samples->pkt->config.channels);
798     break;
799   case CHECK_CONVERT:
800     ConvertInit(samples);
801     if (m_convertState == NEED_CONVERT)
802       buffer = Convert(samples);
803     else if (m_convertState == NEED_BYTESWAP)
804       Endian_Swap16_buf((uint16_t *)buffer, (uint16_t *)buffer, frames * samples->pkt->config.channels);
805     break;
806   default:
807     break;
808   }
809
810   while(frames > 0)
811   {
812     maxFrames = std::min(frames, m_sinkFormat.m_frames);
813     written = m_sink->AddPackets(buffer, maxFrames, true, true);
814     if (written == 0)
815     {
816       Sleep(500*m_sinkFormat.m_frames/m_sinkFormat.m_sampleRate);
817       retry++;
818       if (retry > 4)
819       {
820         m_extError = true;
821         CLog::Log(LOGERROR, "CActiveAESink::OutputSamples - failed");
822         m_stats->UpdateSinkDelay(0, frames);
823         return 0;
824       }
825       else
826         continue;
827     }
828     else if (written > maxFrames)
829     {
830       m_extError = true;
831       CLog::Log(LOGERROR, "CActiveAESink::OutputSamples - sink returned error");
832       m_stats->UpdateSinkDelay(0, samples->pool ? maxFrames : 0);
833       return 0;
834     }
835     frames -= written;
836     buffer += written*m_sinkFormat.m_frameSize;
837     sinkDelay = m_sink->GetDelay();
838     m_stats->UpdateSinkDelay(sinkDelay, samples->pool ? written : 0);
839   }
840   return sinkDelay*1000;
841 }
842
843 void CActiveAESink::ConvertInit(CSampleBuffer* samples)
844 {
845   if (CActiveAEResample::GetAESampleFormat(samples->pkt->config.fmt, samples->pkt->config.bits_per_sample) != m_sinkFormat.m_dataFormat)
846   {
847     m_convertFn = CAEConvert::FrFloat(m_sinkFormat.m_dataFormat);
848     if (m_convertBuffer)
849       _aligned_free(m_convertBuffer);
850     m_convertBufferSampleSize = samples->pkt->max_nb_samples;
851     m_convertBuffer = (uint8_t*)_aligned_malloc(samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize, 16);
852     memset(m_convertBuffer, 0, samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize);
853     m_convertState = NEED_CONVERT;
854   }
855   else if (AE_IS_RAW(m_requestedFormat.m_dataFormat) && CAEUtil::S16NeedsByteSwap(AE_FMT_S16NE, m_sinkFormat.m_dataFormat))
856   {
857     m_convertState = NEED_BYTESWAP;
858   }
859   else
860     m_convertState = SKIP_CONVERT;
861 }
862
863 void CActiveAESink::EnsureConvertBuffer(CSampleBuffer* samples)
864 {
865   if (!m_convertBuffer)
866     return;
867
868   if (samples->pkt->max_nb_samples <= m_convertBufferSampleSize)
869     return;
870
871   _aligned_free(m_convertBuffer);
872   m_convertBufferSampleSize = samples->pkt->max_nb_samples;
873   m_convertBuffer = (uint8_t*)_aligned_malloc(samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize, 16);
874   memset(m_convertBuffer, 0, samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize);
875 }
876
877 uint8_t* CActiveAESink::Convert(CSampleBuffer* samples)
878 {
879   m_convertFn((float*)samples->pkt->data[0], samples->pkt->nb_samples * samples->pkt->config.channels, m_convertBuffer);
880   return m_convertBuffer;
881 }
882
883 #define PI 3.1415926536f
884
885 void CActiveAESink::GenerateNoise()
886 {
887   int nb_floats = m_sinkFormat.m_frames*m_sinkFormat.m_channelLayout.Count();
888   float *noise = (float*)_aligned_malloc(nb_floats*sizeof(float), 16);
889
890   float R1, R2;
891   for(int i=0; i<nb_floats;i++)
892   {
893     do
894     {
895       R1 = (float) rand() / (float) RAND_MAX;
896       R2 = (float) rand() / (float) RAND_MAX;
897     }
898     while(R1 == 0.0f);
899     
900     noise[i] = (float) sqrt( -2.0f * log( R1 )) * cos( 2.0f * PI * R2 ) * 0.00001f;
901   }
902
903   AEDataFormat fmt = CActiveAEResample::GetAESampleFormat(m_sampleOfSilence.pkt->config.fmt, m_sampleOfSilence.pkt->config.bits_per_sample);
904   CAEConvert::AEConvertFrFn convertFn = CAEConvert::FrFloat(fmt);
905   convertFn(noise, nb_floats, m_sampleOfSilence.pkt->data[0]);
906   _aligned_free(noise);
907 }