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