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