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