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