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