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