Merge pull request #4574 from FernetMenta/aefixes
[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)
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) ||
1173       !CompareFormat(m_sinkBuffers->m_inputFormat, sinkInputFormat) ||
1174       m_sinkBuffers->m_format.m_frames != m_sinkFormat.m_frames))
1175   {
1176     m_discardBufferPools.push_back(m_sinkBuffers);
1177     m_sinkBuffers = NULL;
1178   }
1179   if (!m_sinkBuffers)
1180   {
1181     m_sinkBuffers = new CActiveAEBufferPoolResample(sinkInputFormat, m_sinkFormat, m_settings.resampleQuality);
1182     m_sinkBuffers->Create(MAX_WATER_LEVEL*1000, true, false);
1183   }
1184
1185   // reset gui sounds
1186   if (!CompareFormat(oldInternalFormat, m_internalFormat))
1187   {
1188     if (m_settings.guisoundmode == AE_SOUND_ALWAYS ||
1189        (m_settings.guisoundmode == AE_SOUND_IDLE && m_streams.empty()))
1190     {
1191       std::vector<CActiveAESound*>::iterator it;
1192       for (it = m_sounds.begin(); it != m_sounds.end(); ++it)
1193       {
1194         (*it)->SetConverted(false);
1195       }
1196     }
1197     m_sounds_playing.clear();
1198   }
1199
1200   ClearDiscardedBuffers();
1201   m_extDrain = false;
1202 }
1203
1204 CActiveAEStream* CActiveAE::CreateStream(MsgStreamNew *streamMsg)
1205 {
1206   // we only can handle a single pass through stream
1207   bool hasRawStream = false;
1208   bool hasStream = false;
1209   std::list<CActiveAEStream*>::iterator it;
1210   for(it = m_streams.begin(); it != m_streams.end(); ++it)
1211   {
1212     if((*it)->IsDrained())
1213       continue;
1214     if(AE_IS_RAW((*it)->m_format.m_dataFormat))
1215       hasRawStream = true;
1216     hasStream = true;
1217   }
1218   if (hasRawStream || (hasStream && AE_IS_RAW(streamMsg->format.m_dataFormat)))
1219   {
1220     return NULL;
1221   }
1222
1223   // create the stream
1224   CActiveAEStream *stream;
1225   stream = new CActiveAEStream(&streamMsg->format);
1226   stream->m_streamPort = new CActiveAEDataProtocol("stream",
1227                              &stream->m_inMsgEvent, &m_outMsgEvent);
1228
1229   // create buffer pool
1230   stream->m_inputBuffers = NULL; // create in Configure when we know the sink format
1231   stream->m_resampleBuffers = NULL; // create in Configure when we know the sink format
1232   stream->m_statsLock = m_stats.GetLock();
1233   stream->m_fadingSamples = 0;
1234   stream->m_started = false;
1235
1236   if (streamMsg->options & AESTREAM_PAUSED)
1237     stream->m_paused = true;
1238
1239   if (streamMsg->options & AESTREAM_FORCE_RESAMPLE)
1240     stream->m_forceResampler = true;
1241
1242   m_streams.push_back(stream);
1243
1244   return stream;
1245 }
1246
1247 void CActiveAE::DiscardStream(CActiveAEStream *stream)
1248 {
1249   std::list<CActiveAEStream*>::iterator it;
1250   for (it=m_streams.begin(); it!=m_streams.end(); )
1251   {
1252     if (stream == (*it))
1253     {
1254       while (!(*it)->m_processingSamples.empty())
1255       {
1256         (*it)->m_processingSamples.front()->Return();
1257         (*it)->m_processingSamples.pop_front();
1258       }
1259       m_discardBufferPools.push_back((*it)->m_inputBuffers);
1260       m_discardBufferPools.push_back((*it)->m_resampleBuffers);
1261       CLog::Log(LOGDEBUG, "CActiveAE::DiscardStream - audio stream deleted");
1262       delete (*it)->m_streamPort;
1263       delete (*it);
1264       it = m_streams.erase(it);
1265     }
1266     else
1267       ++it;
1268   }
1269
1270   ClearDiscardedBuffers();
1271 }
1272
1273 void CActiveAE::SFlushStream(CActiveAEStream *stream)
1274 {
1275   while (!stream->m_processingSamples.empty())
1276   {
1277     stream->m_processingSamples.front()->Return();
1278     stream->m_processingSamples.pop_front();
1279   }
1280   stream->m_resampleBuffers->Flush();
1281   stream->m_streamPort->Purge();
1282   stream->m_bufferedTime = 0.0;
1283   stream->m_paused = false;
1284
1285   // flush the engine if we only have a single stream
1286   if (m_streams.size() == 1)
1287   {
1288     FlushEngine();
1289   }
1290 }
1291
1292 void CActiveAE::FlushEngine()
1293 {
1294   if (m_sinkBuffers)
1295     m_sinkBuffers->Flush();
1296   if (m_vizBuffers)
1297     m_vizBuffers->Flush();
1298
1299   // send message to sink
1300   Message *reply;
1301   if (m_sink.m_controlPort.SendOutMessageSync(CSinkControlProtocol::FLUSH,
1302                                            &reply, 2000))
1303   {
1304     bool success = reply->signal == CSinkControlProtocol::ACC;
1305     if (!success)
1306     {
1307       CLog::Log(LOGERROR, "ActiveAE::%s - returned error on flush", __FUNCTION__);
1308       m_extError = true;
1309     }
1310     reply->Release();
1311   }
1312   else
1313   {
1314     CLog::Log(LOGERROR, "ActiveAE::%s - failed to flush", __FUNCTION__);
1315     m_extError = true;
1316   }
1317   m_stats.Reset(m_sinkFormat.m_sampleRate);
1318 }
1319
1320 void CActiveAE::ClearDiscardedBuffers()
1321 {
1322   std::list<CActiveAEBufferPool*>::iterator it;
1323   for (it=m_discardBufferPools.begin(); it!=m_discardBufferPools.end(); ++it)
1324   {
1325     CActiveAEBufferPoolResample *rbuf = dynamic_cast<CActiveAEBufferPoolResample*>(*it);
1326     if (rbuf)
1327     {
1328       rbuf->Flush();
1329     }
1330     // if all buffers have returned, we can delete the buffer pool
1331     if ((*it)->m_allSamples.size() == (*it)->m_freeSamples.size())
1332     {
1333       delete (*it);
1334       CLog::Log(LOGDEBUG, "CActiveAE::ClearDiscardedBuffers - buffer pool deleted");
1335       m_discardBufferPools.erase(it);
1336       return;
1337     }
1338   }
1339 }
1340
1341 void CActiveAE::SStopSound(CActiveAESound *sound)
1342 {
1343   std::list<SoundState>::iterator it;
1344   for (it=m_sounds_playing.begin(); it!=m_sounds_playing.end(); ++it)
1345   {
1346     if (it->sound == sound)
1347     {
1348       m_sounds_playing.erase(it);
1349       return;
1350     }
1351   }
1352 }
1353
1354 void CActiveAE::DiscardSound(CActiveAESound *sound)
1355 {
1356   SStopSound(sound);
1357
1358   std::vector<CActiveAESound*>::iterator it;
1359   for (it=m_sounds.begin(); it!=m_sounds.end(); ++it)
1360   {
1361     if ((*it) == sound)
1362     {
1363       m_sounds.erase(it);
1364       return;
1365     }
1366   }
1367 }
1368
1369 void CActiveAE::ChangeResamplers()
1370 {
1371   std::list<CActiveAEStream*>::iterator it;
1372   for(it=m_streams.begin(); it!=m_streams.end(); ++it)
1373   {
1374     bool normalize = true;
1375     if (((*it)->m_resampleBuffers->m_format.m_channelLayout.Count() <
1376          (*it)->m_resampleBuffers->m_inputFormat.m_channelLayout.Count()) &&
1377          !m_settings.normalizelevels)
1378       normalize = false;
1379
1380     if ((*it)->m_resampleBuffers && (*it)->m_resampleBuffers->m_resampler &&
1381         (((*it)->m_resampleBuffers->m_resampleQuality != m_settings.resampleQuality) ||
1382         (((*it)->m_resampleBuffers->m_stereoUpmix != m_settings.stereoupmix)) ||
1383         ((*it)->m_resampleBuffers->m_normalize != normalize)))
1384     {
1385       (*it)->m_resampleBuffers->m_changeResampler = true;
1386     }
1387     (*it)->m_resampleBuffers->m_resampleQuality = m_settings.resampleQuality;
1388     (*it)->m_resampleBuffers->m_stereoUpmix = m_settings.stereoupmix;
1389     (*it)->m_resampleBuffers->m_normalize = normalize;
1390   }
1391 }
1392
1393 void CActiveAE::ApplySettingsToFormat(AEAudioFormat &format, AudioSettings &settings, int *mode)
1394 {
1395   int oldMode = m_mode;
1396   if (mode)
1397     *mode = MODE_PCM;
1398
1399   // raw pass through
1400   if (AE_IS_RAW(format.m_dataFormat))
1401   {
1402     if ((format.m_dataFormat == AE_FMT_AC3 && !settings.ac3passthrough) ||
1403         (format.m_dataFormat == AE_FMT_EAC3 && !settings.eac3passthrough) ||
1404         (format.m_dataFormat == AE_FMT_TRUEHD && !settings.truehdpassthrough) ||
1405         (format.m_dataFormat == AE_FMT_DTS && !settings.dtspassthrough) ||
1406         (format.m_dataFormat == AE_FMT_DTSHD && !settings.dtshdpassthrough))
1407     {
1408       CLog::Log(LOGERROR, "CActiveAE::ApplySettingsToFormat - input audio format is wrong");
1409     }
1410     if (mode)
1411       *mode = MODE_RAW;
1412   }
1413   // transcode
1414   else if (settings.channels <= AE_CH_LAYOUT_2_0 && // no multichannel pcm
1415            settings.passthrough &&
1416            settings.ac3passthrough &&
1417            settings.ac3transcode &&
1418            !m_streams.empty() &&
1419            (format.m_channelLayout.Count() > 2 || settings.stereoupmix))
1420   {
1421     format.m_dataFormat = AE_FMT_AC3;
1422     format.m_sampleRate = 48000;
1423     format.m_channelLayout = AE_CH_LAYOUT_2_0;
1424     if (mode)
1425       *mode = MODE_TRANSCODE;
1426   }
1427   else
1428   {
1429     format.m_dataFormat = AE_FMT_FLOAT;
1430     // consider user channel layout for those cases
1431     // 1. input stream is multichannel
1432     // 2. stereo upmix is selected
1433     // 3. fixed mode
1434     if ((format.m_channelLayout.Count() > 2) ||
1435          settings.stereoupmix ||
1436          (settings.config == AE_CONFIG_FIXED))
1437     {
1438       CAEChannelInfo stdLayout;
1439       switch (settings.channels)
1440       {
1441         default:
1442         case  0: stdLayout = AE_CH_LAYOUT_2_0; break;
1443         case  1: stdLayout = AE_CH_LAYOUT_2_0; break;
1444         case  2: stdLayout = AE_CH_LAYOUT_2_1; break;
1445         case  3: stdLayout = AE_CH_LAYOUT_3_0; break;
1446         case  4: stdLayout = AE_CH_LAYOUT_3_1; break;
1447         case  5: stdLayout = AE_CH_LAYOUT_4_0; break;
1448         case  6: stdLayout = AE_CH_LAYOUT_4_1; break;
1449         case  7: stdLayout = AE_CH_LAYOUT_5_0; break;
1450         case  8: stdLayout = AE_CH_LAYOUT_5_1; break;
1451         case  9: stdLayout = AE_CH_LAYOUT_7_0; break;
1452         case 10: stdLayout = AE_CH_LAYOUT_7_1; break;
1453       }
1454
1455       if (m_settings.config == AE_CONFIG_FIXED || (settings.stereoupmix && format.m_channelLayout.Count() <= 2))
1456         format.m_channelLayout = stdLayout;
1457       else if (m_extKeepConfig && (settings.config == AE_CONFIG_AUTO) && (oldMode != MODE_RAW))
1458         format.m_channelLayout = m_internalFormat.m_channelLayout;
1459       else
1460         format.m_channelLayout.ResolveChannels(stdLayout);
1461     }
1462     // don't change from multi to stereo in AUTO mode
1463     else if ((settings.config == AE_CONFIG_AUTO) &&
1464               m_stats.GetWaterLevel() > 0 && m_internalFormat.m_channelLayout.Count() > 2)
1465     {
1466       format.m_channelLayout = m_internalFormat.m_channelLayout;
1467     }
1468
1469     if (m_sink.GetDeviceType(m_settings.device) == AE_DEVTYPE_IEC958)
1470     {
1471       if (format.m_sampleRate > m_settings.samplerate)
1472       {
1473         format.m_sampleRate = m_settings.samplerate;
1474         CLog::Log(LOGINFO, "CActiveAE::ApplySettings - limit samplerate for SPDIF to %d", format.m_sampleRate);
1475       }
1476       format.m_channelLayout = AE_CH_LAYOUT_2_0;
1477     }
1478
1479     if (m_settings.config == AE_CONFIG_FIXED)
1480     {
1481       format.m_sampleRate = m_settings.samplerate;
1482       CLog::Log(LOGINFO, "CActiveAE::ApplySettings - Forcing samplerate to %d", format.m_sampleRate);
1483     }
1484
1485     // sinks may not support mono
1486     if (format.m_channelLayout.Count() == 1)
1487     {
1488       format.m_channelLayout = AE_CH_LAYOUT_2_0;
1489     }
1490   }
1491 }
1492
1493 bool CActiveAE::NeedReconfigureBuffers()
1494 {
1495   AEAudioFormat newFormat = GetInputFormat();
1496   ApplySettingsToFormat(newFormat, m_settings);
1497
1498   if (newFormat.m_dataFormat != m_sinkRequestFormat.m_dataFormat ||
1499       newFormat.m_channelLayout != m_sinkRequestFormat.m_channelLayout ||
1500       newFormat.m_sampleRate != m_sinkRequestFormat.m_sampleRate)
1501     return true;
1502
1503   return false;
1504 }
1505
1506 bool CActiveAE::NeedReconfigureSink()
1507 {
1508   AEAudioFormat newFormat = GetInputFormat();
1509   ApplySettingsToFormat(newFormat, m_settings);
1510
1511   std::string device = AE_IS_RAW(newFormat.m_dataFormat) ? m_settings.passthoughdevice : m_settings.device;
1512   std::string driver;
1513   CAESinkFactory::ParseDevice(device, driver);
1514
1515   if (!CompareFormat(newFormat, m_sinkFormat) ||
1516       m_currDevice.compare(device) != 0 ||
1517       m_settings.driver.compare(driver) != 0)
1518     return true;
1519
1520   return false;
1521 }
1522
1523 bool CActiveAE::InitSink()
1524 {
1525   SinkConfig config;
1526   config.format = m_sinkRequestFormat;
1527   config.stats = &m_stats;
1528   config.device = AE_IS_RAW(m_sinkRequestFormat.m_dataFormat) ? &m_settings.passthoughdevice :
1529                                                                 &m_settings.device;
1530
1531   // send message to sink
1532   Message *reply;
1533   if (m_sink.m_controlPort.SendOutMessageSync(CSinkControlProtocol::CONFIGURE,
1534                                                  &reply,
1535                                                  5000,
1536                                                  &config, sizeof(config)))
1537   {
1538     bool success = reply->signal == CSinkControlProtocol::ACC;
1539     if (!success)
1540     {
1541       reply->Release();
1542       CLog::Log(LOGERROR, "ActiveAE::%s - returned error", __FUNCTION__);
1543       m_extError = true;
1544       return false;
1545     }
1546     SinkReply *data;
1547     data = (SinkReply*)reply->data;
1548     if (data)
1549     {
1550       m_sinkFormat = data->format;
1551       m_sinkHasVolume = data->hasVolume;
1552       m_stats.SetSinkCacheTotal(data->cacheTotal);
1553       m_stats.SetSinkLatency(data->latency);
1554     }
1555     reply->Release();
1556   }
1557   else
1558   {
1559     CLog::Log(LOGERROR, "ActiveAE::%s - failed to init", __FUNCTION__);
1560     m_stats.SetSinkCacheTotal(0);
1561     m_stats.SetSinkLatency(0);
1562     m_extError = true;
1563     return false;
1564   }
1565
1566   m_inMsgEvent.Reset();
1567   return true;
1568 }
1569
1570 void CActiveAE::DrainSink()
1571 {
1572   // send message to sink
1573   Message *reply;
1574   if (m_sink.m_dataPort.SendOutMessageSync(CSinkDataProtocol::DRAIN,
1575                                                  &reply,
1576                                                  2000))
1577   {
1578     bool success = reply->signal == CSinkDataProtocol::ACC;
1579     if (!success)
1580     {
1581       reply->Release();
1582       CLog::Log(LOGERROR, "ActiveAE::%s - returned error on drain", __FUNCTION__);
1583       m_extError = true;
1584       return;
1585     }
1586     reply->Release();
1587   }
1588   else
1589   {
1590     CLog::Log(LOGERROR, "ActiveAE::%s - failed to drain", __FUNCTION__);
1591     m_extError = true;
1592     return;
1593   }
1594 }
1595
1596 void CActiveAE::UnconfigureSink()
1597 {
1598   // send message to sink
1599   Message *reply;
1600   if (m_sink.m_controlPort.SendOutMessageSync(CSinkControlProtocol::UNCONFIGURE,
1601                                                  &reply,
1602                                                  2000))
1603   {
1604     bool success = reply->signal == CSinkControlProtocol::ACC;
1605     if (!success)
1606     {
1607       CLog::Log(LOGERROR, "ActiveAE::%s - returned error", __FUNCTION__);
1608       m_extError = true;
1609     }
1610     reply->Release();
1611   }
1612   else
1613   {
1614     CLog::Log(LOGERROR, "ActiveAE::%s - failed to unconfigure", __FUNCTION__);
1615     m_extError = true;
1616   }
1617
1618   // make sure we open sink on next configure
1619   m_currDevice = "";
1620
1621   m_inMsgEvent.Reset();
1622 }
1623
1624
1625 bool CActiveAE::RunStages()
1626 {
1627   bool busy = false;
1628
1629   // serve input streams
1630   std::list<CActiveAEStream*>::iterator it;
1631   for (it = m_streams.begin(); it != m_streams.end(); ++it)
1632   {
1633     if ((*it)->m_resampleBuffers && !(*it)->m_paused)
1634       busy = (*it)->m_resampleBuffers->ResampleBuffers();
1635     else if ((*it)->m_resampleBuffers && 
1636             ((*it)->m_resampleBuffers->m_inputSamples.size() > (*it)->m_resampleBuffers->m_allSamples.size() * 0.5))
1637     {
1638       CSingleLock lock((*it)->m_streamLock);
1639       (*it)->m_streamIsBuffering = false;
1640     }
1641
1642     // provide buffers to stream
1643     float time = m_stats.GetCacheTime((*it));
1644     CSampleBuffer *buffer;
1645     if (!(*it)->m_drain)
1646     {
1647       while (time < MAX_CACHE_LEVEL && !(*it)->m_inputBuffers->m_freeSamples.empty())
1648       {
1649         buffer = (*it)->m_inputBuffers->GetFreeBuffer();
1650         (*it)->m_processingSamples.push_back(buffer);
1651         (*it)->m_streamPort->SendInMessage(CActiveAEDataProtocol::STREAMBUFFER, &buffer, sizeof(CSampleBuffer*));
1652         (*it)->IncFreeBuffers();
1653         time += (float)buffer->pkt->max_nb_samples / buffer->pkt->config.sample_rate;
1654       }
1655     }
1656     else
1657     {
1658       if ((*it)->m_resampleBuffers->m_inputSamples.empty() &&
1659           (*it)->m_resampleBuffers->m_outputSamples.empty() &&
1660           (*it)->m_processingSamples.empty())
1661       {
1662         (*it)->m_streamPort->SendInMessage(CActiveAEDataProtocol::STREAMDRAINED);
1663         (*it)->m_drain = false;
1664         (*it)->m_resampleBuffers->m_drain = false;
1665         (*it)->m_started = false;
1666
1667         // set variables being polled via stream interface
1668         CSingleLock lock((*it)->m_streamLock);
1669         if ((*it)->m_streamSlave)
1670         {
1671           CActiveAEStream *slave = (CActiveAEStream*)((*it)->m_streamSlave);
1672           slave->m_paused = false;
1673
1674           // TODO: find better solution for this
1675           // gapless bites audiophile
1676           if (m_settings.config == AE_CONFIG_MATCH)
1677             Configure(&slave->m_format);
1678
1679           (*it)->m_streamSlave = NULL;
1680         }
1681         (*it)->m_streamDrained = true;
1682         (*it)->m_streamDraining = false;
1683         (*it)->m_streamFading = false;
1684       }
1685     }
1686   }
1687
1688   if (m_stats.GetWaterLevel() < MAX_WATER_LEVEL &&
1689      (m_mode != MODE_TRANSCODE || (m_encoderBuffers && !m_encoderBuffers->m_freeSamples.empty())))
1690   {
1691     // mix streams and sounds sounds
1692     if (m_mode != MODE_RAW)
1693     {
1694       CSampleBuffer *out = NULL;
1695       if (!m_sounds_playing.empty() && m_streams.empty())
1696       {
1697         if (m_silenceBuffers && !m_silenceBuffers->m_freeSamples.empty())
1698         {
1699           out = m_silenceBuffers->GetFreeBuffer();
1700           for (int i=0; i<out->pkt->planes; i++)
1701           {
1702             memset(out->pkt->data[i], 0, out->pkt->linesize);
1703           }
1704           out->pkt->nb_samples = out->pkt->max_nb_samples;
1705         }
1706       }
1707
1708       // mix streams
1709       std::list<CActiveAEStream*>::iterator it;
1710
1711       // if we deal with more than a single stream, all streams
1712       // must provide samples for mixing
1713       bool allStreamsReady = true;
1714       for (it = m_streams.begin(); it != m_streams.end(); ++it)
1715       {
1716         if ((*it)->m_paused || !(*it)->m_started || !(*it)->m_resampleBuffers)
1717           continue;
1718
1719         if ((*it)->m_resampleBuffers->m_outputSamples.empty())
1720           allStreamsReady = false;
1721       }
1722
1723       bool needClamp = false;
1724       for (it = m_streams.begin(); it != m_streams.end() && allStreamsReady; ++it)
1725       {
1726         if ((*it)->m_paused || !(*it)->m_resampleBuffers)
1727           continue;
1728
1729         if (!(*it)->m_resampleBuffers->m_outputSamples.empty())
1730         {
1731           (*it)->m_started = true;
1732
1733           if (!out)
1734           {
1735             out = (*it)->m_resampleBuffers->m_outputSamples.front();
1736             (*it)->m_resampleBuffers->m_outputSamples.pop_front();
1737
1738             int nb_floats = out->pkt->nb_samples * out->pkt->config.channels / out->pkt->planes;
1739             int nb_loops = 1;
1740             float fadingStep = 0.0f;
1741
1742             // fading
1743             if ((*it)->m_fadingSamples == -1)
1744             {
1745               (*it)->m_fadingSamples = m_internalFormat.m_sampleRate * (float)(*it)->m_fadingTime / 1000.0f;
1746               (*it)->m_volume = (*it)->m_fadingBase;
1747             }
1748             if ((*it)->m_fadingSamples > 0)
1749             {
1750               nb_floats = out->pkt->config.channels / out->pkt->planes;
1751               nb_loops = out->pkt->nb_samples;
1752               float delta = (*it)->m_fadingTarget - (*it)->m_fadingBase;
1753               int samples = m_internalFormat.m_sampleRate * (float)(*it)->m_fadingTime / 1000.0f;
1754               fadingStep = delta / samples;
1755             }
1756
1757             // for stream amplification, 
1758             // turned off downmix normalization,
1759             // or if sink format is float (in order to prevent from clipping)
1760             // we need to run on a per sample basis
1761             if ((*it)->m_amplify != 1.0 || !(*it)->m_resampleBuffers->m_normalize || (m_sinkFormat.m_dataFormat == AE_FMT_FLOAT))
1762             {
1763               nb_floats = out->pkt->config.channels / out->pkt->planes;
1764               nb_loops = out->pkt->nb_samples;
1765             }
1766
1767             for(int i=0; i<nb_loops; i++)
1768             {
1769               if ((*it)->m_fadingSamples > 0)
1770               {
1771                 (*it)->m_volume += fadingStep;
1772                 (*it)->m_fadingSamples--;
1773
1774                 if ((*it)->m_fadingSamples == 0)
1775                 {
1776                   // set variables being polled via stream interface
1777                   CSingleLock lock((*it)->m_streamLock);
1778                   (*it)->m_streamFading = false;
1779                 }
1780               }
1781
1782               // volume for stream
1783               float volume = (*it)->m_volume * (*it)->m_rgain;
1784               if(nb_loops > 1)
1785                 volume *= (*it)->m_limiter.Run((float**)out->pkt->data, out->pkt->config.channels, i*nb_floats, out->pkt->planes > 1);
1786
1787               for(int j=0; j<out->pkt->planes; j++)
1788               {
1789 #ifdef __SSE__
1790                 CAEUtil::SSEMulArray((float*)out->pkt->data[j]+i*nb_floats, volume, nb_floats);
1791 #else
1792                 float* fbuffer = (float*) out->pkt->data[j]+i*nb_floats;
1793                 for (int k = 0; k < nb_floats; ++k)
1794                 {
1795                   fbuffer[k] *= volume;
1796                 }
1797 #endif
1798               }
1799             }
1800           }
1801           else
1802           {
1803             CSampleBuffer *mix = NULL;
1804             mix = (*it)->m_resampleBuffers->m_outputSamples.front();
1805             (*it)->m_resampleBuffers->m_outputSamples.pop_front();
1806
1807             int nb_floats = mix->pkt->nb_samples * mix->pkt->config.channels / mix->pkt->planes;
1808             int nb_loops = 1;
1809             float fadingStep = 0.0f;
1810
1811             // fading
1812             if ((*it)->m_fadingSamples == -1)
1813             {
1814               (*it)->m_fadingSamples = m_internalFormat.m_sampleRate * (float)(*it)->m_fadingTime / 1000.0f;
1815               (*it)->m_volume = (*it)->m_fadingBase;
1816             }
1817             if ((*it)->m_fadingSamples > 0)
1818             {
1819               nb_floats = mix->pkt->config.channels / mix->pkt->planes;
1820               nb_loops = mix->pkt->nb_samples;
1821               float delta = (*it)->m_fadingTarget - (*it)->m_fadingBase;
1822               int samples = m_internalFormat.m_sampleRate * (float)(*it)->m_fadingTime / 1000.0f;
1823               fadingStep = delta / samples;
1824             }
1825
1826             // for streams amplification of turned off downmix normalization
1827             // we need to run on a per sample basis
1828             if ((*it)->m_amplify != 1.0 || !(*it)->m_resampleBuffers->m_normalize)
1829             {
1830               nb_floats = out->pkt->config.channels / out->pkt->planes;
1831               nb_loops = out->pkt->nb_samples;
1832             }
1833
1834             for(int i=0; i<nb_loops; i++)
1835             {
1836               if ((*it)->m_fadingSamples > 0)
1837               {
1838                 (*it)->m_volume += fadingStep;
1839                 (*it)->m_fadingSamples--;
1840
1841                 if ((*it)->m_fadingSamples == 0)
1842                 {
1843                   // set variables being polled via stream interface
1844                   CSingleLock lock((*it)->m_streamLock);
1845                   (*it)->m_streamFading = false;
1846                 }
1847               }
1848
1849               // volume for stream
1850               float volume = (*it)->m_volume * (*it)->m_rgain;
1851               if(nb_loops > 1)
1852                 volume *= (*it)->m_limiter.Run((float**)mix->pkt->data, mix->pkt->config.channels, i*nb_floats, mix->pkt->planes > 1);
1853
1854               for(int j=0; j<out->pkt->planes && j<mix->pkt->planes; j++)
1855               {
1856                 float *dst = (float*)out->pkt->data[j]+i*nb_floats;
1857                 float *src = (float*)mix->pkt->data[j]+i*nb_floats;
1858 #ifdef __SSE__
1859                 CAEUtil::SSEMulAddArray(dst, src, volume, nb_floats);
1860                 for (int k = 0; k < nb_floats; ++k)
1861                 {
1862                   if (fabs(dst[k]) > 1.0f)
1863                   {
1864                     needClamp = true;
1865                     break;
1866                   }
1867                 }
1868 #else
1869                 for (int k = 0; k < nb_floats; ++k)
1870                 {
1871                   dst[k] += src[k] * volume;
1872                   if (fabs(dst[k]) > 1.0f)
1873                     needClamp = true;
1874                 }
1875 #endif
1876               }
1877             }
1878             mix->Return();
1879           }
1880           busy = true;
1881         }
1882       }// for
1883
1884       // finally clamp samples
1885       if(out && needClamp)
1886       {
1887         int nb_floats = out->pkt->nb_samples * out->pkt->config.channels / out->pkt->planes;
1888         for(int i=0; i<out->pkt->planes; i++)
1889         {
1890           CAEUtil::ClampArray((float*)out->pkt->data[i], nb_floats);
1891         }
1892       }
1893
1894       // process output buffer, gui sounds, encode, viz
1895       if (out)
1896       {
1897         // viz
1898         {
1899           CSingleLock lock(m_vizLock);
1900           if (m_audioCallback && m_vizBuffers && !m_streams.empty())
1901           {
1902             if (!m_vizInitialized)
1903             {
1904               m_audioCallback->OnInitialize(2, m_vizBuffers->m_format.m_sampleRate, 32);
1905               m_vizInitialized = true;
1906             }
1907
1908             if (!m_vizBuffersInput->m_freeSamples.empty())
1909             {
1910               // copy the samples into the viz input buffer
1911               CSampleBuffer *viz = m_vizBuffersInput->GetFreeBuffer();
1912               int samples = std::min(512, out->pkt->nb_samples);
1913               int bytes = samples * out->pkt->config.channels / out->pkt->planes * out->pkt->bytes_per_sample;
1914               for(int i= 0; i < out->pkt->planes; i++)
1915               {
1916                 memcpy(viz->pkt->data[i], out->pkt->data[i], bytes);
1917               }
1918               viz->pkt->nb_samples = samples;
1919               m_vizBuffers->m_inputSamples.push_back(viz);
1920             }
1921             else
1922               CLog::Log(LOGWARNING,"ActiveAE::%s - viz ran out of free buffers", __FUNCTION__);
1923             unsigned int now = XbmcThreads::SystemClockMillis();
1924             unsigned int timestamp = now + m_stats.GetDelay() * 1000;
1925             busy |= m_vizBuffers->ResampleBuffers(timestamp);
1926             while(!m_vizBuffers->m_outputSamples.empty())
1927             {
1928               CSampleBuffer *buf = m_vizBuffers->m_outputSamples.front();
1929               if ((now - buf->timestamp) & 0x80000000)
1930                 break;
1931               else
1932               {
1933                 int samples;
1934                 samples = std::min(512, buf->pkt->nb_samples);
1935                 m_audioCallback->OnAudioData((float*)(buf->pkt->data[0]), samples);
1936                 buf->Return();
1937                 m_vizBuffers->m_outputSamples.pop_front();
1938               }
1939             }
1940           }
1941           else if (m_vizBuffers)
1942             m_vizBuffers->Flush();
1943         }
1944
1945         // mix gui sounds
1946         MixSounds(*(out->pkt));
1947         if (!m_sinkHasVolume || m_muted)
1948           Deamplify(*(out->pkt));
1949
1950         if (m_mode == MODE_TRANSCODE && m_encoder)
1951         {
1952           CSampleBuffer *buf = m_encoderBuffers->GetFreeBuffer();
1953           m_encoder->Encode(out->pkt->data[0], out->pkt->planes*out->pkt->linesize,
1954                             buf->pkt->data[0], buf->pkt->planes*buf->pkt->linesize);
1955           buf->pkt->nb_samples = buf->pkt->max_nb_samples;
1956           out->Return();
1957           out = buf;
1958         }
1959         busy = true;
1960       }
1961
1962       // update stats
1963       if(out)
1964       {
1965         m_stats.AddSamples(out->pkt->nb_samples, m_streams);
1966         m_sinkBuffers->m_inputSamples.push_back(out);
1967       }
1968     }
1969     // pass through
1970     else
1971     {
1972       std::list<CActiveAEStream*>::iterator it;
1973       CSampleBuffer *buffer;
1974       for (it = m_streams.begin(); it != m_streams.end(); ++it)
1975       {
1976         if (!(*it)->m_resampleBuffers->m_outputSamples.empty())
1977         {
1978           buffer =  (*it)->m_resampleBuffers->m_outputSamples.front();
1979           (*it)->m_resampleBuffers->m_outputSamples.pop_front();
1980           m_stats.AddSamples(buffer->pkt->nb_samples, m_streams);
1981           m_sinkBuffers->m_inputSamples.push_back(buffer);
1982         }
1983       }
1984     }
1985
1986     // serve sink buffers
1987     busy = m_sinkBuffers->ResampleBuffers();
1988     while(!m_sinkBuffers->m_outputSamples.empty())
1989     {
1990       CSampleBuffer *out = NULL;
1991       out = m_sinkBuffers->m_outputSamples.front();
1992       m_sinkBuffers->m_outputSamples.pop_front();
1993       m_sink.m_dataPort.SendOutMessage(CSinkDataProtocol::SAMPLE,
1994           &out, sizeof(CSampleBuffer*));
1995       busy = true;
1996     }
1997   }
1998
1999   return busy;
2000 }
2001
2002 bool CActiveAE::HasWork()
2003 {
2004   if (!m_sounds_playing.empty())
2005     return true;
2006   if (!m_sinkBuffers->m_inputSamples.empty())
2007     return true;
2008   if (!m_sinkBuffers->m_outputSamples.empty())
2009     return true;
2010
2011   std::list<CActiveAEStream*>::iterator it;
2012   for (it = m_streams.begin(); it != m_streams.end(); ++it)
2013   {
2014     if (!(*it)->m_resampleBuffers->m_inputSamples.empty())
2015       return true;
2016     if (!(*it)->m_resampleBuffers->m_outputSamples.empty())
2017       return true;
2018     if (!(*it)->m_processingSamples.empty())
2019       return true;
2020   }
2021
2022   return false;
2023 }
2024
2025 void CActiveAE::MixSounds(CSoundPacket &dstSample)
2026 {
2027   if (m_sounds_playing.empty())
2028     return;
2029
2030   float volume;
2031   float *out;
2032   float *sample_buffer;
2033   int max_samples = dstSample.nb_samples;
2034
2035   std::list<SoundState>::iterator it;
2036   for (it = m_sounds_playing.begin(); it != m_sounds_playing.end(); )
2037   {
2038     if (!it->sound->IsConverted())
2039       ResampleSound(it->sound);
2040     int available_samples = it->sound->GetSound(false)->nb_samples - it->samples_played;
2041     int mix_samples = std::min(max_samples, available_samples);
2042     int start = it->samples_played *
2043                 m_dllAvUtil.av_get_bytes_per_sample(it->sound->GetSound(false)->config.fmt) *
2044                 it->sound->GetSound(false)->config.channels /
2045                 it->sound->GetSound(false)->planes;
2046
2047     for(int j=0; j<dstSample.planes; j++)
2048     {
2049       volume = it->sound->GetVolume();
2050       out = (float*)dstSample.data[j];
2051       sample_buffer = (float*)(it->sound->GetSound(false)->data[j]+start);
2052       int nb_floats = mix_samples * dstSample.config.channels / dstSample.planes;
2053 #ifdef __SSE__
2054       CAEUtil::SSEMulAddArray(out, sample_buffer, volume, nb_floats);
2055 #else
2056       for (int k = 0; k < nb_floats; ++k)
2057         *out++ += *sample_buffer++ * volume;
2058 #endif
2059     }
2060
2061     it->samples_played += mix_samples;
2062
2063     // no more frames, so remove it from the list
2064     if (it->samples_played >= it->sound->GetSound(false)->nb_samples)
2065     {
2066       it = m_sounds_playing.erase(it);
2067       continue;
2068     }
2069     ++it;
2070   }
2071 }
2072
2073 void CActiveAE::Deamplify(CSoundPacket &dstSample)
2074 {
2075   if (m_volumeScaled < 1.0 || m_muted)
2076   {
2077     float *buffer;
2078     int nb_floats = dstSample.nb_samples * dstSample.config.channels / dstSample.planes;
2079     float volume = m_muted ? 0.0f : m_volumeScaled;
2080
2081     for(int j=0; j<dstSample.planes; j++)
2082     {
2083       buffer = (float*)dstSample.data[j];
2084 #ifdef __SSE__
2085       CAEUtil::SSEMulArray(buffer, volume, nb_floats);
2086 #else
2087       float *fbuffer = buffer;
2088       for (int i = 0; i < nb_floats; i++)
2089         *fbuffer++ *= volume;
2090 #endif
2091     }
2092   }
2093 }
2094
2095 //-----------------------------------------------------------------------------
2096 // Configuration
2097 //-----------------------------------------------------------------------------
2098
2099 void CActiveAE::LoadSettings()
2100 {
2101   m_settings.device = CSettings::Get().GetString("audiooutput.audiodevice");
2102   m_settings.passthoughdevice = CSettings::Get().GetString("audiooutput.passthroughdevice");
2103
2104   m_settings.config = CSettings::Get().GetInt("audiooutput.config");
2105   m_settings.channels = (m_sink.GetDeviceType(m_settings.device) == AE_DEVTYPE_IEC958) ? AE_CH_LAYOUT_2_0 : CSettings::Get().GetInt("audiooutput.channels");
2106   m_settings.samplerate = CSettings::Get().GetInt("audiooutput.samplerate");
2107
2108   m_settings.stereoupmix = IsSettingVisible("audiooutput.stereoupmix") ? CSettings::Get().GetBool("audiooutput.stereoupmix") : false;
2109   m_settings.normalizelevels = CSettings::Get().GetBool("audiooutput.normalizelevels");
2110   m_settings.guisoundmode = CSettings::Get().GetInt("audiooutput.guisoundmode");
2111
2112   m_settings.passthrough = m_settings.config == AE_CONFIG_FIXED ? false : CSettings::Get().GetBool("audiooutput.passthrough");
2113   if (!m_sink.HasPassthroughDevice())
2114     m_settings.passthrough = false;
2115   m_settings.ac3passthrough = CSettings::Get().GetBool("audiooutput.ac3passthrough");
2116   m_settings.ac3transcode = CSettings::Get().GetBool("audiooutput.ac3transcode");
2117   m_settings.eac3passthrough = CSettings::Get().GetBool("audiooutput.eac3passthrough");
2118   m_settings.truehdpassthrough = CSettings::Get().GetBool("audiooutput.truehdpassthrough");
2119   m_settings.dtspassthrough = CSettings::Get().GetBool("audiooutput.dtspassthrough");
2120   m_settings.dtshdpassthrough = CSettings::Get().GetBool("audiooutput.dtshdpassthrough");
2121
2122   m_settings.resampleQuality = static_cast<AEQuality>(CSettings::Get().GetInt("audiooutput.processquality"));
2123 }
2124
2125 bool CActiveAE::Initialize()
2126 {
2127   if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllAvFormat.Load())
2128   {
2129     CLog::Log(LOGERROR,"CActiveAE::Initialize - failed to load ffmpeg libraries");
2130     return false;
2131   }
2132   m_dllAvFormat.av_register_all();
2133
2134   Create();
2135   Message *reply;
2136   if (m_controlPort.SendOutMessageSync(CActiveAEControlProtocol::INIT,
2137                                                  &reply,
2138                                                  10000))
2139   {
2140     bool success = reply->signal == CActiveAEControlProtocol::ACC;
2141     reply->Release();
2142     if (!success)
2143     {
2144       CLog::Log(LOGERROR, "ActiveAE::%s - returned error", __FUNCTION__);
2145       Dispose();
2146       return false;
2147     }
2148   }
2149   else
2150   {
2151     CLog::Log(LOGERROR, "ActiveAE::%s - failed to init", __FUNCTION__);
2152     Dispose();
2153     return false;
2154   }
2155
2156   // hook into windowing for receiving display reset events
2157 #if defined(HAS_GLX) || defined(TARGET_DARWIN) 
2158   g_Windowing.Register(this);
2159 #endif
2160
2161   m_inMsgEvent.Reset();
2162   return true;
2163 }
2164
2165 void CActiveAE::EnumerateOutputDevices(AEDeviceList &devices, bool passthrough)
2166 {
2167   m_sink.EnumerateOutputDevices(devices, passthrough);
2168 }
2169
2170 std::string CActiveAE::GetDefaultDevice(bool passthrough)
2171 {
2172   return m_sink.GetDefaultDevice(passthrough);
2173 }
2174
2175 void CActiveAE::OnSettingsChange(const std::string& setting)
2176 {
2177   if (setting == "audiooutput.passthroughdevice" ||
2178       setting == "audiooutput.audiodevice"       ||
2179       setting == "audiooutput.config"            ||
2180       setting == "audiooutput.ac3passthrough"    ||
2181       setting == "audiooutput.ac3transcode"      ||
2182       setting == "audiooutput.eac3passthrough"   ||
2183       setting == "audiooutput.dtspassthrough"    ||
2184       setting == "audiooutput.truehdpassthrough" ||
2185       setting == "audiooutput.dtshdpassthrough"  ||
2186       setting == "audiooutput.channels"          ||
2187       setting == "audiooutput.stereoupmix"       ||
2188       setting == "audiooutput.streamsilence"     ||
2189       setting == "audiooutput.processquality"    ||
2190       setting == "audiooutput.passthrough"       ||
2191       setting == "audiooutput.samplerate"        ||
2192       setting == "audiooutput.normalizelevels"   ||
2193       setting == "audiooutput.guisoundmode")
2194   {
2195     m_controlPort.SendOutMessage(CActiveAEControlProtocol::RECONFIGURE);
2196   }
2197 }
2198
2199 bool CActiveAE::SupportsRaw(AEDataFormat format, int samplerate)
2200 {
2201   if (!m_sink.SupportsFormat(CSettings::Get().GetString("audiooutput.passthroughdevice"), format, samplerate))
2202     return false;
2203
2204   return true;
2205 }
2206
2207 bool CActiveAE::SupportsSilenceTimeout()
2208 {
2209   return true;
2210 }
2211
2212 bool CActiveAE::SupportsQualityLevel(enum AEQuality level)
2213 {
2214   if (level == AE_QUALITY_LOW || level == AE_QUALITY_MID || level == AE_QUALITY_HIGH)
2215     return true;
2216
2217   return false;
2218 }
2219
2220 bool CActiveAE::IsSettingVisible(const std::string &settingId)
2221 {
2222   if (settingId == "audiooutput.samplerate")
2223   {
2224     if (m_sink.GetDeviceType(CSettings::Get().GetString("audiooutput.audiodevice")) == AE_DEVTYPE_IEC958)
2225       return true;
2226     if (CSettings::Get().GetInt("audiooutput.config") == AE_CONFIG_FIXED)
2227       return true;
2228   }
2229   else if (settingId == "audiooutput.channels")
2230   {
2231     if (m_sink.GetDeviceType(CSettings::Get().GetString("audiooutput.audiodevice")) != AE_DEVTYPE_IEC958)
2232       return true;
2233   }
2234   else if (settingId == "audiooutput.passthrough")
2235   {
2236     if (m_sink.HasPassthroughDevice() && CSettings::Get().GetInt("audiooutput.config") != AE_CONFIG_FIXED)
2237       return true;
2238   }
2239   else if (settingId == "audiooutput.truehdpassthrough")
2240   {
2241     if (m_sink.SupportsFormat(CSettings::Get().GetString("audiooutput.passthroughdevice"), AE_FMT_TRUEHD, 192000) &&
2242         CSettings::Get().GetInt("audiooutput.config") != AE_CONFIG_FIXED)
2243       return true;
2244   }
2245   else if (settingId == "audiooutput.dtshdpassthrough")
2246   {
2247     if (m_sink.SupportsFormat(CSettings::Get().GetString("audiooutput.passthroughdevice"), AE_FMT_DTSHD, 192000) &&
2248         CSettings::Get().GetInt("audiooutput.config") != AE_CONFIG_FIXED)
2249       return true;
2250   }
2251   else if (settingId == "audiooutput.eac3passthrough")
2252   {
2253     if (m_sink.SupportsFormat(CSettings::Get().GetString("audiooutput.passthroughdevice"), AE_FMT_EAC3, 192000) &&
2254         CSettings::Get().GetInt("audiooutput.config") != AE_CONFIG_FIXED)
2255       return true;
2256   }
2257   else if (settingId == "audiooutput.stereoupmix")
2258   {
2259     if (m_sink.HasPassthroughDevice() ||
2260         CSettings::Get().GetInt("audiooutput.channels") > AE_CH_LAYOUT_2_0)
2261     return true;
2262   }
2263   else if (settingId == "audiooutput.ac3transcode")
2264   {
2265     if (m_sink.HasPassthroughDevice() &&
2266         CSettings::Get().GetBool("audiooutput.ac3passthrough") &&
2267         CSettings::Get().GetInt("audiooutput.config") != AE_CONFIG_FIXED &&
2268         (CSettings::Get().GetInt("audiooutput.channels") <= AE_CH_LAYOUT_2_0 || m_sink.GetDeviceType(CSettings::Get().GetString("audiooutput.audiodevice")) == AE_DEVTYPE_IEC958))
2269       return true;
2270   }
2271   return false;
2272 }
2273
2274 void CActiveAE::Shutdown()
2275 {
2276   Dispose();
2277 }
2278
2279 bool CActiveAE::Suspend()
2280 {
2281   return m_controlPort.SendOutMessage(CActiveAEControlProtocol::SUSPEND);
2282 }
2283
2284 bool CActiveAE::Resume()
2285 {
2286   Message *reply;
2287   if (m_controlPort.SendOutMessageSync(CActiveAEControlProtocol::INIT,
2288                                                  &reply,
2289                                                  5000))
2290   {
2291     bool success = reply->signal == CActiveAEControlProtocol::ACC;
2292     reply->Release();
2293     if (!success)
2294     {
2295       CLog::Log(LOGERROR, "ActiveAE::%s - returned error", __FUNCTION__);
2296       return false;
2297     }
2298   }
2299   else
2300   {
2301     CLog::Log(LOGERROR, "ActiveAE::%s - failed to init", __FUNCTION__);
2302     return false;
2303   }
2304
2305   m_inMsgEvent.Reset();
2306   return true;
2307 }
2308
2309 bool CActiveAE::IsSuspended()
2310 {
2311   return m_stats.IsSuspended();
2312 }
2313
2314 float CActiveAE::GetVolume()
2315 {
2316   return m_aeVolume;
2317 }
2318
2319 void CActiveAE::SetVolume(const float volume)
2320 {
2321   m_aeVolume = std::max( 0.0f, std::min(1.0f, volume));
2322   m_controlPort.SendOutMessage(CActiveAEControlProtocol::VOLUME, &m_aeVolume, sizeof(float));
2323 }
2324
2325 void CActiveAE::SetMute(const bool enabled)
2326 {
2327   m_aeMuted = enabled;
2328   m_controlPort.SendOutMessage(CActiveAEControlProtocol::MUTE, &m_aeMuted, sizeof(bool));
2329 }
2330
2331 bool CActiveAE::IsMuted()
2332 {
2333   return m_aeMuted;
2334 }
2335
2336 void CActiveAE::SetSoundMode(const int mode)
2337 {
2338   return;
2339 }
2340
2341 void CActiveAE::KeepConfiguration(unsigned int millis)
2342 {
2343   unsigned int timeMs = millis;
2344   m_controlPort.SendOutMessage(CActiveAEControlProtocol::KEEPCONFIG, &timeMs, sizeof(unsigned int));
2345 }
2346
2347 void CActiveAE::DeviceChange()
2348 {
2349   m_controlPort.SendOutMessage(CActiveAEControlProtocol::DEVICECHANGE);
2350 }
2351
2352 void CActiveAE::OnLostDevice()
2353 {
2354   Message *reply;
2355   if (m_controlPort.SendOutMessageSync(CActiveAEControlProtocol::DISPLAYLOST,
2356                                                  &reply,
2357                                                  5000))
2358   {
2359     bool success = reply->signal == CActiveAEControlProtocol::ACC;
2360     reply->Release();
2361     if (!success)
2362     {
2363       CLog::Log(LOGERROR, "ActiveAE::%s - returned error", __FUNCTION__);
2364     }
2365   }
2366   else
2367   {
2368     CLog::Log(LOGERROR, "ActiveAE::%s - timed out", __FUNCTION__);
2369   }
2370 }
2371
2372 void CActiveAE::OnResetDevice()
2373 {
2374   m_controlPort.SendOutMessage(CActiveAEControlProtocol::DISPLAYRESET);
2375 }
2376
2377 void CActiveAE::OnAppFocusChange(bool focus)
2378 {
2379   m_controlPort.SendOutMessage(CActiveAEControlProtocol::APPFOCUSED, &focus, sizeof(focus));
2380 }
2381
2382 //-----------------------------------------------------------------------------
2383 // Utils
2384 //-----------------------------------------------------------------------------
2385
2386 uint8_t **CActiveAE::AllocSoundSample(SampleConfig &config, int &samples, int &bytes_per_sample, int &planes, int &linesize)
2387 {
2388   uint8_t **buffer;
2389   planes = m_dllAvUtil.av_sample_fmt_is_planar(config.fmt) ? config.channels : 1;
2390   buffer = new uint8_t*[planes];
2391
2392   // align buffer to 16 in order to be compatible with sse in CAEConvert
2393   m_dllAvUtil.av_samples_alloc(buffer, &linesize, config.channels,
2394                                  samples, config.fmt, 16);
2395   bytes_per_sample = m_dllAvUtil.av_get_bytes_per_sample(config.fmt);
2396   return buffer;
2397 }
2398
2399 void CActiveAE::FreeSoundSample(uint8_t **data)
2400 {
2401   m_dllAvUtil.av_freep(data);
2402   delete [] data;
2403 }
2404
2405 bool CActiveAE::CompareFormat(AEAudioFormat &lhs, AEAudioFormat &rhs)
2406 {
2407   if (lhs.m_channelLayout != rhs.m_channelLayout ||
2408       lhs.m_dataFormat != rhs.m_dataFormat ||
2409       lhs.m_sampleRate != rhs.m_sampleRate)
2410     return false;
2411   else
2412     return true;
2413 }
2414
2415 //-----------------------------------------------------------------------------
2416 // GUI Sounds
2417 //-----------------------------------------------------------------------------
2418
2419 /**
2420  * load sound from an audio file and store original format
2421  * register the sound in ActiveAE
2422  * later when the engine is idle it will convert the sound to sink format
2423  */
2424
2425 #define SOUNDBUFFER_SIZE 20480
2426
2427 IAESound *CActiveAE::MakeSound(const std::string& file)
2428 {
2429   AVFormatContext *fmt_ctx = NULL;
2430   AVCodecContext *dec_ctx = NULL;
2431   AVIOContext *io_ctx;
2432   AVInputFormat *io_fmt;
2433   AVCodec *dec = NULL;
2434   CActiveAESound *sound = NULL;
2435   SampleConfig config;
2436
2437   sound = new CActiveAESound(file);
2438   if (!sound->Prepare())
2439   {
2440     delete sound;
2441     return NULL;
2442   }
2443   int fileSize = sound->GetFileSize();
2444
2445   fmt_ctx = m_dllAvFormat.avformat_alloc_context();
2446   unsigned char* buffer = (unsigned char*)m_dllAvUtil.av_malloc(SOUNDBUFFER_SIZE+FF_INPUT_BUFFER_PADDING_SIZE);
2447   io_ctx = m_dllAvFormat.avio_alloc_context(buffer, SOUNDBUFFER_SIZE, 0,
2448                                             sound, CActiveAESound::Read, NULL, CActiveAESound::Seek);
2449   io_ctx->max_packet_size = sound->GetChunkSize();
2450   if(io_ctx->max_packet_size)
2451     io_ctx->max_packet_size *= SOUNDBUFFER_SIZE / io_ctx->max_packet_size;
2452
2453   if(!sound->IsSeekPosible())
2454     io_ctx->seekable = 0;
2455
2456   fmt_ctx->pb = io_ctx;
2457
2458   m_dllAvFormat.av_probe_input_buffer(io_ctx, &io_fmt, file.c_str(), NULL, 0, 0);
2459   if (!io_fmt)
2460   {
2461     m_dllAvFormat.avformat_close_input(&fmt_ctx);
2462     delete sound;
2463     return NULL;
2464   }
2465
2466   // find decoder
2467   if (m_dllAvFormat.avformat_open_input(&fmt_ctx, file.c_str(), NULL, NULL) == 0)
2468   {
2469     fmt_ctx->flags |= AVFMT_FLAG_NOPARSE;
2470     if (m_dllAvFormat.avformat_find_stream_info(fmt_ctx, NULL) >= 0)
2471     {
2472       dec_ctx = fmt_ctx->streams[0]->codec;
2473       dec = m_dllAvCodec.avcodec_find_decoder(dec_ctx->codec_id);
2474       config.sample_rate = dec_ctx->sample_rate;
2475       config.channels = dec_ctx->channels;
2476       config.channel_layout = dec_ctx->channel_layout;
2477     }
2478   }
2479   if (dec == NULL)
2480   {
2481     m_dllAvFormat.avformat_close_input(&fmt_ctx);
2482     delete sound;
2483     return NULL;
2484   }
2485
2486   dec_ctx = m_dllAvCodec.avcodec_alloc_context3(dec);
2487   dec_ctx->sample_rate = config.sample_rate;
2488   dec_ctx->channels = config.channels;
2489   if (!config.channel_layout)
2490     config.channel_layout = m_dllAvUtil.av_get_default_channel_layout(config.channels);
2491   dec_ctx->channel_layout = config.channel_layout;
2492
2493   AVPacket avpkt;
2494   AVFrame *decoded_frame = NULL;
2495   decoded_frame = m_dllAvCodec.avcodec_alloc_frame();
2496
2497   if (m_dllAvCodec.avcodec_open2(dec_ctx, dec, NULL) >= 0)
2498   {
2499     bool init = false;
2500
2501     // decode until eof
2502     m_dllAvCodec.av_init_packet(&avpkt);
2503     int len;
2504     while (m_dllAvFormat.av_read_frame(fmt_ctx, &avpkt) >= 0)
2505     {
2506       int got_frame = 0;
2507       len = m_dllAvCodec.avcodec_decode_audio4(dec_ctx, decoded_frame, &got_frame, &avpkt);
2508       if (len < 0)
2509       {
2510         m_dllAvCodec.avcodec_close(dec_ctx);
2511         m_dllAvUtil.av_free(dec_ctx);
2512         m_dllAvUtil.av_free(&decoded_frame);
2513         m_dllAvFormat.avformat_close_input(&fmt_ctx);
2514         delete sound;
2515         return NULL;
2516       }
2517       if (got_frame)
2518       {
2519         if (!init)
2520         {
2521           int samples = fileSize / m_dllAvUtil.av_get_bytes_per_sample(dec_ctx->sample_fmt) / config.channels;
2522           config.fmt = dec_ctx->sample_fmt;
2523           config.bits_per_sample = dec_ctx->bits_per_coded_sample;
2524           sound->InitSound(true, config, samples);
2525           init = true;
2526         }
2527         sound->StoreSound(true, decoded_frame->extended_data,
2528                           decoded_frame->nb_samples, decoded_frame->linesize[0]);
2529       }
2530     }
2531     m_dllAvCodec.avcodec_close(dec_ctx);
2532   }
2533
2534   m_dllAvUtil.av_free(dec_ctx);
2535   m_dllAvUtil.av_free(decoded_frame);
2536   m_dllAvFormat.avformat_close_input(&fmt_ctx);
2537
2538   sound->Finish();
2539
2540   // register sound
2541   m_dataPort.SendOutMessage(CActiveAEDataProtocol::NEWSOUND, &sound, sizeof(CActiveAESound*));
2542
2543   return sound;
2544 }
2545
2546 void CActiveAE::FreeSound(IAESound *sound)
2547 {
2548   m_dataPort.SendOutMessage(CActiveAEDataProtocol::FREESOUND, &sound, sizeof(CActiveAESound*));
2549 }
2550
2551 void CActiveAE::PlaySound(CActiveAESound *sound)
2552 {
2553   m_dataPort.SendOutMessage(CActiveAEDataProtocol::PLAYSOUND, &sound, sizeof(CActiveAESound*));
2554 }
2555
2556 void CActiveAE::StopSound(CActiveAESound *sound)
2557 {
2558   m_controlPort.SendOutMessage(CActiveAEControlProtocol::STOPSOUND, &sound, sizeof(CActiveAESound*));
2559 }
2560
2561 /**
2562  * resample sounds to destination format for mixing
2563  * destination format is either format of stream or
2564  * default sink format when no stream is playing
2565  */
2566 void CActiveAE::ResampleSounds()
2567 {
2568   if (m_settings.guisoundmode == AE_SOUND_OFF ||
2569      (m_settings.guisoundmode == AE_SOUND_IDLE && !m_streams.empty()))
2570     return;
2571
2572   std::vector<CActiveAESound*>::iterator it;
2573   for (it = m_sounds.begin(); it != m_sounds.end(); ++it)
2574   {
2575     if (!(*it)->IsConverted())
2576     {
2577       ResampleSound(*it);
2578       // only do one sound, then yield to main loop
2579       break;
2580     }
2581   }
2582 }
2583
2584 bool CActiveAE::ResampleSound(CActiveAESound *sound)
2585 {
2586   SampleConfig orig_config, dst_config;
2587   uint8_t **dst_buffer;
2588   int dst_samples;
2589
2590   if (m_mode == MODE_RAW || m_internalFormat.m_dataFormat == AE_FMT_INVALID)
2591     return false;
2592
2593   if (!sound->GetSound(true))
2594     return false;
2595
2596   orig_config = sound->GetSound(true)->config;
2597
2598   dst_config.channel_layout = CActiveAEResample::GetAVChannelLayout(m_internalFormat.m_channelLayout);
2599   dst_config.channels = m_internalFormat.m_channelLayout.Count();
2600   dst_config.sample_rate = m_internalFormat.m_sampleRate;
2601   dst_config.fmt = CActiveAEResample::GetAVSampleFormat(m_internalFormat.m_dataFormat);
2602   dst_config.bits_per_sample = CAEUtil::DataFormatToUsedBits(m_internalFormat.m_dataFormat);
2603
2604   CActiveAEResample *resampler = new CActiveAEResample();
2605   resampler->Init(dst_config.channel_layout,
2606                   dst_config.channels,
2607                   dst_config.sample_rate,
2608                   dst_config.fmt,
2609                   dst_config.bits_per_sample,
2610                   orig_config.channel_layout,
2611                   orig_config.channels,
2612                   orig_config.sample_rate,
2613                   orig_config.fmt,
2614                   orig_config.bits_per_sample,
2615                   false,
2616                   true,
2617                   NULL,
2618                   m_settings.resampleQuality);
2619
2620   dst_samples = resampler->CalcDstSampleCount(sound->GetSound(true)->nb_samples,
2621                                               m_internalFormat.m_sampleRate,
2622                                               orig_config.sample_rate);
2623
2624   dst_buffer = sound->InitSound(false, dst_config, dst_samples);
2625   if (!dst_buffer)
2626   {
2627     delete resampler;
2628     return false;
2629   }
2630   int samples = resampler->Resample(dst_buffer, dst_samples,
2631                                     sound->GetSound(true)->data,
2632                                     sound->GetSound(true)->nb_samples,
2633                                     1.0);
2634
2635   sound->GetSound(false)->nb_samples = samples;
2636
2637   delete resampler;
2638   sound->SetConverted(true);
2639   return true;
2640 }
2641
2642 //-----------------------------------------------------------------------------
2643 // Streams
2644 //-----------------------------------------------------------------------------
2645
2646 IAEStream *CActiveAE::MakeStream(enum AEDataFormat dataFormat, unsigned int sampleRate, unsigned int encodedSampleRate, CAEChannelInfo channelLayout, unsigned int options)
2647 {
2648   if (IsSuspended())
2649     return NULL;
2650
2651   //TODO: pass number of samples in audio packet
2652
2653   AEAudioFormat format;
2654   format.m_dataFormat = dataFormat;
2655   format.m_sampleRate = sampleRate;
2656   format.m_encodedRate = encodedSampleRate;
2657   format.m_channelLayout = channelLayout;
2658   format.m_frames = format.m_sampleRate / 10;
2659   format.m_frameSize = format.m_channelLayout.Count() *
2660                        (CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3);
2661
2662   MsgStreamNew msg;
2663   msg.format = format;
2664   msg.options = options;
2665
2666   Message *reply;
2667   if (m_dataPort.SendOutMessageSync(CActiveAEDataProtocol::NEWSTREAM,
2668                                     &reply,10000,
2669                                     &msg, sizeof(MsgStreamNew)))
2670   {
2671     bool success = reply->signal == CActiveAEControlProtocol::ACC;
2672     if (success)
2673     {
2674       CActiveAEStream *stream = *(CActiveAEStream**)reply->data;
2675       reply->Release();
2676       return stream;
2677     }
2678     reply->Release();
2679   }
2680
2681   CLog::Log(LOGERROR, "ActiveAE::%s - could not create stream", __FUNCTION__);
2682   return NULL;
2683 }
2684
2685 IAEStream *CActiveAE::FreeStream(IAEStream *stream)
2686 {
2687   m_dataPort.SendOutMessage(CActiveAEDataProtocol::FREESTREAM, &stream, sizeof(IAEStream*));
2688   return NULL;
2689 }
2690
2691 void CActiveAE::FlushStream(CActiveAEStream *stream)
2692 {
2693   Message *reply;
2694   if (m_controlPort.SendOutMessageSync(CActiveAEControlProtocol::FLUSHSTREAM,
2695                                        &reply,1000,
2696                                        &stream, sizeof(CActiveAEStream*)))
2697   {
2698     bool success = reply->signal == CActiveAEControlProtocol::ACC;
2699     reply->Release();
2700     if (!success)
2701     {
2702       CLog::Log(LOGERROR, "CActiveAE::FlushStream - failed");
2703     }
2704   }
2705 }
2706
2707 void CActiveAE::PauseStream(CActiveAEStream *stream, bool pause)
2708 {
2709   // TODO pause sink, needs api change
2710   if (pause)
2711     m_controlPort.SendOutMessage(CActiveAEControlProtocol::PAUSESTREAM,
2712                                    &stream, sizeof(CActiveAEStream*));
2713   else
2714     m_controlPort.SendOutMessage(CActiveAEControlProtocol::RESUMESTREAM,
2715                                    &stream, sizeof(CActiveAEStream*));
2716 }
2717
2718 void CActiveAE::SetStreamAmplification(CActiveAEStream *stream, float amplify)
2719 {
2720   MsgStreamParameter msg;
2721   msg.stream = stream;
2722   msg.parameter.float_par = amplify;
2723   m_controlPort.SendOutMessage(CActiveAEControlProtocol::STREAMAMP,
2724                                      &msg, sizeof(MsgStreamParameter));
2725 }
2726
2727 void CActiveAE::SetStreamReplaygain(CActiveAEStream *stream, float rgain)
2728 {
2729   MsgStreamParameter msg;
2730   msg.stream = stream;
2731   msg.parameter.float_par = rgain;
2732   m_controlPort.SendOutMessage(CActiveAEControlProtocol::STREAMRGAIN,
2733                                      &msg, sizeof(MsgStreamParameter));
2734 }
2735
2736 void CActiveAE::SetStreamVolume(CActiveAEStream *stream, float volume)
2737 {
2738   MsgStreamParameter msg;
2739   msg.stream = stream;
2740   msg.parameter.float_par = volume;
2741   m_controlPort.SendOutMessage(CActiveAEControlProtocol::STREAMVOLUME,
2742                                      &msg, sizeof(MsgStreamParameter));
2743 }
2744
2745 void CActiveAE::SetStreamResampleRatio(CActiveAEStream *stream, double ratio)
2746 {
2747   MsgStreamParameter msg;
2748   msg.stream = stream;
2749   msg.parameter.double_par = ratio;
2750   m_controlPort.SendOutMessage(CActiveAEControlProtocol::STREAMRESAMPLERATIO,
2751                                      &msg, sizeof(MsgStreamParameter));
2752 }
2753
2754 void CActiveAE::SetStreamFade(CActiveAEStream *stream, float from, float target, unsigned int millis)
2755 {
2756   MsgStreamFade msg;
2757   msg.stream = stream;
2758   msg.from = from;
2759   msg.target = target;
2760   msg.millis = millis;
2761   m_controlPort.SendOutMessage(CActiveAEControlProtocol::STREAMFADE,
2762                                      &msg, sizeof(MsgStreamFade));
2763 }
2764
2765 void CActiveAE::RegisterAudioCallback(IAudioCallback* pCallback)
2766 {
2767   CSingleLock lock(m_vizLock);
2768   m_audioCallback = pCallback;
2769   m_vizInitialized = false;
2770 }
2771
2772 void CActiveAE::UnregisterAudioCallback()
2773 {
2774   CSingleLock lock(m_vizLock);
2775   m_audioCallback = NULL;
2776 }