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