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