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