Merge pull request #4441 from Memphiz/osxdevicereset
[vuplus_xbmc] / xbmc / cores / AudioEngine / Engines / ActiveAE / ActiveAE.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 "ActiveAE.h"
22
23 using namespace ActiveAE;
24 #include "ActiveAESound.h"
25 #include "ActiveAEStream.h"
26 #include "cores/AudioEngine/Utils/AEUtil.h"
27 #include "cores/AudioEngine/Encoders/AEEncoderFFmpeg.h"
28
29 #include "settings/Settings.h"
30 #include "settings/AdvancedSettings.h"
31 #include "windowing/WindowingFactory.h"
32
33 #define MAX_CACHE_LEVEL 0.5   // total cache time of stream in seconds
34 #define MAX_WATER_LEVEL 0.25  // buffered time after stream stages in seconds
35 #define MAX_BUFFER_TIME 0.1   // max time of a buffer in seconds
36
37 void CEngineStats::Reset(unsigned int sampleRate)
38 {
39   CSingleLock lock(m_lock);
40   m_sinkUpdate = XbmcThreads::SystemClockMillis();
41   m_sinkDelay = 0;
42   m_sinkSampleRate = sampleRate;
43   m_bufferedSamples = 0;
44   m_suspended = false;
45 }
46
47 void CEngineStats::UpdateSinkDelay(double delay, int samples)
48 {
49   CSingleLock lock(m_lock);
50   m_sinkUpdate = XbmcThreads::SystemClockMillis();
51   m_sinkDelay = delay;
52   if (samples > m_bufferedSamples)
53   {
54     CLog::Log(LOGERROR, "CEngineStats::UpdateSinkDelay - inconsistency in buffer time");
55   }
56   else
57     m_bufferedSamples -= samples;
58 }
59
60 void CEngineStats::AddSamples(int samples, std::list<CActiveAEStream*> &streams)
61 {
62   CSingleLock lock(m_lock);
63   m_bufferedSamples += samples;
64
65   //update buffered time of streams
66   std::list<CActiveAEStream*>::iterator it;
67   for(it=streams.begin(); it!=streams.end(); ++it)
68   {
69     float delay = 0;
70     std::deque<CSampleBuffer*>::iterator itBuf;
71     for(itBuf=(*it)->m_processingSamples.begin(); itBuf!=(*it)->m_processingSamples.end(); ++itBuf)
72     {
73       delay += (float)(*itBuf)->pkt->nb_samples / (*itBuf)->pkt->config.sample_rate;
74     }
75     delay += (*it)->m_resampleBuffers->GetDelay();
76     (*it)->m_bufferedTime = delay;
77   }
78 }
79
80 float CEngineStats::GetDelay()
81 {
82   CSingleLock lock(m_lock);
83   unsigned int now = XbmcThreads::SystemClockMillis();
84   float delay = m_sinkDelay - (double)(now-m_sinkUpdate) / 1000;
85   delay += (float)m_bufferedSamples / m_sinkSampleRate;
86
87   if (delay < 0)
88     delay = 0.0;
89
90   return delay;
91 }
92
93 // this is used to sync a/v so we need to add sink latency here
94 float CEngineStats::GetDelay(CActiveAEStream *stream)
95 {
96   CSingleLock lock(m_lock);
97   unsigned int now = XbmcThreads::SystemClockMillis();
98   float delay = m_sinkDelay - (double)(now-m_sinkUpdate) / 1000;
99   delay += m_sinkLatency;
100   delay += (float)m_bufferedSamples / m_sinkSampleRate;
101
102   if (delay < 0)
103     delay = 0.0;
104
105   delay += stream->m_bufferedTime;
106   return delay;
107 }
108
109 float CEngineStats::GetCacheTime(CActiveAEStream *stream)
110 {
111   CSingleLock lock(m_lock);
112   float delay = (float)m_bufferedSamples / m_sinkSampleRate;
113
114   delay += stream->m_bufferedTime;
115   return delay;
116 }
117
118 float CEngineStats::GetCacheTotal(CActiveAEStream *stream)
119 {
120   return MAX_CACHE_LEVEL + m_sinkCacheTotal;
121 }
122
123 float CEngineStats::GetWaterLevel()
124 {
125   return (float)m_bufferedSamples / m_sinkSampleRate;
126 }
127
128 void CEngineStats::SetSuspended(bool state)
129 {
130   CSingleLock lock(m_lock);
131   m_suspended = state;
132 }
133
134 bool CEngineStats::IsSuspended()
135 {
136   CSingleLock lock(m_lock);
137   return m_suspended;
138 }
139
140 CActiveAE::CActiveAE() :
141   CThread("ActiveAE"),
142   m_controlPort("OutputControlPort", &m_inMsgEvent, &m_outMsgEvent),
143   m_dataPort("OutputDataPort", &m_inMsgEvent, &m_outMsgEvent),
144   m_sink(&m_outMsgEvent)
145 {
146   m_sinkBuffers = NULL;
147   m_silenceBuffers = NULL;
148   m_encoderBuffers = NULL;
149   m_vizBuffers = NULL;
150   m_vizBuffersInput = NULL;
151   m_volume = 1.0;
152   m_aeVolume = 1.0;
153   m_muted = false;
154   m_aeMuted = false;
155   m_mode = MODE_PCM;
156   m_encoder = NULL;
157   m_audioCallback = NULL;
158   m_vizInitialized = false;
159   m_sinkHasVolume = false;
160 }
161
162 CActiveAE::~CActiveAE()
163 {
164   Dispose();
165 }
166
167 void CActiveAE::Dispose()
168 {
169 #if defined(HAS_GLX) || defined(TARGET_DARWIN_OSX)
170   g_Windowing.Unregister(this);
171 #endif
172
173   m_bStop = true;
174   m_outMsgEvent.Set();
175   StopThread();
176   m_controlPort.Purge();
177   m_dataPort.Purge();
178   m_sink.Dispose();
179
180   m_dllAvFormat.Unload();
181   m_dllAvCodec.Unload();
182   m_dllAvUtil.Unload();
183 }
184
185 //-----------------------------------------------------------------------------
186 // Behavior
187 //-----------------------------------------------------------------------------
188
189 enum AE_STATES
190 {
191   AE_TOP = 0,                      // 0
192   AE_TOP_ERROR,                    // 1
193   AE_TOP_UNCONFIGURED,             // 2
194   AE_TOP_RECONFIGURING,            // 3
195   AE_TOP_CONFIGURED,               // 4
196   AE_TOP_CONFIGURED_SUSPEND,       // 5
197   AE_TOP_CONFIGURED_IDLE,          // 6
198   AE_TOP_CONFIGURED_PLAY,          // 7
199 };
200
201 int AE_parentStates[] = {
202     -1,
203     0, //TOP_ERROR
204     0, //TOP_UNCONFIGURED
205     0, //TOP_CONFIGURED
206     0, //TOP_RECONFIGURING
207     4, //TOP_CONFIGURED_SUSPEND
208     4, //TOP_CONFIGURED_IDLE
209     4, //TOP_CONFIGURED_PLAY
210 };
211
212 void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg)
213 {
214   for (int state = m_state; ; state = AE_parentStates[state])
215   {
216     switch (state)
217     {
218     case AE_TOP: // TOP
219       if (port == &m_controlPort)
220       {
221         switch (signal)
222         {
223         case CActiveAEControlProtocol::GETSTATE:
224           msg->Reply(CActiveAEControlProtocol::ACC, &m_state, sizeof(m_state));
225           return;
226         case CActiveAEControlProtocol::VOLUME:
227           m_volume = *(float*)msg->data;
228           if (m_sinkHasVolume)
229             m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::VOLUME, &m_volume, sizeof(float));
230           return;
231         case CActiveAEControlProtocol::MUTE:
232           m_muted = *(bool*)msg->data;
233           return;
234         case CActiveAEControlProtocol::KEEPCONFIG:
235           m_extKeepConfig = *(unsigned int*)msg->data;
236           return;
237         case CActiveAEControlProtocol::DISPLAYRESET:
238           return;
239         case CActiveAEControlProtocol::APPFOCUSED:
240           m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::APPFOCUSED, msg->data, sizeof(bool));
241           return;
242         default:
243           break;
244         }
245       }
246       else if (port == &m_dataPort)
247       {
248         switch (signal)
249         {
250         case CActiveAEDataProtocol::NEWSOUND:
251           CActiveAESound *sound;
252           sound = *(CActiveAESound**)msg->data;
253           if (sound)
254           {
255             m_sounds.push_back(sound);
256             ResampleSounds();
257           }
258           return;
259         case CActiveAEDataProtocol::FREESTREAM:
260           CActiveAEStream *stream;
261           stream = *(CActiveAEStream**)msg->data;
262           DiscardStream(stream);
263           return;
264         case CActiveAEDataProtocol::FREESOUND:
265           sound = *(CActiveAESound**)msg->data;
266           DiscardSound(sound);
267           return;
268         case CActiveAEDataProtocol::DRAINSTREAM:
269           stream = *(CActiveAEStream**)msg->data;
270           stream->m_drain = true;
271           stream->m_resampleBuffers->m_drain = true;
272           msg->Reply(CActiveAEDataProtocol::ACC);
273           stream->m_streamPort->SendInMessage(CActiveAEDataProtocol::STREAMDRAINED);
274           return;
275         default:
276           break;
277         }
278       }
279       else if (port == &m_sink.m_dataPort)
280       {
281         switch (signal)
282         {
283         case CSinkDataProtocol::RETURNSAMPLE:
284           CSampleBuffer **buffer;
285           buffer = (CSampleBuffer**)msg->data;
286           if (buffer)
287           {
288             (*buffer)->Return();
289           }
290           return;
291         default:
292           break;
293         }
294       }
295       {
296         std::string portName = port == NULL ? "timer" : port->portName;
297         CLog::Log(LOGWARNING, "CActiveAE::%s - signal: %d from port: %s not handled for state: %d", __FUNCTION__, signal, portName.c_str(), m_state);
298       }
299       return;
300
301     case AE_TOP_ERROR:
302       if (port == NULL) // timeout
303       {
304         switch (signal)
305         {
306         case CActiveAEControlProtocol::TIMEOUT:
307           m_extError = false;
308           LoadSettings();
309           Configure();
310           if (!m_extError)
311           {
312             m_state = AE_TOP_CONFIGURED_IDLE;
313             m_extTimeout = 0;
314           }
315           else
316           {
317             m_state = AE_TOP_ERROR;
318             m_extTimeout = 500;
319           }
320           return;
321         default:
322           break;
323         }
324       }
325       break;
326
327     case AE_TOP_UNCONFIGURED:
328       if (port == &m_controlPort)
329       {
330         switch (signal)
331         {
332         case CActiveAEControlProtocol::INIT:
333           m_extError = false;
334           m_sink.EnumerateSinkList(false);
335           LoadSettings();
336           Configure();
337           msg->Reply(CActiveAEControlProtocol::ACC);
338           if (!m_extError)
339           {
340             m_state = AE_TOP_CONFIGURED_IDLE;
341             m_extTimeout = 0;
342           }
343           else
344           {
345             m_state = AE_TOP_ERROR;
346             m_extTimeout = 500;
347           }
348           return;
349
350         default:
351           break;
352         }
353       }
354       break;
355
356     case AE_TOP_RECONFIGURING:
357       if (port == NULL) // timeout
358       {
359         switch (signal)
360         {
361         case CActiveAEControlProtocol::TIMEOUT:
362           // drain
363           if (RunStages())
364           {
365             m_extTimeout = 0;
366             return;
367           }
368           if (!m_sinkBuffers->m_inputSamples.empty() || !m_sinkBuffers->m_outputSamples.empty())
369           {
370             m_extTimeout = 100;
371             return;
372           }
373           if (NeedReconfigureSink())
374             DrainSink();
375
376           if (!m_extError)
377             Configure();
378           if (!m_extError)
379           {
380             m_state = AE_TOP_CONFIGURED_PLAY;
381             m_extTimeout = 0;
382           }
383           else
384           {
385             m_state = AE_TOP_ERROR;
386             m_extTimeout = 500;
387           }
388           m_extDeferData = false;
389           return;
390         default:
391           break;
392         }
393       }
394       break;
395
396     case AE_TOP_CONFIGURED:
397       if (port == &m_controlPort)
398       {
399         bool streaming;
400         switch (signal)
401         {
402         case CActiveAEControlProtocol::RECONFIGURE:
403           if (m_streams.empty())
404           {
405             streaming = false;
406             m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::STREAMING, &streaming, sizeof(bool));
407           }
408           LoadSettings();
409           ChangeResamplers();
410           if (!NeedReconfigureBuffers() && !NeedReconfigureSink())
411             return;
412           m_state = AE_TOP_RECONFIGURING;
413           m_extTimeout = 0;
414           // don't accept any data until we are reconfigured
415           m_extDeferData = true;
416           return;
417         case CActiveAEControlProtocol::SUSPEND:
418           UnconfigureSink();
419           m_stats.SetSuspended(true);
420           m_state = AE_TOP_CONFIGURED_SUSPEND;
421           m_extDeferData = true;
422           return;
423         case CActiveAEControlProtocol::DISPLAYLOST:
424           if (m_sink.GetDeviceType(m_mode == MODE_PCM ? m_settings.device : m_settings.passthoughdevice) == AE_DEVTYPE_HDMI)
425           {
426             UnconfigureSink();
427             m_stats.SetSuspended(true);
428             m_state = AE_TOP_CONFIGURED_SUSPEND;
429             m_extDeferData = true;
430           }
431           msg->Reply(CActiveAEControlProtocol::ACC);
432           return;
433         case CActiveAEControlProtocol::DEVICECHANGE:
434           time_t now;
435           time(&now);
436           CLog::Log(LOGDEBUG,"CActiveAE - device change event");
437           while (!m_extLastDeviceChange.empty() && (now - m_extLastDeviceChange.front() > 0))
438           {
439             m_extLastDeviceChange.pop();
440           }
441           if (m_extLastDeviceChange.size() > 2)
442           {
443             CLog::Log(LOGWARNING,"CActiveAE - received %ld device change events within one second", m_extLastDeviceChange.size());
444             return;
445           }
446           m_extLastDeviceChange.push(now);
447           UnconfigureSink();
448           m_controlPort.PurgeOut(CActiveAEControlProtocol::DEVICECHANGE);
449           m_sink.EnumerateSinkList(true);
450           LoadSettings();
451           m_extError = false;
452           Configure();
453           if (!m_extError)
454           {
455             m_state = AE_TOP_CONFIGURED_PLAY;
456             m_extTimeout = 0;
457           }
458           else
459           {
460             m_state = AE_TOP_ERROR;
461             m_extTimeout = 500;
462           }
463           return;
464         case CActiveAEControlProtocol::PAUSESTREAM:
465           CActiveAEStream *stream;
466           stream = *(CActiveAEStream**)msg->data;
467           if (stream->m_paused != true && m_streams.size() == 1)
468           {
469             FlushEngine();
470             streaming = false;
471             m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::STREAMING, &streaming, sizeof(bool));
472           }
473           stream->m_paused = true;
474           return;
475         case CActiveAEControlProtocol::RESUMESTREAM:
476           stream = *(CActiveAEStream**)msg->data;
477           stream->m_paused = false;
478           streaming = true;
479           m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::STREAMING, &streaming, sizeof(bool));
480           m_extTimeout = 0;
481           return;
482         case CActiveAEControlProtocol::FLUSHSTREAM:
483           stream = *(CActiveAEStream**)msg->data;
484           SFlushStream(stream);
485           msg->Reply(CActiveAEControlProtocol::ACC);
486           m_extTimeout = 0;
487           return;
488         case CActiveAEControlProtocol::STREAMAMP:
489           MsgStreamParameter *par;
490           par = (MsgStreamParameter*)msg->data;
491           par->stream->m_limiter.SetAmplification(par->parameter.float_par);
492           par->stream->m_amplify = par->parameter.float_par;
493           return;
494         case CActiveAEControlProtocol::STREAMVOLUME:
495           par = (MsgStreamParameter*)msg->data;
496           par->stream->m_volume = par->parameter.float_par;
497           return;
498         case CActiveAEControlProtocol::STREAMRGAIN:
499           par = (MsgStreamParameter*)msg->data;
500           par->stream->m_rgain = par->parameter.float_par;
501           return;
502         case CActiveAEControlProtocol::STREAMRESAMPLERATIO:
503           par = (MsgStreamParameter*)msg->data;
504           if (par->stream->m_resampleBuffers)
505           {
506             par->stream->m_resampleBuffers->m_resampleRatio = par->parameter.double_par;
507           }
508           return;
509         case CActiveAEControlProtocol::STREAMFADE:
510           MsgStreamFade *fade;
511           fade = (MsgStreamFade*)msg->data;
512           fade->stream->m_fadingBase = fade->from;
513           fade->stream->m_fadingTarget = fade->target;
514           fade->stream->m_fadingTime = fade->millis;
515           fade->stream->m_fadingSamples = -1;
516           return;
517         case CActiveAEControlProtocol::STOPSOUND:
518           CActiveAESound *sound;
519           sound = *(CActiveAESound**)msg->data;
520           SStopSound(sound);
521           return;
522         default:
523           break;
524         }
525       }
526       else if (port == &m_dataPort)
527       {
528         switch (signal)
529         {
530         case CActiveAEDataProtocol::PLAYSOUND:
531           CActiveAESound *sound;
532           sound = *(CActiveAESound**)msg->data;
533           if (m_settings.guisoundmode == AE_SOUND_OFF ||
534              (m_settings.guisoundmode == AE_SOUND_IDLE && !m_streams.empty()))
535             return;
536           if (sound)
537           {
538             SoundState st = {sound, 0};
539             m_sounds_playing.push_back(st);
540             m_extTimeout = 0;
541             m_state = AE_TOP_CONFIGURED_PLAY;
542           }
543           return;
544         case CActiveAEDataProtocol::NEWSTREAM:
545           MsgStreamNew *streamMsg;
546           CActiveAEStream *stream;
547           streamMsg = (MsgStreamNew*)msg->data;
548           stream = CreateStream(streamMsg);
549           if(stream)
550           {
551             msg->Reply(CActiveAEDataProtocol::ACC, &stream, sizeof(CActiveAEStream*));
552             LoadSettings();
553             Configure();
554             if (!m_extError)
555             {
556               m_state = AE_TOP_CONFIGURED_PLAY;
557               m_extTimeout = 0;
558             }
559             else
560             {
561               m_state = AE_TOP_ERROR;
562               m_extTimeout = 500;
563             }
564           }
565           else
566             msg->Reply(CActiveAEDataProtocol::ERR);
567           return;
568         case CActiveAEDataProtocol::STREAMSAMPLE:
569           MsgStreamSample *msgData;
570           CSampleBuffer *samples;
571           msgData = (MsgStreamSample*)msg->data;
572           samples = msgData->stream->m_processingSamples.front();
573           msgData->stream->m_processingSamples.pop_front();
574           if (samples != msgData->buffer)
575             CLog::Log(LOGERROR, "CActiveAE - inconsistency in stream sample message");
576           if (msgData->buffer->pkt->nb_samples == 0)
577             msgData->buffer->Return();
578           else
579             msgData->stream->m_resampleBuffers->m_inputSamples.push_back(msgData->buffer);
580           m_extTimeout = 0;
581           m_state = AE_TOP_CONFIGURED_PLAY;
582           return;
583         case CActiveAEDataProtocol::FREESTREAM:
584           stream = *(CActiveAEStream**)msg->data;
585           DiscardStream(stream);
586           if (m_streams.empty())
587           {
588             if (m_extKeepConfig)
589               m_extDrainTimer.Set(m_extKeepConfig);
590             else
591               m_extDrainTimer.Set(m_stats.GetDelay() * 1000);
592             m_extDrain = true;
593           }
594           m_extTimeout = 0;
595           m_state = AE_TOP_CONFIGURED_PLAY;
596           return;
597         case CActiveAEDataProtocol::DRAINSTREAM:
598           stream = *(CActiveAEStream**)msg->data;
599           stream->m_drain = true;
600           stream->m_resampleBuffers->m_drain = true;
601           m_extTimeout = 0;
602           m_state = AE_TOP_CONFIGURED_PLAY;
603           msg->Reply(CActiveAEDataProtocol::ACC);
604           return;
605         default:
606           break;
607         }
608       }
609       else if (port == &m_sink.m_dataPort)
610       {
611         switch (signal)
612         {
613         case CSinkDataProtocol::RETURNSAMPLE:
614           CSampleBuffer **buffer;
615           buffer = (CSampleBuffer**)msg->data;
616           if (buffer)
617           {
618             (*buffer)->Return();
619           }
620           m_extTimeout = 0;
621           m_state = AE_TOP_CONFIGURED_PLAY;
622           return;
623         default:
624           break;
625         }
626       }
627       break;
628
629     case AE_TOP_CONFIGURED_SUSPEND:
630       if (port == &m_controlPort)
631       {
632         bool displayReset = false;
633         switch (signal)
634         {
635         case CActiveAEControlProtocol::DISPLAYRESET:
636           CLog::Log(LOGDEBUG,"CActiveAE - display reset event");
637           displayReset = true;
638         case CActiveAEControlProtocol::INIT:
639           m_extError = false;
640           if (!displayReset)
641           {
642             m_controlPort.PurgeOut(CActiveAEControlProtocol::DEVICECHANGE);
643             m_sink.EnumerateSinkList(true);
644             LoadSettings();
645           }
646           Configure();
647           if (!displayReset)
648             msg->Reply(CActiveAEControlProtocol::ACC);
649           if (!m_extError)
650           {
651             m_state = AE_TOP_CONFIGURED_PLAY;
652             m_extTimeout = 0;
653           }
654           else
655           {
656             m_state = AE_TOP_ERROR;
657             m_extTimeout = 500;
658           }
659           m_stats.SetSuspended(false);
660           m_extDeferData = false;
661           return;
662         case CActiveAEControlProtocol::DEVICECHANGE:
663           return;
664         default:
665           break;
666         }
667       }
668       else if (port == &m_sink.m_dataPort)
669       {
670         switch (signal)
671         {
672         case CSinkDataProtocol::RETURNSAMPLE:
673           CSampleBuffer **buffer;
674           buffer = (CSampleBuffer**)msg->data;
675           if (buffer)
676           {
677             (*buffer)->Return();
678           }
679           return;
680         default:
681           break;
682         }
683       }
684       else if (port == NULL) // timeout
685       {
686         switch (signal)
687         {
688         case CActiveAEControlProtocol::TIMEOUT:
689           m_extTimeout = 1000;
690           return;
691         default:
692           break;
693         }
694       }
695       break;
696
697     case AE_TOP_CONFIGURED_IDLE:
698       if (port == &m_controlPort)
699       {
700         switch (signal)
701         {
702         case CActiveAEControlProtocol::RESUMESTREAM:
703           CActiveAEStream *stream;
704           stream = *(CActiveAEStream**)msg->data;
705           stream->m_paused = false;
706           m_state = AE_TOP_CONFIGURED_PLAY;
707           m_extTimeout = 0;
708           return;
709         case CActiveAEControlProtocol::FLUSHSTREAM:
710           stream = *(CActiveAEStream**)msg->data;
711           SFlushStream(stream);
712           msg->Reply(CActiveAEControlProtocol::ACC);
713           m_state = AE_TOP_CONFIGURED_PLAY;
714           m_extTimeout = 0;
715           return;
716         default:
717           break;
718         }
719       }
720       else if (port == NULL) // timeout
721       {
722         switch (signal)
723         {
724         case CActiveAEControlProtocol::TIMEOUT:
725           ResampleSounds();
726           ClearDiscardedBuffers();
727           if (m_extDrain)
728           {
729             if (m_extDrainTimer.IsTimePast())
730             {
731               Configure();
732               if (!m_extError)
733               {
734                 m_state = AE_TOP_CONFIGURED_PLAY;
735                 m_extTimeout = 0;
736               }
737               else
738               {
739                 m_state = AE_TOP_ERROR;
740                 m_extTimeout = 500;
741               }
742             }
743             else
744               m_extTimeout = m_extDrainTimer.MillisLeft();
745           }
746           else
747             m_extTimeout = 5000;
748           return;
749         default:
750           break;
751         }
752       }
753       break;
754
755     case AE_TOP_CONFIGURED_PLAY:
756       if (port == NULL) // timeout
757       {
758         switch (signal)
759         {
760         case CActiveAEControlProtocol::TIMEOUT:
761           if (m_extError)
762           {
763             m_state = AE_TOP_ERROR;
764             m_extTimeout = 100;
765             return;
766           }
767           if (RunStages())
768           {
769             m_extTimeout = 0;
770             return;
771           }
772           if (!m_extDrain && HasWork())
773           {
774             ClearDiscardedBuffers();
775             m_extTimeout = 100;
776             return;
777           }
778           m_extTimeout = 0;
779           m_state = AE_TOP_CONFIGURED_IDLE;
780           return;
781         default:
782           break;
783         }
784       }
785       break;
786
787     default: // we are in no state, should not happen
788       CLog::Log(LOGERROR, "CActiveAE::%s - no valid state: %d", __FUNCTION__, m_state);
789       return;
790     }
791   } // for
792 }
793
794 void CActiveAE::Process()
795 {
796   Message *msg = NULL;
797   Protocol *port = NULL;
798   bool gotMsg;
799   XbmcThreads::EndTime timer;
800
801   m_state = AE_TOP_UNCONFIGURED;
802   m_extTimeout = 1000;
803   m_bStateMachineSelfTrigger = false;
804   m_extDrain = false;
805   m_extDeferData = false;
806   m_extKeepConfig = 0;
807
808   // start sink
809   m_sink.Start();
810
811   while (!m_bStop)
812   {
813     gotMsg = false;
814     timer.Set(m_extTimeout);
815
816     if (m_bStateMachineSelfTrigger)
817     {
818       m_bStateMachineSelfTrigger = false;
819       // self trigger state machine
820       StateMachine(msg->signal, port, msg);
821       if (!m_bStateMachineSelfTrigger)
822       {
823         msg->Release();
824         msg = NULL;
825       }
826       continue;
827     }
828     // check control port
829     else if (m_controlPort.ReceiveOutMessage(&msg))
830     {
831       gotMsg = true;
832       port = &m_controlPort;
833     }
834     // check sink data port
835     else if (m_sink.m_dataPort.ReceiveInMessage(&msg))
836     {
837       gotMsg = true;
838       port = &m_sink.m_dataPort;
839     }
840     else if (!m_extDeferData)
841     {
842       // check data port
843       if (m_dataPort.ReceiveOutMessage(&msg))
844       {
845         gotMsg = true;
846         port = &m_dataPort;
847       }
848       // stream data ports
849       else
850       {
851         std::list<CActiveAEStream*>::iterator it;
852         for(it=m_streams.begin(); it!=m_streams.end(); ++it)
853         {
854           if((*it)->m_streamPort->ReceiveOutMessage(&msg))
855           {
856             gotMsg = true;
857             port = &m_dataPort;
858             break;
859           }
860         }
861       }
862     }
863
864     if (gotMsg)
865     {
866       StateMachine(msg->signal, port, msg);
867       if (!m_bStateMachineSelfTrigger)
868       {
869         msg->Release();
870         msg = NULL;
871       }
872       continue;
873     }
874
875     // wait for message
876     else if (m_outMsgEvent.WaitMSec(m_extTimeout))
877     {
878       m_extTimeout = timer.MillisLeft();
879       continue;
880     }
881     // time out
882     else
883     {
884       msg = m_controlPort.GetMessage();
885       msg->signal = CActiveAEControlProtocol::TIMEOUT;
886       port = 0;
887       // signal timeout to state machine
888       StateMachine(msg->signal, port, msg);
889       if (!m_bStateMachineSelfTrigger)
890       {
891         msg->Release();
892         msg = NULL;
893       }
894     }
895   }
896 }
897
898 AEAudioFormat CActiveAE::GetInputFormat(AEAudioFormat *desiredFmt)
899 {
900   AEAudioFormat inputFormat;
901
902   if (m_streams.empty())
903   {
904     inputFormat.m_dataFormat    = AE_FMT_FLOAT;
905     inputFormat.m_sampleRate    = 44100;
906     inputFormat.m_encodedRate   = 0;
907     inputFormat.m_channelLayout = AE_CH_LAYOUT_2_0;
908     inputFormat.m_frames        = 0;
909     inputFormat.m_frameSamples  = 0;
910     inputFormat.m_frameSize     = 0;
911   }
912   // force input format after unpausing slave
913   else if (desiredFmt != NULL)
914   {
915     inputFormat = *desiredFmt;
916   }
917   // keep format when having multiple streams
918   else if (m_streams.size() > 1 && m_silenceBuffers == NULL)
919   {
920     inputFormat = m_inputFormat;
921   }
922   else
923   {
924     inputFormat = m_streams.front()->m_format;
925     m_inputFormat = inputFormat;
926   }
927
928   return inputFormat;
929 }
930
931 void CActiveAE::Configure(AEAudioFormat *desiredFmt)
932 {
933   bool initSink = false;
934
935   AEAudioFormat sinkInputFormat, inputFormat;
936   AEAudioFormat oldInternalFormat = m_internalFormat;
937   AEAudioFormat oldSinkRequestFormat = m_sinkRequestFormat;
938
939   inputFormat = GetInputFormat(desiredFmt);
940
941   m_sinkRequestFormat = inputFormat;
942   ApplySettingsToFormat(m_sinkRequestFormat, m_settings, (int*)&m_mode);
943   m_extKeepConfig = 0;
944
945   std::string device = AE_IS_RAW(m_sinkRequestFormat.m_dataFormat) ? m_settings.passthoughdevice : m_settings.device;
946   std::string driver;
947   CAESinkFactory::ParseDevice(device, driver);
948   if ((!CompareFormat(m_sinkRequestFormat, m_sinkFormat) && !CompareFormat(m_sinkRequestFormat, oldSinkRequestFormat)) ||
949       m_currDevice.compare(device) != 0 ||
950       m_settings.driver.compare(driver) != 0)
951   {
952     if (!InitSink())
953       return;
954     m_settings.driver = driver;
955     m_currDevice = device;
956     initSink = true;
957     m_stats.Reset(m_sinkFormat.m_sampleRate);
958     m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::VOLUME, &m_volume, sizeof(float));
959
960     // limit buffer size in case of sink returns large buffer
961     unsigned int buffertime = m_sinkFormat.m_frames / m_sinkFormat.m_sampleRate;
962     if (buffertime > MAX_BUFFER_TIME)
963     {
964       CLog::Log(LOGWARNING, "ActiveAE::%s - sink returned large buffer of %d ms, reducing to %d ms", __FUNCTION__, buffertime, (int)(MAX_BUFFER_TIME*1000));
965       m_sinkFormat.m_frames = MAX_BUFFER_TIME * m_sinkFormat.m_sampleRate;
966     }
967   }
968
969   if (m_silenceBuffers)
970   {
971     m_discardBufferPools.push_back(m_silenceBuffers);
972     m_silenceBuffers = NULL;
973   }
974
975   // buffers for driving gui sounds if no streams are active
976   if (m_streams.empty())
977   {
978     inputFormat = m_sinkFormat;
979     if (m_sinkFormat.m_channelLayout.Count() > m_sinkRequestFormat.m_channelLayout.Count())
980     {
981       inputFormat.m_channelLayout = m_sinkRequestFormat.m_channelLayout;
982       inputFormat.m_channelLayout.ResolveChannels(m_sinkFormat.m_channelLayout);
983     }
984     inputFormat.m_dataFormat = AE_FMT_FLOAT;
985     inputFormat.m_frameSize = inputFormat.m_channelLayout.Count() *
986                               (CAEUtil::DataFormatToBits(inputFormat.m_dataFormat) >> 3);
987     m_silenceBuffers = new CActiveAEBufferPool(inputFormat);
988     m_silenceBuffers->Create(MAX_WATER_LEVEL*1000);
989     sinkInputFormat = inputFormat;
990     m_internalFormat = inputFormat;
991
992     bool streaming = false;
993     m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::STREAMING, &streaming, sizeof(bool));
994
995     delete m_encoder;
996     m_encoder = NULL;
997
998     if (m_encoderBuffers)
999     {
1000       m_discardBufferPools.push_back(m_encoderBuffers);
1001       m_encoderBuffers = NULL;
1002     }
1003     if (m_vizBuffers)
1004     {
1005       m_discardBufferPools.push_back(m_vizBuffers);
1006       m_vizBuffers = NULL;
1007     }
1008     if (m_vizBuffersInput)
1009     {
1010       m_discardBufferPools.push_back(m_vizBuffersInput);
1011       m_vizBuffersInput = NULL;
1012     }
1013   }
1014   // resample buffers for streams
1015   else
1016   {
1017     bool streaming = true;
1018     m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::STREAMING, &streaming, sizeof(bool));
1019
1020     AEAudioFormat outputFormat;
1021     if (m_mode == MODE_RAW)
1022     {
1023       inputFormat.m_frames = m_sinkFormat.m_frames;
1024       outputFormat = inputFormat;
1025       sinkInputFormat = m_sinkFormat;
1026     }
1027     // transcode everything with more than 2 channels
1028     else if (m_mode == MODE_TRANSCODE)
1029     {
1030       outputFormat = inputFormat;
1031       outputFormat.m_dataFormat = AE_FMT_FLOATP;
1032       outputFormat.m_sampleRate = 48000;
1033       outputFormat.m_encodedRate = 48000;
1034
1035       // setup encoder
1036       if (!m_encoder)
1037       {
1038         m_encoder = new CAEEncoderFFmpeg();
1039         m_encoder->Initialize(outputFormat, true);
1040         m_encoderFormat = outputFormat;
1041       }
1042       else
1043         outputFormat = m_encoderFormat;
1044
1045       outputFormat.m_channelLayout = m_encoderFormat.m_channelLayout;
1046       outputFormat.m_frames = m_encoderFormat.m_frames;
1047
1048       // encoder buffer
1049       if (m_encoder->GetCodecID() == AV_CODEC_ID_AC3)
1050       {
1051         AEAudioFormat format;
1052         format.m_channelLayout = AE_CH_LAYOUT_2_0;
1053         format.m_dataFormat = AE_FMT_S16NE;
1054         format.m_frameSize = 2* (CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3);
1055         format.m_frames = AC3_FRAME_SIZE;
1056         format.m_sampleRate = 48000;
1057         format.m_encodedRate = m_encoderFormat.m_sampleRate;
1058         if (m_encoderBuffers && initSink)
1059         {
1060           m_discardBufferPools.push_back(m_encoderBuffers);
1061           m_encoderBuffers = NULL;
1062         }
1063         if (!m_encoderBuffers)
1064         {
1065           m_encoderBuffers = new CActiveAEBufferPool(format);
1066           m_encoderBuffers->Create(MAX_WATER_LEVEL*1000);
1067         }
1068       }
1069
1070       sinkInputFormat = m_sinkFormat;
1071     }
1072     else
1073     {
1074       outputFormat = m_sinkFormat;
1075       outputFormat.m_dataFormat = AE_FMT_FLOAT;
1076       outputFormat.m_frameSize = outputFormat.m_channelLayout.Count() *
1077                                  (CAEUtil::DataFormatToBits(outputFormat.m_dataFormat) >> 3);
1078
1079       // due to channel ordering of the driver, a sink may return more channels than
1080       // requested, i.e. 2.1 request returns FL,FR,BL,BR,FC,LFE for ALSA
1081       // in this case we need to downmix to requested format
1082       if (m_sinkFormat.m_channelLayout.Count() > m_sinkRequestFormat.m_channelLayout.Count())
1083       {
1084         outputFormat.m_channelLayout = m_sinkRequestFormat.m_channelLayout;
1085         outputFormat.m_channelLayout.ResolveChannels(m_sinkFormat.m_channelLayout);
1086       }
1087
1088       // TODO: adjust to decoder
1089       sinkInputFormat = outputFormat;
1090     }
1091     m_internalFormat = outputFormat;
1092
1093     std::list<CActiveAEStream*>::iterator it;
1094     for(it=m_streams.begin(); it!=m_streams.end(); ++it)
1095     {
1096       // check if we support input format of stream
1097       if (!AE_IS_RAW((*it)->m_format.m_dataFormat) && 
1098           CActiveAEResample::GetAVSampleFormat((*it)->m_format.m_dataFormat) == AV_SAMPLE_FMT_FLT &&
1099           (*it)->m_format.m_dataFormat != AE_FMT_FLOAT)
1100       {
1101         (*it)->m_convertFn = CAEConvert::ToFloat((*it)->m_format.m_dataFormat);
1102         (*it)->m_format.m_dataFormat = AE_FMT_FLOAT;
1103       }
1104
1105       if (!(*it)->m_inputBuffers)
1106       {
1107         // align input buffers with period of sink or encoder
1108         (*it)->m_format.m_frames = m_internalFormat.m_frames * ((float)(*it)->m_format.m_sampleRate / m_internalFormat.m_sampleRate);
1109
1110         // create buffer pool
1111         (*it)->m_inputBuffers = new CActiveAEBufferPool((*it)->m_format);
1112         (*it)->m_inputBuffers->Create(MAX_CACHE_LEVEL*1000);
1113         (*it)->m_streamSpace = (*it)->m_format.m_frameSize * (*it)->m_format.m_frames;
1114
1115         // if input format does not follow ffmpeg channel mask, we may need to remap channels
1116         (*it)->InitRemapper();
1117       }
1118       if (initSink && (*it)->m_resampleBuffers)
1119       {
1120         m_discardBufferPools.push_back((*it)->m_resampleBuffers);
1121         (*it)->m_resampleBuffers = NULL;
1122       }
1123       if (!(*it)->m_resampleBuffers)
1124       {
1125         (*it)->m_resampleBuffers = new CActiveAEBufferPoolResample((*it)->m_inputBuffers->m_format, outputFormat, m_settings.resampleQuality);
1126         (*it)->m_resampleBuffers->m_changeResampler = (*it)->m_forceResampler;
1127         (*it)->m_resampleBuffers->Create(MAX_CACHE_LEVEL*1000, false, m_settings.stereoupmix, m_settings.normalizelevels);
1128       }
1129       if (m_mode == MODE_TRANSCODE || m_streams.size() > 1)
1130         (*it)->m_resampleBuffers->m_fillPackets = true;
1131
1132       // amplification
1133       (*it)->m_limiter.SetSamplerate(outputFormat.m_sampleRate);
1134     }
1135
1136     // update buffered time of streams
1137     m_stats.AddSamples(0, m_streams);
1138
1139     // buffers for viz
1140     if (!AE_IS_RAW(inputFormat.m_dataFormat))
1141     {
1142       if (initSink && m_vizBuffers)
1143       {
1144         m_discardBufferPools.push_back(m_vizBuffers);
1145         m_vizBuffers = NULL;
1146         m_discardBufferPools.push_back(m_vizBuffersInput);
1147         m_vizBuffersInput = NULL;
1148       }
1149       if (!m_vizBuffers)
1150       {
1151         AEAudioFormat vizFormat = m_internalFormat;
1152         vizFormat.m_channelLayout = AE_CH_LAYOUT_2_0;
1153         vizFormat.m_dataFormat = AE_FMT_FLOAT;
1154
1155         // input buffers
1156         m_vizBuffersInput = new CActiveAEBufferPool(m_internalFormat);
1157         m_vizBuffersInput->Create(2000);
1158
1159         // resample buffers
1160         m_vizBuffers = new CActiveAEBufferPoolResample(m_internalFormat, vizFormat, m_settings.resampleQuality);
1161         // TODO use cache of sync + water level
1162         m_vizBuffers->Create(2000, false, false);
1163         m_vizInitialized = false;
1164       }
1165     }
1166   }
1167
1168   // resample buffers for sink
1169   if (m_sinkBuffers && 
1170      (!CompareFormat(m_sinkBuffers->m_format,m_sinkFormat) || !CompareFormat(m_sinkBuffers->m_inputFormat, sinkInputFormat)))
1171   {
1172     m_discardBufferPools.push_back(m_sinkBuffers);
1173     m_sinkBuffers = NULL;
1174   }
1175   if (!m_sinkBuffers)
1176   {
1177     m_sinkBuffers = new CActiveAEBufferPoolResample(sinkInputFormat, m_sinkFormat, m_settings.resampleQuality);
1178     m_sinkBuffers->Create(MAX_WATER_LEVEL*1000, true, false);
1179   }
1180
1181   // reset gui sounds
1182   if (!CompareFormat(oldInternalFormat, m_internalFormat))
1183   {
1184     if (m_settings.guisoundmode == AE_SOUND_ALWAYS ||
1185        (m_settings.guisoundmode == AE_SOUND_IDLE && m_streams.empty()))
1186     {
1187       std::vector<CActiveAESound*>::iterator it;
1188       for (it = m_sounds.begin(); it != m_sounds.end(); ++it)
1189       {
1190         (*it)->SetConverted(false);
1191       }
1192     }
1193     m_sounds_playing.clear();
1194   }
1195
1196   ClearDiscardedBuffers();
1197   m_extDrain = false;
1198 }
1199
1200 CActiveAEStream* CActiveAE::CreateStream(MsgStreamNew *streamMsg)
1201 {
1202   // we only can handle a single pass through stream
1203   bool hasRawStream = false;
1204   bool hasStream = false;
1205   std::list<CActiveAEStream*>::iterator it;
1206   for(it = m_streams.begin(); it != m_streams.end(); ++it)
1207   {
1208     if((*it)->IsDrained())
1209       continue;
1210     if(AE_IS_RAW((*it)->m_format.m_dataFormat))
1211       hasRawStream = true;
1212     hasStream = true;
1213   }
1214   if (hasRawStream || (hasStream && AE_IS_RAW(streamMsg->format.m_dataFormat)))
1215   {
1216     return NULL;
1217   }
1218
1219   // create the stream
1220   CActiveAEStream *stream;
1221   stream = new CActiveAEStream(&streamMsg->format);
1222   stream->m_streamPort = new CActiveAEDataProtocol("stream",
1223                              &stream->m_inMsgEvent, &m_outMsgEvent);
1224
1225   // create buffer pool
1226   stream->m_inputBuffers = NULL; // create in Configure when we know the sink format
1227   stream->m_resampleBuffers = NULL; // create in Configure when we know the sink format
1228   stream->m_statsLock = m_stats.GetLock();
1229   stream->m_fadingSamples = 0;
1230   stream->m_started = false;
1231
1232   if (streamMsg->options & AESTREAM_PAUSED)
1233     stream->m_paused = true;
1234
1235   if (streamMsg->options & AESTREAM_FORCE_RESAMPLE)
1236     stream->m_forceResampler = true;
1237
1238   m_streams.push_back(stream);
1239
1240   return stream;
1241 }
1242
1243 void CActiveAE::DiscardStream(CActiveAEStream *stream)
1244 {
1245   std::list<CActiveAEStream*>::iterator it;
1246   for (it=m_streams.begin(); it!=m_streams.end(); )
1247   {
1248     if (stream == (*it))
1249     {
1250       while (!(*it)->m_processingSamples.empty())
1251       {
1252         (*it)->m_processingSamples.front()->Return();
1253         (*it)->m_processingSamples.pop_front();
1254       }
1255       m_discardBufferPools.push_back((*it)->m_inputBuffers);
1256       m_discardBufferPools.push_back((*it)->m_resampleBuffers);
1257       CLog::Log(LOGDEBUG, "CActiveAE::DiscardStream - audio stream deleted");
1258       delete (*it)->m_streamPort;
1259       delete (*it);
1260       it = m_streams.erase(it);
1261     }
1262     else
1263       ++it;
1264   }
1265
1266   ClearDiscardedBuffers();
1267 }
1268
1269 void CActiveAE::SFlushStream(CActiveAEStream *stream)
1270 {
1271   while (!stream->m_processingSamples.empty())
1272   {
1273     stream->m_processingSamples.front()->Return();
1274     stream->m_processingSamples.pop_front();
1275   }
1276   stream->m_resampleBuffers->Flush();
1277   stream->m_streamPort->Purge();
1278   stream->m_bufferedTime = 0.0;
1279   stream->m_paused = false;
1280
1281   // flush the engine if we only have a single stream
1282   if (m_streams.size() == 1)
1283   {
1284     FlushEngine();
1285   }
1286 }
1287
1288 void CActiveAE::FlushEngine()
1289 {
1290   if (m_sinkBuffers)
1291     m_sinkBuffers->Flush();
1292   if (m_vizBuffers)
1293     m_vizBuffers->Flush();
1294
1295   // send message to sink
1296   Message *reply;
1297   if (m_sink.m_controlPort.SendOutMessageSync(CSinkControlProtocol::FLUSH,
1298                                            &reply, 2000))
1299   {
1300     bool success = reply->signal == CSinkControlProtocol::ACC;
1301     if (!success)
1302     {
1303       CLog::Log(LOGERROR, "ActiveAE::%s - returned error on flush", __FUNCTION__);
1304       m_extError = true;
1305     }
1306     reply->Release();
1307   }
1308   else
1309   {
1310     CLog::Log(LOGERROR, "ActiveAE::%s - failed to flush", __FUNCTION__);
1311     m_extError = true;
1312   }
1313   m_stats.Reset(m_sinkFormat.m_sampleRate);
1314 }
1315
1316 void CActiveAE::ClearDiscardedBuffers()
1317 {
1318   std::list<CActiveAEBufferPool*>::iterator it;
1319   for (it=m_discardBufferPools.begin(); it!=m_discardBufferPools.end(); ++it)
1320   {
1321     CActiveAEBufferPoolResample *rbuf = dynamic_cast<CActiveAEBufferPoolResample*>(*it);
1322     if (rbuf)
1323     {
1324       rbuf->Flush();
1325     }
1326     // if all buffers have returned, we can delete the buffer pool
1327     if ((*it)->m_allSamples.size() == (*it)->m_freeSamples.size())
1328     {
1329       delete (*it);
1330       CLog::Log(LOGDEBUG, "CActiveAE::ClearDiscardedBuffers - buffer pool deleted");
1331       m_discardBufferPools.erase(it);
1332       return;
1333     }
1334   }
1335 }
1336
1337 void CActiveAE::SStopSound(CActiveAESound *sound)
1338 {
1339   std::list<SoundState>::iterator it;
1340   for (it=m_sounds_playing.begin(); it!=m_sounds_playing.end(); ++it)
1341   {
1342     if (it->sound == sound)
1343     {
1344       m_sounds_playing.erase(it);
1345       return;
1346     }
1347   }
1348 }
1349
1350 void CActiveAE::DiscardSound(CActiveAESound *sound)
1351 {
1352   SStopSound(sound);
1353
1354   std::vector<CActiveAESound*>::iterator it;
1355   for (it=m_sounds.begin(); it!=m_sounds.end(); ++it)
1356   {
1357     if ((*it) == sound)
1358     {
1359       m_sounds.erase(it);
1360       return;
1361     }
1362   }
1363 }
1364
1365 void CActiveAE::ChangeResamplers()
1366 {
1367   std::list<CActiveAEStream*>::iterator it;
1368   for(it=m_streams.begin(); it!=m_streams.end(); ++it)
1369   {
1370     bool normalize = true;
1371     if (((*it)->m_resampleBuffers->m_format.m_channelLayout.Count() <
1372          (*it)->m_resampleBuffers->m_inputFormat.m_channelLayout.Count()) &&
1373          !m_settings.normalizelevels)
1374       normalize = false;
1375
1376     if ((*it)->m_resampleBuffers && (*it)->m_resampleBuffers->m_resampler &&
1377         (((*it)->m_resampleBuffers->m_resampleQuality != m_settings.resampleQuality) ||
1378         (((*it)->m_resampleBuffers->m_stereoUpmix != m_settings.stereoupmix)) ||
1379         ((*it)->m_resampleBuffers->m_normalize != normalize)))
1380     {
1381       (*it)->m_resampleBuffers->m_changeResampler = true;
1382     }
1383     (*it)->m_resampleBuffers->m_resampleQuality = m_settings.resampleQuality;
1384     (*it)->m_resampleBuffers->m_stereoUpmix = m_settings.stereoupmix;
1385     (*it)->m_resampleBuffers->m_normalize = normalize;
1386   }
1387 }
1388
1389 void CActiveAE::ApplySettingsToFormat(AEAudioFormat &format, AudioSettings &settings, int *mode)
1390 {
1391   int oldMode = m_mode;
1392   if (mode)
1393     *mode = MODE_PCM;
1394
1395   // raw pass through
1396   if (AE_IS_RAW(format.m_dataFormat))
1397   {
1398     if ((format.m_dataFormat == AE_FMT_AC3 && !settings.ac3passthrough) ||
1399         (format.m_dataFormat == AE_FMT_EAC3 && !settings.eac3passthrough) ||
1400         (format.m_dataFormat == AE_FMT_TRUEHD && !settings.truehdpassthrough) ||
1401         (format.m_dataFormat == AE_FMT_DTS && !settings.dtspassthrough) ||
1402         (format.m_dataFormat == AE_FMT_DTSHD && !settings.dtshdpassthrough))
1403     {
1404       CLog::Log(LOGERROR, "CActiveAE::ApplySettingsToFormat - input audio format is wrong");
1405     }
1406     if (mode)
1407       *mode = MODE_RAW;
1408   }
1409   // transcode
1410   else if (settings.channels <= AE_CH_LAYOUT_2_0 && // no multichannel pcm
1411            settings.passthrough &&
1412            settings.ac3passthrough &&
1413            settings.ac3transcode &&
1414            !m_streams.empty() &&
1415            (format.m_channelLayout.Count() > 2 || settings.stereoupmix))
1416   {
1417     format.m_dataFormat = AE_FMT_AC3;
1418     format.m_sampleRate = 48000;
1419     format.m_channelLayout = AE_CH_LAYOUT_2_0;
1420     if (mode)
1421       *mode = MODE_TRANSCODE;
1422   }
1423   else
1424   {
1425     format.m_dataFormat = AE_FMT_FLOAT;
1426     // consider user channel layout for those cases
1427     // 1. input stream is multichannel
1428     // 2. stereo upmix is selected
1429     // 3. fixed mode
1430     if ((format.m_channelLayout.Count() > 2) ||
1431          settings.stereoupmix ||
1432          (settings.config == AE_CONFIG_FIXED))
1433     {
1434       CAEChannelInfo stdLayout;
1435       switch (settings.channels)
1436       {
1437         default:
1438         case  0: stdLayout = AE_CH_LAYOUT_2_0; break;
1439         case  1: stdLayout = AE_CH_LAYOUT_2_0; break;
1440         case  2: stdLayout = AE_CH_LAYOUT_2_1; break;
1441         case  3: stdLayout = AE_CH_LAYOUT_3_0; break;
1442         case  4: stdLayout = AE_CH_LAYOUT_3_1; break;
1443         case  5: stdLayout = AE_CH_LAYOUT_4_0; break;
1444         case  6: stdLayout = AE_CH_LAYOUT_4_1; break;
1445         case  7: stdLayout = AE_CH_LAYOUT_5_0; break;
1446         case  8: stdLayout = AE_CH_LAYOUT_5_1; break;
1447         case  9: stdLayout = AE_CH_LAYOUT_7_0; break;
1448         case 10: stdLayout = AE_CH_LAYOUT_7_1; break;
1449       }
1450
1451       if (m_settings.config == AE_CONFIG_FIXED || (settings.stereoupmix && format.m_channelLayout.Count() <= 2))
1452         format.m_channelLayout = stdLayout;
1453       else if (m_extKeepConfig && (settings.config == AE_CONFIG_AUTO) && (oldMode != MODE_RAW))
1454         format.m_channelLayout = m_internalFormat.m_channelLayout;
1455       else
1456         format.m_channelLayout.ResolveChannels(stdLayout);
1457     }
1458     // don't change from multi to stereo in AUTO mode
1459     else if ((settings.config == AE_CONFIG_AUTO) &&
1460               m_stats.GetWaterLevel() > 0 && m_internalFormat.m_channelLayout.Count() > 2)
1461     {
1462       format.m_channelLayout = m_internalFormat.m_channelLayout;
1463     }
1464
1465     if (m_sink.GetDeviceType(m_settings.device) == AE_DEVTYPE_IEC958)
1466     {
1467       if (format.m_sampleRate > m_settings.samplerate)
1468       {
1469         format.m_sampleRate = m_settings.samplerate;
1470         CLog::Log(LOGINFO, "CActiveAE::ApplySettings - limit samplerate for SPDIF to %d", format.m_sampleRate);
1471       }
1472       format.m_channelLayout = AE_CH_LAYOUT_2_0;
1473     }
1474
1475     if (m_settings.config == AE_CONFIG_FIXED)
1476     {
1477       format.m_sampleRate = m_settings.samplerate;
1478       CLog::Log(LOGINFO, "CActiveAE::ApplySettings - Forcing samplerate to %d", format.m_sampleRate);
1479     }
1480
1481     // sinks may not support mono
1482     if (format.m_channelLayout.Count() == 1)
1483     {
1484       format.m_channelLayout = AE_CH_LAYOUT_2_0;
1485     }
1486   }
1487 }
1488
1489 bool CActiveAE::NeedReconfigureBuffers()
1490 {
1491   AEAudioFormat newFormat = GetInputFormat();
1492   ApplySettingsToFormat(newFormat, m_settings);
1493
1494   if (newFormat.m_dataFormat != m_sinkRequestFormat.m_dataFormat ||
1495       newFormat.m_channelLayout != m_sinkRequestFormat.m_channelLayout ||
1496       newFormat.m_sampleRate != m_sinkRequestFormat.m_sampleRate)
1497     return true;
1498
1499   return false;
1500 }
1501
1502 bool CActiveAE::NeedReconfigureSink()
1503 {
1504   AEAudioFormat newFormat = GetInputFormat();
1505   ApplySettingsToFormat(newFormat, m_settings);
1506
1507   std::string device = AE_IS_RAW(newFormat.m_dataFormat) ? m_settings.passthoughdevice : m_settings.device;
1508   std::string driver;
1509   CAESinkFactory::ParseDevice(device, driver);
1510
1511   if (!CompareFormat(newFormat, m_sinkFormat) ||
1512       m_currDevice.compare(device) != 0 ||
1513       m_settings.driver.compare(driver) != 0)
1514     return true;
1515
1516   return false;
1517 }
1518
1519 bool CActiveAE::InitSink()
1520 {
1521   SinkConfig config;
1522   config.format = m_sinkRequestFormat;
1523   config.stats = &m_stats;
1524   config.device = AE_IS_RAW(m_sinkRequestFormat.m_dataFormat) ? &m_settings.passthoughdevice :
1525                                                                 &m_settings.device;
1526
1527   // send message to sink
1528   Message *reply;
1529   if (m_sink.m_controlPort.SendOutMessageSync(CSinkControlProtocol::CONFIGURE,
1530                                                  &reply,
1531                                                  5000,
1532                                                  &config, sizeof(config)))
1533   {
1534     bool success = reply->signal == CSinkControlProtocol::ACC;
1535     if (!success)
1536     {
1537       reply->Release();
1538       CLog::Log(LOGERROR, "ActiveAE::%s - returned error", __FUNCTION__);
1539       m_extError = true;
1540       return false;
1541     }
1542     SinkReply *data;
1543     data = (SinkReply*)reply->data;
1544     if (data)
1545     {
1546       m_sinkFormat = data->format;
1547       m_sinkHasVolume = data->hasVolume;
1548       m_stats.SetSinkCacheTotal(data->cacheTotal);
1549       m_stats.SetSinkLatency(data->latency);
1550     }
1551     reply->Release();
1552   }
1553   else
1554   {
1555     CLog::Log(LOGERROR, "ActiveAE::%s - failed to init", __FUNCTION__);
1556     m_stats.SetSinkCacheTotal(0);
1557     m_stats.SetSinkLatency(0);
1558     m_extError = true;
1559     return false;
1560   }
1561
1562   m_inMsgEvent.Reset();
1563   return true;
1564 }
1565
1566 void CActiveAE::DrainSink()
1567 {
1568   // send message to sink
1569   Message *reply;
1570   if (m_sink.m_dataPort.SendOutMessageSync(CSinkDataProtocol::DRAIN,
1571                                                  &reply,
1572                                                  2000))
1573   {
1574     bool success = reply->signal == CSinkDataProtocol::ACC;
1575     if (!success)
1576     {
1577       reply->Release();
1578       CLog::Log(LOGERROR, "ActiveAE::%s - returned error on drain", __FUNCTION__);
1579       m_extError = true;
1580       return;
1581     }
1582     reply->Release();
1583   }
1584   else
1585   {
1586     CLog::Log(LOGERROR, "ActiveAE::%s - failed to drain", __FUNCTION__);
1587     m_extError = true;
1588     return;
1589   }
1590 }
1591
1592 void CActiveAE::UnconfigureSink()
1593 {
1594   // send message to sink
1595   Message *reply;
1596   if (m_sink.m_controlPort.SendOutMessageSync(CSinkControlProtocol::UNCONFIGURE,
1597                                                  &reply,
1598                                                  2000))
1599   {
1600     bool success = reply->signal == CSinkControlProtocol::ACC;
1601     if (!success)
1602     {
1603       CLog::Log(LOGERROR, "ActiveAE::%s - returned error", __FUNCTION__);
1604       m_extError = true;
1605     }
1606     reply->Release();
1607   }
1608   else
1609   {
1610     CLog::Log(LOGERROR, "ActiveAE::%s - failed to unconfigure", __FUNCTION__);
1611     m_extError = true;
1612   }
1613
1614   // make sure we open sink on next configure
1615   m_currDevice = "";
1616
1617   m_inMsgEvent.Reset();
1618 }
1619
1620
1621 bool CActiveAE::RunStages()
1622 {
1623   bool busy = false;
1624
1625   // serve input streams
1626   std::list<CActiveAEStream*>::iterator it;
1627   for (it = m_streams.begin(); it != m_streams.end(); ++it)
1628   {
1629     if ((*it)->m_resampleBuffers && !(*it)->m_paused)
1630       busy = (*it)->m_resampleBuffers->ResampleBuffers();
1631     else if ((*it)->m_resampleBuffers && 
1632             ((*it)->m_resampleBuffers->m_inputSamples.size() > (*it)->m_resampleBuffers->m_allSamples.size() * 0.5))
1633     {
1634       CSingleLock lock((*it)->m_streamLock);
1635       (*it)->m_streamIsBuffering = false;
1636     }
1637
1638     // provide buffers to stream
1639     float time = m_stats.GetCacheTime((*it));
1640     CSampleBuffer *buffer;
1641     if (!(*it)->m_drain)
1642     {
1643       while (time < MAX_CACHE_LEVEL && !(*it)->m_inputBuffers->m_freeSamples.empty())
1644       {
1645         buffer = (*it)->m_inputBuffers->GetFreeBuffer();
1646         (*it)->m_processingSamples.push_back(buffer);
1647         (*it)->m_streamPort->SendInMessage(CActiveAEDataProtocol::STREAMBUFFER, &buffer, sizeof(CSampleBuffer*));
1648         (*it)->IncFreeBuffers();
1649         time += (float)buffer->pkt->max_nb_samples / buffer->pkt->config.sample_rate;
1650       }
1651     }
1652     else
1653     {
1654       if ((*it)->m_resampleBuffers->m_inputSamples.empty() &&
1655           (*it)->m_resampleBuffers->m_outputSamples.empty() &&
1656           (*it)->m_processingSamples.empty())
1657       {
1658         (*it)->m_streamPort->SendInMessage(CActiveAEDataProtocol::STREAMDRAINED);
1659         (*it)->m_drain = false;
1660         (*it)->m_resampleBuffers->m_drain = false;
1661         (*it)->m_started = false;
1662
1663         // set variables being polled via stream interface
1664         CSingleLock lock((*it)->m_streamLock);
1665         if ((*it)->m_streamSlave)
1666         {
1667           CActiveAEStream *slave = (CActiveAEStream*)((*it)->m_streamSlave);
1668           slave->m_paused = false;
1669
1670           // TODO: find better solution for this
1671           // gapless bites audiophile
1672           if (m_settings.config == AE_CONFIG_MATCH)
1673             Configure(&slave->m_format);
1674
1675           (*it)->m_streamSlave = NULL;
1676         }
1677         (*it)->m_streamDrained = true;
1678         (*it)->m_streamDraining = false;
1679         (*it)->m_streamFading = false;
1680       }
1681     }
1682   }
1683
1684   if (m_stats.GetWaterLevel() < MAX_WATER_LEVEL &&
1685      (m_mode != MODE_TRANSCODE || (m_encoderBuffers && !m_encoderBuffers->m_freeSamples.empty())))
1686   {
1687     // mix streams and sounds sounds
1688     if (m_mode != MODE_RAW)
1689     {
1690       CSampleBuffer *out = NULL;
1691       if (!m_sounds_playing.empty() && m_streams.empty())
1692       {
1693         if (m_silenceBuffers && !m_silenceBuffers->m_freeSamples.empty())
1694         {
1695           out = m_silenceBuffers->GetFreeBuffer();
1696           for (int i=0; i<out->pkt->planes; i++)
1697           {
1698             memset(out->pkt->data[i], 0, out->pkt->linesize);
1699           }
1700           out->pkt->nb_samples = out->pkt->max_nb_samples;
1701         }
1702       }
1703
1704       // mix streams
1705       std::list<CActiveAEStream*>::iterator it;
1706
1707       // if we deal with more than a single stream, all streams
1708       // must provide samples for mixing
1709       bool allStreamsReady = true;
1710       for (it = m_streams.begin(); it != m_streams.end(); ++it)
1711       {
1712         if ((*it)->m_paused || !(*it)->m_started || !(*it)->m_resampleBuffers)
1713           continue;
1714
1715         if ((*it)->m_resampleBuffers->m_outputSamples.empty())
1716           allStreamsReady = false;
1717       }
1718
1719       bool needClamp = false;
1720       for (it = m_streams.begin(); it != m_streams.end() && allStreamsReady; ++it)
1721       {
1722         if ((*it)->m_paused || !(*it)->m_resampleBuffers)
1723           continue;
1724
1725         if (!(*it)->m_resampleBuffers->m_outputSamples.empty())
1726         {
1727           (*it)->m_started = true;
1728
1729           if (!out)
1730           {
1731             out = (*it)->m_resampleBuffers->m_outputSamples.front();
1732             (*it)->m_resampleBuffers->m_outputSamples.pop_front();
1733
1734             int nb_floats = out->pkt->nb_samples * out->pkt->config.channels / out->pkt->planes;
1735             int nb_loops = 1;
1736             float fadingStep = 0.0f;
1737
1738             // fading
1739             if ((*it)->m_fadingSamples == -1)
1740             {
1741               (*it)->m_fadingSamples = m_internalFormat.m_sampleRate * (float)(*it)->m_fadingTime / 1000.0f;
1742               (*it)->m_volume = (*it)->m_fadingBase;
1743             }
1744             if ((*it)->m_fadingSamples > 0)
1745             {
1746               nb_floats = out->pkt->config.channels / out->pkt->planes;
1747               nb_loops = out->pkt->nb_samples;
1748               float delta = (*it)->m_fadingTarget - (*it)->m_fadingBase;
1749               int samples = m_internalFormat.m_sampleRate * (float)(*it)->m_fadingTime / 1000.0f;
1750               fadingStep = delta / samples;
1751             }
1752
1753             // for stream amplification, 
1754             // turned off downmix normalization,
1755             // or if sink format is float (in order to prevent from clipping)
1756             // we need to run on a per sample basis
1757             if ((*it)->m_amplify != 1.0 || !(*it)->m_resampleBuffers->m_normalize || (m_sinkFormat.m_dataFormat == AE_FMT_FLOAT))
1758             {
1759               nb_floats = out->pkt->config.channels / out->pkt->planes;
1760               nb_loops = out->pkt->nb_samples;
1761             }
1762
1763             for(int i=0; i<nb_loops; i++)
1764             {
1765               if ((*it)->m_fadingSamples > 0)
1766               {
1767                 (*it)->m_volume += fadingStep;
1768                 (*it)->m_fadingSamples--;
1769
1770                 if ((*it)->m_fadingSamples == 0)
1771                 {
1772                   // set variables being polled via stream interface
1773                   CSingleLock lock((*it)->m_streamLock);
1774                   (*it)->m_streamFading = false;
1775                 }
1776               }
1777
1778               // volume for stream
1779               float volume = (*it)->m_volume * (*it)->m_rgain;
1780               if(nb_loops > 1)
1781                 volume *= (*it)->m_limiter.Run((float**)out->pkt->data, out->pkt->config.channels, i*nb_floats, out->pkt->planes > 1);
1782
1783               for(int j=0; j<out->pkt->planes; j++)
1784               {
1785 #ifdef __SSE__
1786                 CAEUtil::SSEMulArray((float*)out->pkt->data[j]+i*nb_floats, volume, nb_floats);
1787 #else
1788                 float* fbuffer = (float*) out->pkt->data[j]+i*nb_floats;
1789                 for (int k = 0; k < nb_floats; ++k)
1790                 {
1791                   fbuffer[k] *= volume;
1792                 }
1793 #endif
1794               }
1795             }
1796           }
1797           else
1798           {
1799             CSampleBuffer *mix = NULL;
1800             mix = (*it)->m_resampleBuffers->m_outputSamples.front();
1801             (*it)->m_resampleBuffers->m_outputSamples.pop_front();
1802
1803             int nb_floats = mix->pkt->nb_samples * mix->pkt->config.channels / mix->pkt->planes;
1804             int nb_loops = 1;
1805             float fadingStep = 0.0f;
1806
1807             // fading
1808             if ((*it)->m_fadingSamples == -1)
1809             {
1810               (*it)->m_fadingSamples = m_internalFormat.m_sampleRate * (float)(*it)->m_fadingTime / 1000.0f;
1811               (*it)->m_volume = (*it)->m_fadingBase;
1812             }
1813             if ((*it)->m_fadingSamples > 0)
1814             {
1815               nb_floats = mix->pkt->config.channels / mix->pkt->planes;
1816               nb_loops = mix->pkt->nb_samples;
1817               float delta = (*it)->m_fadingTarget - (*it)->m_fadingBase;
1818               int samples = m_internalFormat.m_sampleRate * (float)(*it)->m_fadingTime / 1000.0f;
1819               fadingStep = delta / samples;
1820             }
1821
1822             // for streams amplification of turned off downmix normalization
1823             // we need to run on a per sample basis
1824             if ((*it)->m_amplify != 1.0 || !(*it)->m_resampleBuffers->m_normalize)
1825             {
1826               nb_floats = out->pkt->config.channels / out->pkt->planes;
1827               nb_loops = out->pkt->nb_samples;
1828             }
1829
1830             for(int i=0; i<nb_loops; i++)
1831             {
1832               if ((*it)->m_fadingSamples > 0)
1833               {
1834                 (*it)->m_volume += fadingStep;
1835                 (*it)->m_fadingSamples--;
1836
1837                 if ((*it)->m_fadingSamples == 0)
1838                 {
1839                   // set variables being polled via stream interface
1840                   CSingleLock lock((*it)->m_streamLock);
1841                   (*it)->m_streamFading = false;
1842                 }
1843               }
1844
1845               // volume for stream
1846               float volume = (*it)->m_volume * (*it)->m_rgain;
1847               if(nb_loops > 1)
1848                 volume *= (*it)->m_limiter.Run((float**)mix->pkt->data, mix->pkt->config.channels, i*nb_floats, mix->pkt->planes > 1);
1849
1850               for(int j=0; j<out->pkt->planes && j<mix->pkt->planes; j++)
1851               {
1852                 float *dst = (float*)out->pkt->data[j]+i*nb_floats;
1853                 float *src = (float*)mix->pkt->data[j]+i*nb_floats;
1854 #ifdef __SSE__
1855                 CAEUtil::SSEMulAddArray(dst, src, volume, nb_floats);
1856                 for (int k = 0; k < nb_floats; ++k)
1857                 {
1858                   if (fabs(dst[k]) > 1.0f)
1859                   {
1860                     needClamp = true;
1861                     break;
1862                   }
1863                 }
1864 #else
1865                 for (int k = 0; k < nb_floats; ++k)
1866                 {
1867                   dst[k] += src[k] * volume;
1868                   if (fabs(dst[k]) > 1.0f)
1869                     needClamp = true;
1870                 }
1871 #endif
1872               }
1873             }
1874             mix->Return();
1875           }
1876           busy = true;
1877         }
1878       }// for
1879
1880       // finally clamp samples
1881       if(out && needClamp)
1882       {
1883         int nb_floats = out->pkt->nb_samples * out->pkt->config.channels / out->pkt->planes;
1884         for(int i=0; i<out->pkt->planes; i++)
1885         {
1886           CAEUtil::ClampArray((float*)out->pkt->data[i], nb_floats);
1887         }
1888       }
1889
1890       // process output buffer, gui sounds, encode, viz
1891       if (out)
1892       {
1893         // viz
1894         {
1895           CSingleLock lock(m_vizLock);
1896           if (m_audioCallback && m_vizBuffers && !m_streams.empty())
1897           {
1898             if (!m_vizInitialized)
1899             {
1900               m_audioCallback->OnInitialize(2, m_vizBuffers->m_format.m_sampleRate, 32);
1901               m_vizInitialized = true;
1902             }
1903
1904             if (!m_vizBuffersInput->m_freeSamples.empty())
1905             {
1906               // copy the samples into the viz input buffer
1907               CSampleBuffer *viz = m_vizBuffersInput->GetFreeBuffer();
1908               int samples = std::min(512, out->pkt->nb_samples);
1909               int bytes = samples * out->pkt->config.channels / out->pkt->planes * out->pkt->bytes_per_sample;
1910               for(int i= 0; i < out->pkt->planes; i++)
1911               {
1912                 memcpy(viz->pkt->data[i], out->pkt->data[i], bytes);
1913               }
1914               viz->pkt->nb_samples = samples;
1915               m_vizBuffers->m_inputSamples.push_back(viz);
1916             }
1917             else
1918               CLog::Log(LOGWARNING,"ActiveAE::%s - viz ran out of free buffers", __FUNCTION__);
1919             unsigned int now = XbmcThreads::SystemClockMillis();
1920             unsigned int timestamp = now + m_stats.GetDelay() * 1000;
1921             busy |= m_vizBuffers->ResampleBuffers(timestamp);
1922             while(!m_vizBuffers->m_outputSamples.empty())
1923             {
1924               CSampleBuffer *buf = m_vizBuffers->m_outputSamples.front();
1925               if ((now - buf->timestamp) & 0x80000000)
1926                 break;
1927               else
1928               {
1929                 int samples;
1930                 samples = std::min(512, buf->pkt->nb_samples);
1931                 m_audioCallback->OnAudioData((float*)(buf->pkt->data[0]), samples);
1932                 buf->Return();
1933                 m_vizBuffers->m_outputSamples.pop_front();
1934               }
1935             }
1936           }
1937           else if (m_vizBuffers)
1938             m_vizBuffers->Flush();
1939         }
1940
1941         // mix gui sounds
1942         MixSounds(*(out->pkt));
1943         if (!m_sinkHasVolume || m_muted)
1944           Deamplify(*(out->pkt));
1945
1946         if (m_mode == MODE_TRANSCODE && m_encoder)
1947         {
1948           CSampleBuffer *buf = m_encoderBuffers->GetFreeBuffer();
1949           m_encoder->Encode(out->pkt->data[0], out->pkt->planes*out->pkt->linesize,
1950                             buf->pkt->data[0], buf->pkt->planes*buf->pkt->linesize);
1951           buf->pkt->nb_samples = buf->pkt->max_nb_samples;
1952           out->Return();
1953           out = buf;
1954         }
1955         busy = true;
1956       }
1957
1958       // update stats
1959       if(out)
1960       {
1961         m_stats.AddSamples(out->pkt->nb_samples, m_streams);
1962         m_sinkBuffers->m_inputSamples.push_back(out);
1963       }
1964     }
1965     // pass through
1966     else
1967     {
1968       std::list<CActiveAEStream*>::iterator it;
1969       CSampleBuffer *buffer;
1970       for (it = m_streams.begin(); it != m_streams.end(); ++it)
1971       {
1972         if (!(*it)->m_resampleBuffers->m_outputSamples.empty())
1973         {
1974           buffer =  (*it)->m_resampleBuffers->m_outputSamples.front();
1975           (*it)->m_resampleBuffers->m_outputSamples.pop_front();
1976           m_stats.AddSamples(buffer->pkt->nb_samples, m_streams);
1977           m_sinkBuffers->m_inputSamples.push_back(buffer);
1978         }
1979       }
1980     }
1981
1982     // serve sink buffers
1983     busy = m_sinkBuffers->ResampleBuffers();
1984     while(!m_sinkBuffers->m_outputSamples.empty())
1985     {
1986       CSampleBuffer *out = NULL;
1987       out = m_sinkBuffers->m_outputSamples.front();
1988       m_sinkBuffers->m_outputSamples.pop_front();
1989       m_sink.m_dataPort.SendOutMessage(CSinkDataProtocol::SAMPLE,
1990           &out, sizeof(CSampleBuffer*));
1991       busy = true;
1992     }
1993   }
1994
1995   return busy;
1996 }
1997
1998 bool CActiveAE::HasWork()
1999 {
2000   if (!m_sounds_playing.empty())
2001     return true;
2002   if (!m_sinkBuffers->m_inputSamples.empty())
2003     return true;
2004   if (!m_sinkBuffers->m_outputSamples.empty())
2005     return true;
2006
2007   std::list<CActiveAEStream*>::iterator it;
2008   for (it = m_streams.begin(); it != m_streams.end(); ++it)
2009   {
2010     if (!(*it)->m_resampleBuffers->m_inputSamples.empty())
2011       return true;
2012     if (!(*it)->m_resampleBuffers->m_outputSamples.empty())
2013       return true;
2014     if (!(*it)->m_processingSamples.empty())
2015       return true;
2016   }
2017
2018   return false;
2019 }
2020
2021 void CActiveAE::MixSounds(CSoundPacket &dstSample)
2022 {
2023   if (m_sounds_playing.empty())
2024     return;
2025
2026   float volume;
2027   float *out;
2028   float *sample_buffer;
2029   int max_samples = dstSample.nb_samples;
2030
2031   std::list<SoundState>::iterator it;
2032   for (it = m_sounds_playing.begin(); it != m_sounds_playing.end(); )
2033   {
2034     if (!it->sound->IsConverted())
2035       ResampleSound(it->sound);
2036     int available_samples = it->sound->GetSound(false)->nb_samples - it->samples_played;
2037     int mix_samples = std::min(max_samples, available_samples);
2038     int start = it->samples_played *
2039                 m_dllAvUtil.av_get_bytes_per_sample(it->sound->GetSound(false)->config.fmt) *
2040                 it->sound->GetSound(false)->config.channels /
2041                 it->sound->GetSound(false)->planes;
2042
2043     for(int j=0; j<dstSample.planes; j++)
2044     {
2045       volume = it->sound->GetVolume();
2046       out = (float*)dstSample.data[j];
2047       sample_buffer = (float*)(it->sound->GetSound(false)->data[j]+start);
2048       int nb_floats = mix_samples * dstSample.config.channels / dstSample.planes;
2049 #ifdef __SSE__
2050       CAEUtil::SSEMulAddArray(out, sample_buffer, volume, nb_floats);
2051 #else
2052       for (int k = 0; k < nb_floats; ++k)
2053         *out++ += *sample_buffer++ * volume;
2054 #endif
2055     }
2056
2057     it->samples_played += mix_samples;
2058
2059     // no more frames, so remove it from the list
2060     if (it->samples_played >= it->sound->GetSound(false)->nb_samples)
2061     {
2062       it = m_sounds_playing.erase(it);
2063       continue;
2064     }
2065     ++it;
2066   }
2067 }
2068
2069 void CActiveAE::Deamplify(CSoundPacket &dstSample)
2070 {
2071   if (m_volume < 1.0 || m_muted)
2072   {
2073     float *buffer;
2074     int nb_floats = dstSample.nb_samples * dstSample.config.channels / dstSample.planes;
2075     float volume = m_muted ? 0.0f : m_volume;
2076
2077     for(int j=0; j<dstSample.planes; j++)
2078     {
2079       buffer = (float*)dstSample.data[j];
2080 #ifdef __SSE__
2081       CAEUtil::SSEMulArray(buffer, volume, nb_floats);
2082 #else
2083       float *fbuffer = buffer;
2084       for (int i = 0; i < nb_floats; i++)
2085         *fbuffer++ *= volume;
2086 #endif
2087     }
2088   }
2089 }
2090
2091 //-----------------------------------------------------------------------------
2092 // Configuration
2093 //-----------------------------------------------------------------------------
2094
2095 void CActiveAE::LoadSettings()
2096 {
2097   m_settings.device = CSettings::Get().GetString("audiooutput.audiodevice");
2098   m_settings.passthoughdevice = CSettings::Get().GetString("audiooutput.passthroughdevice");
2099
2100   m_settings.config = CSettings::Get().GetInt("audiooutput.config");
2101   m_settings.channels = (m_sink.GetDeviceType(m_settings.device) == AE_DEVTYPE_IEC958) ? AE_CH_LAYOUT_2_0 : CSettings::Get().GetInt("audiooutput.channels");
2102   m_settings.samplerate = CSettings::Get().GetInt("audiooutput.samplerate");
2103
2104   m_settings.stereoupmix = IsSettingVisible("audiooutput.stereoupmix") ? CSettings::Get().GetBool("audiooutput.stereoupmix") : false;
2105   m_settings.normalizelevels = CSettings::Get().GetBool("audiooutput.normalizelevels");
2106   m_settings.guisoundmode = CSettings::Get().GetInt("audiooutput.guisoundmode");
2107
2108   m_settings.passthrough = m_settings.config == AE_CONFIG_FIXED ? false : CSettings::Get().GetBool("audiooutput.passthrough");
2109   if (!m_sink.HasPassthroughDevice())
2110     m_settings.passthrough = false;
2111   m_settings.ac3passthrough = CSettings::Get().GetBool("audiooutput.ac3passthrough");
2112   m_settings.ac3transcode = CSettings::Get().GetBool("audiooutput.ac3transcode");
2113   m_settings.eac3passthrough = CSettings::Get().GetBool("audiooutput.eac3passthrough");
2114   m_settings.truehdpassthrough = CSettings::Get().GetBool("audiooutput.truehdpassthrough");
2115   m_settings.dtspassthrough = CSettings::Get().GetBool("audiooutput.dtspassthrough");
2116   m_settings.dtshdpassthrough = CSettings::Get().GetBool("audiooutput.dtshdpassthrough");
2117
2118   m_settings.resampleQuality = static_cast<AEQuality>(CSettings::Get().GetInt("audiooutput.processquality"));
2119 }
2120
2121 bool CActiveAE::Initialize()
2122 {
2123   if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllAvFormat.Load())
2124   {
2125     CLog::Log(LOGERROR,"CActiveAE::Initialize - failed to load ffmpeg libraries");
2126     return false;
2127   }
2128   m_dllAvFormat.av_register_all();
2129
2130   Create();
2131   Message *reply;
2132   if (m_controlPort.SendOutMessageSync(CActiveAEControlProtocol::INIT,
2133                                                  &reply,
2134                                                  10000))
2135   {
2136     bool success = reply->signal == CActiveAEControlProtocol::ACC;
2137     reply->Release();
2138     if (!success)
2139     {
2140       CLog::Log(LOGERROR, "ActiveAE::%s - returned error", __FUNCTION__);
2141       Dispose();
2142       return false;
2143     }
2144   }
2145   else
2146   {
2147     CLog::Log(LOGERROR, "ActiveAE::%s - failed to init", __FUNCTION__);
2148     Dispose();
2149     return false;
2150   }
2151
2152   // hook into windowing for receiving display reset events
2153 #if defined(HAS_GLX) || defined(TARGET_DARWIN_OSX)
2154   g_Windowing.Register(this);
2155 #endif
2156
2157   m_inMsgEvent.Reset();
2158   return true;
2159 }
2160
2161 void CActiveAE::EnumerateOutputDevices(AEDeviceList &devices, bool passthrough)
2162 {
2163   m_sink.EnumerateOutputDevices(devices, passthrough);
2164 }
2165
2166 std::string CActiveAE::GetDefaultDevice(bool passthrough)
2167 {
2168   return m_sink.GetDefaultDevice(passthrough);
2169 }
2170
2171 void CActiveAE::OnSettingsChange(const std::string& setting)
2172 {
2173   if (setting == "audiooutput.passthroughdevice" ||
2174       setting == "audiooutput.audiodevice"       ||
2175       setting == "audiooutput.config"            ||
2176       setting == "audiooutput.ac3passthrough"    ||
2177       setting == "audiooutput.ac3transcode"      ||
2178       setting == "audiooutput.eac3passthrough"   ||
2179       setting == "audiooutput.dtspassthrough"    ||
2180       setting == "audiooutput.truehdpassthrough" ||
2181       setting == "audiooutput.dtshdpassthrough"  ||
2182       setting == "audiooutput.channels"          ||
2183       setting == "audiooutput.stereoupmix"       ||
2184       setting == "audiooutput.streamsilence"     ||
2185       setting == "audiooutput.processquality"    ||
2186       setting == "audiooutput.passthrough"       ||
2187       setting == "audiooutput.samplerate"        ||
2188       setting == "audiooutput.normalizelevels"   ||
2189       setting == "audiooutput.guisoundmode")
2190   {
2191     m_controlPort.SendOutMessage(CActiveAEControlProtocol::RECONFIGURE);
2192   }
2193 }
2194
2195 bool CActiveAE::SupportsRaw(AEDataFormat format, int samplerate)
2196 {
2197   if (!m_sink.SupportsFormat(CSettings::Get().GetString("audiooutput.passthroughdevice"), format, samplerate))
2198     return false;
2199
2200   return true;
2201 }
2202
2203 bool CActiveAE::SupportsSilenceTimeout()
2204 {
2205   return true;
2206 }
2207
2208 bool CActiveAE::SupportsQualityLevel(enum AEQuality level)
2209 {
2210   if (level == AE_QUALITY_LOW || level == AE_QUALITY_MID || level == AE_QUALITY_HIGH)
2211     return true;
2212
2213   return false;
2214 }
2215
2216 bool CActiveAE::IsSettingVisible(const std::string &settingId)
2217 {
2218   if (settingId == "audiooutput.samplerate")
2219   {
2220     if (m_sink.GetDeviceType(CSettings::Get().GetString("audiooutput.audiodevice")) == AE_DEVTYPE_IEC958)
2221       return true;
2222     if (CSettings::Get().GetInt("audiooutput.config") == AE_CONFIG_FIXED)
2223       return true;
2224   }
2225   else if (settingId == "audiooutput.channels")
2226   {
2227     if (m_sink.GetDeviceType(CSettings::Get().GetString("audiooutput.audiodevice")) != AE_DEVTYPE_IEC958)
2228       return true;
2229   }
2230   else if (settingId == "audiooutput.passthrough")
2231   {
2232     if (m_sink.HasPassthroughDevice() && CSettings::Get().GetInt("audiooutput.config") != AE_CONFIG_FIXED)
2233       return true;
2234   }
2235   else if (settingId == "audiooutput.truehdpassthrough")
2236   {
2237     if (m_sink.SupportsFormat(CSettings::Get().GetString("audiooutput.passthroughdevice"), AE_FMT_TRUEHD, 192000) &&
2238         CSettings::Get().GetInt("audiooutput.config") != AE_CONFIG_FIXED)
2239       return true;
2240   }
2241   else if (settingId == "audiooutput.dtshdpassthrough")
2242   {
2243     if (m_sink.SupportsFormat(CSettings::Get().GetString("audiooutput.passthroughdevice"), AE_FMT_DTSHD, 192000) &&
2244         CSettings::Get().GetInt("audiooutput.config") != AE_CONFIG_FIXED)
2245       return true;
2246   }
2247   else if (settingId == "audiooutput.eac3passthrough")
2248   {
2249     if (m_sink.SupportsFormat(CSettings::Get().GetString("audiooutput.passthroughdevice"), AE_FMT_EAC3, 192000) &&
2250         CSettings::Get().GetInt("audiooutput.config") != AE_CONFIG_FIXED)
2251       return true;
2252   }
2253   else if (settingId == "audiooutput.stereoupmix")
2254   {
2255     if (m_sink.HasPassthroughDevice() ||
2256         CSettings::Get().GetInt("audiooutput.channels") > AE_CH_LAYOUT_2_0)
2257     return true;
2258   }
2259   else if (settingId == "audiooutput.ac3transcode")
2260   {
2261     if (m_sink.HasPassthroughDevice() &&
2262         CSettings::Get().GetBool("audiooutput.ac3passthrough") &&
2263         CSettings::Get().GetInt("audiooutput.config") != AE_CONFIG_FIXED &&
2264         (CSettings::Get().GetInt("audiooutput.channels") <= AE_CH_LAYOUT_2_0 || m_sink.GetDeviceType(CSettings::Get().GetString("audiooutput.audiodevice")) == AE_DEVTYPE_IEC958))
2265       return true;
2266   }
2267   return false;
2268 }
2269
2270 void CActiveAE::Shutdown()
2271 {
2272   Dispose();
2273 }
2274
2275 bool CActiveAE::Suspend()
2276 {
2277   return m_controlPort.SendOutMessage(CActiveAEControlProtocol::SUSPEND);
2278 }
2279
2280 bool CActiveAE::Resume()
2281 {
2282   Message *reply;
2283   if (m_controlPort.SendOutMessageSync(CActiveAEControlProtocol::INIT,
2284                                                  &reply,
2285                                                  5000))
2286   {
2287     bool success = reply->signal == CActiveAEControlProtocol::ACC;
2288     reply->Release();
2289     if (!success)
2290     {
2291       CLog::Log(LOGERROR, "ActiveAE::%s - returned error", __FUNCTION__);
2292       return false;
2293     }
2294   }
2295   else
2296   {
2297     CLog::Log(LOGERROR, "ActiveAE::%s - failed to init", __FUNCTION__);
2298     return false;
2299   }
2300
2301   m_inMsgEvent.Reset();
2302   return true;
2303 }
2304
2305 bool CActiveAE::IsSuspended()
2306 {
2307   return m_stats.IsSuspended();
2308 }
2309
2310 float CActiveAE::GetVolume()
2311 {
2312   return m_aeVolume;
2313 }
2314
2315 void CActiveAE::SetVolume(const float volume)
2316 {
2317   m_aeVolume = std::max( 0.0f, std::min(1.0f, volume));
2318   m_controlPort.SendOutMessage(CActiveAEControlProtocol::VOLUME, &m_aeVolume, sizeof(float));
2319 }
2320
2321 void CActiveAE::SetMute(const bool enabled)
2322 {
2323   m_aeMuted = enabled;
2324   m_controlPort.SendOutMessage(CActiveAEControlProtocol::MUTE, &m_aeMuted, sizeof(bool));
2325 }
2326
2327 bool CActiveAE::IsMuted()
2328 {
2329   return m_aeMuted;
2330 }
2331
2332 void CActiveAE::SetSoundMode(const int mode)
2333 {
2334   return;
2335 }
2336
2337 void CActiveAE::KeepConfiguration(unsigned int millis)
2338 {
2339   unsigned int timeMs = millis;
2340   m_controlPort.SendOutMessage(CActiveAEControlProtocol::KEEPCONFIG, &timeMs, sizeof(unsigned int));
2341 }
2342
2343 void CActiveAE::DeviceChange()
2344 {
2345   m_controlPort.SendOutMessage(CActiveAEControlProtocol::DEVICECHANGE);
2346 }
2347
2348 void CActiveAE::OnLostDevice()
2349 {
2350   Message *reply;
2351   if (m_controlPort.SendOutMessageSync(CActiveAEControlProtocol::DISPLAYLOST,
2352                                                  &reply,
2353                                                  5000))
2354   {
2355     bool success = reply->signal == CActiveAEControlProtocol::ACC;
2356     reply->Release();
2357     if (!success)
2358     {
2359       CLog::Log(LOGERROR, "ActiveAE::%s - returned error", __FUNCTION__);
2360     }
2361   }
2362   else
2363   {
2364     CLog::Log(LOGERROR, "ActiveAE::%s - timed out", __FUNCTION__);
2365   }
2366 }
2367
2368 void CActiveAE::OnResetDevice()
2369 {
2370   m_controlPort.SendOutMessage(CActiveAEControlProtocol::DISPLAYRESET);
2371 }
2372
2373 void CActiveAE::OnAppFocusChange(bool focus)
2374 {
2375   m_controlPort.SendOutMessage(CActiveAEControlProtocol::APPFOCUSED, &focus, sizeof(focus));
2376 }
2377
2378 //-----------------------------------------------------------------------------
2379 // Utils
2380 //-----------------------------------------------------------------------------
2381
2382 uint8_t **CActiveAE::AllocSoundSample(SampleConfig &config, int &samples, int &bytes_per_sample, int &planes, int &linesize)
2383 {
2384   uint8_t **buffer;
2385   planes = m_dllAvUtil.av_sample_fmt_is_planar(config.fmt) ? config.channels : 1;
2386   buffer = new uint8_t*[planes];
2387
2388   // align buffer to 16 in order to be compatible with sse in CAEConvert
2389   m_dllAvUtil.av_samples_alloc(buffer, &linesize, config.channels,
2390                                  samples, config.fmt, 16);
2391   bytes_per_sample = m_dllAvUtil.av_get_bytes_per_sample(config.fmt);
2392   return buffer;
2393 }
2394
2395 void CActiveAE::FreeSoundSample(uint8_t **data)
2396 {
2397   m_dllAvUtil.av_freep(data);
2398   delete [] data;
2399 }
2400
2401 bool CActiveAE::CompareFormat(AEAudioFormat &lhs, AEAudioFormat &rhs)
2402 {
2403   if (lhs.m_channelLayout != rhs.m_channelLayout ||
2404       lhs.m_dataFormat != rhs.m_dataFormat ||
2405       lhs.m_sampleRate != rhs.m_sampleRate)
2406     return false;
2407   else
2408     return true;
2409 }
2410
2411 //-----------------------------------------------------------------------------
2412 // GUI Sounds
2413 //-----------------------------------------------------------------------------
2414
2415 /**
2416  * load sound from an audio file and store original format
2417  * register the sound in ActiveAE
2418  * later when the engine is idle it will convert the sound to sink format
2419  */
2420
2421 #define SOUNDBUFFER_SIZE 20480
2422
2423 IAESound *CActiveAE::MakeSound(const std::string& file)
2424 {
2425   AVFormatContext *fmt_ctx = NULL;
2426   AVCodecContext *dec_ctx = NULL;
2427   AVIOContext *io_ctx;
2428   AVInputFormat *io_fmt;
2429   AVCodec *dec = NULL;
2430   CActiveAESound *sound = NULL;
2431   SampleConfig config;
2432
2433   sound = new CActiveAESound(file);
2434   if (!sound->Prepare())
2435   {
2436     delete sound;
2437     return NULL;
2438   }
2439   int fileSize = sound->GetFileSize();
2440
2441   fmt_ctx = m_dllAvFormat.avformat_alloc_context();
2442   unsigned char* buffer = (unsigned char*)m_dllAvUtil.av_malloc(SOUNDBUFFER_SIZE+FF_INPUT_BUFFER_PADDING_SIZE);
2443   io_ctx = m_dllAvFormat.avio_alloc_context(buffer, SOUNDBUFFER_SIZE, 0,
2444                                             sound, CActiveAESound::Read, NULL, CActiveAESound::Seek);
2445   io_ctx->max_packet_size = sound->GetChunkSize();
2446   if(io_ctx->max_packet_size)
2447     io_ctx->max_packet_size *= SOUNDBUFFER_SIZE / io_ctx->max_packet_size;
2448
2449   if(!sound->IsSeekPosible())
2450     io_ctx->seekable = 0;
2451
2452   fmt_ctx->pb = io_ctx;
2453
2454   m_dllAvFormat.av_probe_input_buffer(io_ctx, &io_fmt, file.c_str(), NULL, 0, 0);
2455   if (!io_fmt)
2456   {
2457     m_dllAvFormat.avformat_close_input(&fmt_ctx);
2458     delete sound;
2459     return NULL;
2460   }
2461
2462   // find decoder
2463   if (m_dllAvFormat.avformat_open_input(&fmt_ctx, file.c_str(), NULL, NULL) == 0)
2464   {
2465     fmt_ctx->flags |= AVFMT_FLAG_NOPARSE;
2466     if (m_dllAvFormat.avformat_find_stream_info(fmt_ctx, NULL) >= 0)
2467     {
2468       dec_ctx = fmt_ctx->streams[0]->codec;
2469       dec = m_dllAvCodec.avcodec_find_decoder(dec_ctx->codec_id);
2470       config.sample_rate = dec_ctx->sample_rate;
2471       config.channels = dec_ctx->channels;
2472       config.channel_layout = dec_ctx->channel_layout;
2473     }
2474   }
2475   if (dec == NULL)
2476   {
2477     m_dllAvFormat.avformat_close_input(&fmt_ctx);
2478     delete sound;
2479     return NULL;
2480   }
2481
2482   dec_ctx = m_dllAvCodec.avcodec_alloc_context3(dec);
2483   dec_ctx->sample_rate = config.sample_rate;
2484   dec_ctx->channels = config.channels;
2485   if (!config.channel_layout)
2486     config.channel_layout = m_dllAvUtil.av_get_default_channel_layout(config.channels);
2487   dec_ctx->channel_layout = config.channel_layout;
2488
2489   AVPacket avpkt;
2490   AVFrame *decoded_frame = NULL;
2491   decoded_frame = m_dllAvCodec.avcodec_alloc_frame();
2492
2493   if (m_dllAvCodec.avcodec_open2(dec_ctx, dec, NULL) >= 0)
2494   {
2495     bool init = false;
2496
2497     // decode until eof
2498     m_dllAvCodec.av_init_packet(&avpkt);
2499     int len;
2500     while (m_dllAvFormat.av_read_frame(fmt_ctx, &avpkt) >= 0)
2501     {
2502       int got_frame = 0;
2503       len = m_dllAvCodec.avcodec_decode_audio4(dec_ctx, decoded_frame, &got_frame, &avpkt);
2504       if (len < 0)
2505       {
2506         m_dllAvCodec.avcodec_close(dec_ctx);
2507         m_dllAvUtil.av_free(dec_ctx);
2508         m_dllAvUtil.av_free(&decoded_frame);
2509         m_dllAvFormat.avformat_close_input(&fmt_ctx);
2510         delete sound;
2511         return NULL;
2512       }
2513       if (got_frame)
2514       {
2515         if (!init)
2516         {
2517           int samples = fileSize / m_dllAvUtil.av_get_bytes_per_sample(dec_ctx->sample_fmt) / config.channels;
2518           config.fmt = dec_ctx->sample_fmt;
2519           config.bits_per_sample = dec_ctx->bits_per_coded_sample;
2520           sound->InitSound(true, config, samples);
2521           init = true;
2522         }
2523         sound->StoreSound(true, decoded_frame->extended_data,
2524                           decoded_frame->nb_samples, decoded_frame->linesize[0]);
2525       }
2526     }
2527     m_dllAvCodec.avcodec_close(dec_ctx);
2528   }
2529
2530   m_dllAvUtil.av_free(dec_ctx);
2531   m_dllAvUtil.av_free(decoded_frame);
2532   m_dllAvFormat.avformat_close_input(&fmt_ctx);
2533
2534   sound->Finish();
2535
2536   // register sound
2537   m_dataPort.SendOutMessage(CActiveAEDataProtocol::NEWSOUND, &sound, sizeof(CActiveAESound*));
2538
2539   return sound;
2540 }
2541
2542 void CActiveAE::FreeSound(IAESound *sound)
2543 {
2544   m_dataPort.SendOutMessage(CActiveAEDataProtocol::FREESOUND, &sound, sizeof(CActiveAESound*));
2545 }
2546
2547 void CActiveAE::PlaySound(CActiveAESound *sound)
2548 {
2549   m_dataPort.SendOutMessage(CActiveAEDataProtocol::PLAYSOUND, &sound, sizeof(CActiveAESound*));
2550 }
2551
2552 void CActiveAE::StopSound(CActiveAESound *sound)
2553 {
2554   m_controlPort.SendOutMessage(CActiveAEControlProtocol::STOPSOUND, &sound, sizeof(CActiveAESound*));
2555 }
2556
2557 /**
2558  * resample sounds to destination format for mixing
2559  * destination format is either format of stream or
2560  * default sink format when no stream is playing
2561  */
2562 void CActiveAE::ResampleSounds()
2563 {
2564   if (m_settings.guisoundmode == AE_SOUND_OFF ||
2565      (m_settings.guisoundmode == AE_SOUND_IDLE && !m_streams.empty()))
2566     return;
2567
2568   std::vector<CActiveAESound*>::iterator it;
2569   for (it = m_sounds.begin(); it != m_sounds.end(); ++it)
2570   {
2571     if (!(*it)->IsConverted())
2572     {
2573       ResampleSound(*it);
2574       // only do one sound, then yield to main loop
2575       break;
2576     }
2577   }
2578 }
2579
2580 bool CActiveAE::ResampleSound(CActiveAESound *sound)
2581 {
2582   SampleConfig orig_config, dst_config;
2583   uint8_t **dst_buffer;
2584   int dst_samples;
2585
2586   if (m_mode == MODE_RAW || m_internalFormat.m_dataFormat == AE_FMT_INVALID)
2587     return false;
2588
2589   if (!sound->GetSound(true))
2590     return false;
2591
2592   orig_config = sound->GetSound(true)->config;
2593
2594   dst_config.channel_layout = CActiveAEResample::GetAVChannelLayout(m_internalFormat.m_channelLayout);
2595   dst_config.channels = m_internalFormat.m_channelLayout.Count();
2596   dst_config.sample_rate = m_internalFormat.m_sampleRate;
2597   dst_config.fmt = CActiveAEResample::GetAVSampleFormat(m_internalFormat.m_dataFormat);
2598   dst_config.bits_per_sample = CAEUtil::DataFormatToUsedBits(m_internalFormat.m_dataFormat);
2599
2600   CActiveAEResample *resampler = new CActiveAEResample();
2601   resampler->Init(dst_config.channel_layout,
2602                   dst_config.channels,
2603                   dst_config.sample_rate,
2604                   dst_config.fmt,
2605                   dst_config.bits_per_sample,
2606                   orig_config.channel_layout,
2607                   orig_config.channels,
2608                   orig_config.sample_rate,
2609                   orig_config.fmt,
2610                   orig_config.bits_per_sample,
2611                   false,
2612                   true,
2613                   NULL,
2614                   m_settings.resampleQuality);
2615
2616   dst_samples = resampler->CalcDstSampleCount(sound->GetSound(true)->nb_samples,
2617                                               m_internalFormat.m_sampleRate,
2618                                               orig_config.sample_rate);
2619
2620   dst_buffer = sound->InitSound(false, dst_config, dst_samples);
2621   if (!dst_buffer)
2622   {
2623     delete resampler;
2624     return false;
2625   }
2626   int samples = resampler->Resample(dst_buffer, dst_samples,
2627                                     sound->GetSound(true)->data,
2628                                     sound->GetSound(true)->nb_samples,
2629                                     1.0);
2630
2631   sound->GetSound(false)->nb_samples = samples;
2632
2633   delete resampler;
2634   sound->SetConverted(true);
2635   return true;
2636 }
2637
2638 //-----------------------------------------------------------------------------
2639 // Streams
2640 //-----------------------------------------------------------------------------
2641
2642 IAEStream *CActiveAE::MakeStream(enum AEDataFormat dataFormat, unsigned int sampleRate, unsigned int encodedSampleRate, CAEChannelInfo channelLayout, unsigned int options)
2643 {
2644   //TODO: pass number of samples in audio packet
2645
2646   AEAudioFormat format;
2647   format.m_dataFormat = dataFormat;
2648   format.m_sampleRate = sampleRate;
2649   format.m_encodedRate = encodedSampleRate;
2650   format.m_channelLayout = channelLayout;
2651   format.m_frames = format.m_sampleRate / 10;
2652   format.m_frameSize = format.m_channelLayout.Count() *
2653                        (CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3);
2654
2655   MsgStreamNew msg;
2656   msg.format = format;
2657   msg.options = options;
2658
2659   Message *reply;
2660   if (m_dataPort.SendOutMessageSync(CActiveAEDataProtocol::NEWSTREAM,
2661                                     &reply,10000,
2662                                     &msg, sizeof(MsgStreamNew)))
2663   {
2664     bool success = reply->signal == CActiveAEControlProtocol::ACC;
2665     if (success)
2666     {
2667       CActiveAEStream *stream = *(CActiveAEStream**)reply->data;
2668       reply->Release();
2669       return stream;
2670     }
2671     reply->Release();
2672   }
2673
2674   CLog::Log(LOGERROR, "ActiveAE::%s - could not create stream", __FUNCTION__);
2675   return NULL;
2676 }
2677
2678 IAEStream *CActiveAE::FreeStream(IAEStream *stream)
2679 {
2680   m_dataPort.SendOutMessage(CActiveAEDataProtocol::FREESTREAM, &stream, sizeof(IAEStream*));
2681   return NULL;
2682 }
2683
2684 void CActiveAE::FlushStream(CActiveAEStream *stream)
2685 {
2686   Message *reply;
2687   if (m_controlPort.SendOutMessageSync(CActiveAEControlProtocol::FLUSHSTREAM,
2688                                        &reply,1000,
2689                                        &stream, sizeof(CActiveAEStream*)))
2690   {
2691     bool success = reply->signal == CActiveAEControlProtocol::ACC;
2692     reply->Release();
2693     if (!success)
2694     {
2695       CLog::Log(LOGERROR, "CActiveAE::FlushStream - failed");
2696     }
2697   }
2698 }
2699
2700 void CActiveAE::PauseStream(CActiveAEStream *stream, bool pause)
2701 {
2702   // TODO pause sink, needs api change
2703   if (pause)
2704     m_controlPort.SendOutMessage(CActiveAEControlProtocol::PAUSESTREAM,
2705                                    &stream, sizeof(CActiveAEStream*));
2706   else
2707     m_controlPort.SendOutMessage(CActiveAEControlProtocol::RESUMESTREAM,
2708                                    &stream, sizeof(CActiveAEStream*));
2709 }
2710
2711 void CActiveAE::SetStreamAmplification(CActiveAEStream *stream, float amplify)
2712 {
2713   MsgStreamParameter msg;
2714   msg.stream = stream;
2715   msg.parameter.float_par = amplify;
2716   m_controlPort.SendOutMessage(CActiveAEControlProtocol::STREAMAMP,
2717                                      &msg, sizeof(MsgStreamParameter));
2718 }
2719
2720 void CActiveAE::SetStreamReplaygain(CActiveAEStream *stream, float rgain)
2721 {
2722   MsgStreamParameter msg;
2723   msg.stream = stream;
2724   msg.parameter.float_par = rgain;
2725   m_controlPort.SendOutMessage(CActiveAEControlProtocol::STREAMRGAIN,
2726                                      &msg, sizeof(MsgStreamParameter));
2727 }
2728
2729 void CActiveAE::SetStreamVolume(CActiveAEStream *stream, float volume)
2730 {
2731   MsgStreamParameter msg;
2732   msg.stream = stream;
2733   msg.parameter.float_par = volume;
2734   m_controlPort.SendOutMessage(CActiveAEControlProtocol::STREAMVOLUME,
2735                                      &msg, sizeof(MsgStreamParameter));
2736 }
2737
2738 void CActiveAE::SetStreamResampleRatio(CActiveAEStream *stream, double ratio)
2739 {
2740   MsgStreamParameter msg;
2741   msg.stream = stream;
2742   msg.parameter.double_par = ratio;
2743   m_controlPort.SendOutMessage(CActiveAEControlProtocol::STREAMRESAMPLERATIO,
2744                                      &msg, sizeof(MsgStreamParameter));
2745 }
2746
2747 void CActiveAE::SetStreamFade(CActiveAEStream *stream, float from, float target, unsigned int millis)
2748 {
2749   MsgStreamFade msg;
2750   msg.stream = stream;
2751   msg.from = from;
2752   msg.target = target;
2753   msg.millis = millis;
2754   m_controlPort.SendOutMessage(CActiveAEControlProtocol::STREAMFADE,
2755                                      &msg, sizeof(MsgStreamFade));
2756 }
2757
2758 void CActiveAE::RegisterAudioCallback(IAudioCallback* pCallback)
2759 {
2760   CSingleLock lock(m_vizLock);
2761   m_audioCallback = pCallback;
2762   m_vizInitialized = false;
2763 }
2764
2765 void CActiveAE::UnregisterAudioCallback()
2766 {
2767   CSingleLock lock(m_vizLock);
2768   m_audioCallback = NULL;
2769 }