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