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