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