Merge pull request #4314 from MartijnKaijser/beta1
[vuplus_xbmc] / xbmc / cores / AudioEngine / AEFactory.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 #include "system.h"
21
22 #include "AEFactory.h"
23 #include "Utils/AEUtil.h"
24
25 #include "Engines/ActiveAE/ActiveAE.h"
26
27 #include "guilib/LocalizeStrings.h"
28 #include "settings/lib/Setting.h"
29 #include "settings/Settings.h"
30 #include "utils/StringUtils.h"
31
32 IAE* CAEFactory::AE = NULL;
33 static float  g_fVolume = 1.0f;
34 static bool   g_bMute = false;
35
36 IAE *CAEFactory::GetEngine()
37 {
38   return AE;
39 }
40
41 bool CAEFactory::LoadEngine()
42 {
43   return CAEFactory::LoadEngine(AE_ENGINE_ACTIVE);
44 }
45
46 bool CAEFactory::LoadEngine(enum AEEngine engine)
47 {
48   /* can only load the engine once, XBMC restart is required to change it */
49   if (AE)
50     return false;
51
52   switch(engine)
53   {
54     case AE_ENGINE_NULL     :
55     case AE_ENGINE_ACTIVE   : AE = new ActiveAE::CActiveAE(); break;
56     default:
57       return false;
58   }
59
60   if (AE && !AE->CanInit())
61   {
62     delete AE;
63     AE = NULL;
64   }
65
66   return AE != NULL;
67 }
68
69 void CAEFactory::UnLoadEngine()
70 {
71   if(AE)
72   {
73     AE->Shutdown();
74     delete AE;
75     AE = NULL;
76   }
77 }
78
79 bool CAEFactory::StartEngine()
80 {
81   if (!AE)
82     return false;
83
84   if (AE->Initialize())
85     return true;
86
87   delete AE;
88   AE = NULL;
89   return false;
90 }
91
92 bool CAEFactory::Suspend()
93 {
94   if(AE)
95     return AE->Suspend();
96
97   return false;
98 }
99
100 bool CAEFactory::Resume()
101 {
102   if(AE)
103     return AE->Resume();
104
105   return false;
106 }
107
108 bool CAEFactory::IsSuspended()
109 {
110   if(AE)
111     return AE->IsSuspended();
112
113   /* No engine to process audio */
114   return true;
115 }
116
117 /* engine wrapping */
118 IAESound *CAEFactory::MakeSound(const std::string &file)
119 {
120   if(AE)
121     return AE->MakeSound(file);
122   
123   return NULL;
124 }
125
126 void CAEFactory::FreeSound(IAESound *sound)
127 {
128   if(AE)
129     AE->FreeSound(sound);
130 }
131
132 void CAEFactory::SetSoundMode(const int mode)
133 {
134   if(AE)
135     AE->SetSoundMode(mode);
136 }
137
138 void CAEFactory::OnSettingsChange(std::string setting)
139 {
140   if(AE)
141     AE->OnSettingsChange(setting);
142 }
143
144 void CAEFactory::EnumerateOutputDevices(AEDeviceList &devices, bool passthrough)
145 {
146   if(AE)
147     AE->EnumerateOutputDevices(devices, passthrough);
148 }
149
150 void CAEFactory::VerifyOutputDevice(std::string &device, bool passthrough)
151 {
152   AEDeviceList devices;
153   EnumerateOutputDevices(devices, passthrough);
154   std::string firstDevice;
155
156   for (AEDeviceList::const_iterator deviceIt = devices.begin(); deviceIt != devices.end(); ++deviceIt)
157   {
158     /* remember the first device so we can default to it if required */
159     if (firstDevice.empty())
160       firstDevice = deviceIt->second;
161
162     if (deviceIt->second == device)
163       return;
164     else if (deviceIt->first == device)
165     {
166       device = deviceIt->second;
167       return;
168     }
169   }
170
171   /* if the device wasnt found, set it to the first viable output */
172   device = firstDevice;
173 }
174
175 std::string CAEFactory::GetDefaultDevice(bool passthrough)
176 {
177   if(AE)
178     return AE->GetDefaultDevice(passthrough);
179
180   return "default";
181 }
182
183 bool CAEFactory::SupportsRaw(AEDataFormat format)
184 {
185   // check if passthrough is enabled
186   if (!CSettings::Get().GetBool("audiooutput.passthrough"))
187     return false;
188
189   // fixed config disabled passthrough
190   if (CSettings::Get().GetInt("audiooutput.config") == AE_CONFIG_FIXED)
191     return false;
192
193   // check if the format is enabled in settings
194   if (format == AE_FMT_AC3 && !CSettings::Get().GetBool("audiooutput.ac3passthrough"))
195     return false;
196   if (format == AE_FMT_DTS && !CSettings::Get().GetBool("audiooutput.dtspassthrough"))
197     return false;
198   if (format == AE_FMT_EAC3 && !CSettings::Get().GetBool("audiooutput.eac3passthrough"))
199     return false;
200   if (format == AE_FMT_TRUEHD && !CSettings::Get().GetBool("audiooutput.truehdpassthrough"))
201     return false;
202   if (format == AE_FMT_DTSHD && !CSettings::Get().GetBool("audiooutput.dtshdpassthrough"))
203     return false;
204
205   if(AE)
206     return AE->SupportsRaw(format);
207
208   return false;
209 }
210
211 bool CAEFactory::SupportsSilenceTimeout()
212 {
213   if(AE)
214     return AE->SupportsSilenceTimeout();
215
216   return false;
217 }
218
219 /**
220   * Returns true if current AudioEngine supports at lest two basic quality levels
221   * @return true if quality setting is supported, otherwise false
222   */
223 bool CAEFactory::SupportsQualitySetting(void) 
224 {
225   if (!AE)
226     return false;
227
228   return ((AE->SupportsQualityLevel(AE_QUALITY_LOW)? 1 : 0) + 
229           (AE->SupportsQualityLevel(AE_QUALITY_MID)? 1 : 0) +
230           (AE->SupportsQualityLevel(AE_QUALITY_HIGH)? 1 : 0)) >= 2; 
231 }
232   
233 void CAEFactory::SetMute(const bool enabled)
234 {
235   if(AE)
236     AE->SetMute(enabled);
237
238   g_bMute = enabled;
239 }
240
241 bool CAEFactory::IsMuted()
242 {
243   if(AE)
244     return AE->IsMuted();
245
246   return g_bMute || (g_fVolume == 0.0f);
247 }
248
249 float CAEFactory::GetVolume()
250 {
251   if(AE)
252     return AE->GetVolume();
253
254   return g_fVolume;
255 }
256
257 void CAEFactory::SetVolume(const float volume)
258 {
259   if(AE)
260     AE->SetVolume(volume);
261   else
262     g_fVolume = volume;
263 }
264
265 void CAEFactory::Shutdown()
266 {
267   if(AE)
268     AE->Shutdown();
269 }
270
271 IAEStream *CAEFactory::MakeStream(enum AEDataFormat dataFormat, unsigned int sampleRate, 
272   unsigned int encodedSampleRate, CAEChannelInfo channelLayout, unsigned int options)
273 {
274   if(AE)
275     return AE->MakeStream(dataFormat, sampleRate, encodedSampleRate, channelLayout, options);
276
277   return NULL;
278 }
279
280 IAEStream *CAEFactory::FreeStream(IAEStream *stream)
281 {
282   if(AE)
283     return AE->FreeStream(stream);
284
285   return NULL;
286 }
287
288 void CAEFactory::GarbageCollect()
289 {
290   if(AE)
291     AE->GarbageCollect();
292 }
293
294 void CAEFactory::SettingOptionsAudioDevicesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string &current)
295 {
296   SettingOptionsAudioDevicesFillerGeneral(setting, list, current, false);
297 }
298
299 void CAEFactory::SettingOptionsAudioDevicesPassthroughFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string &current)
300 {
301   SettingOptionsAudioDevicesFillerGeneral(setting, list, current, true);
302 }
303
304 void CAEFactory::SettingOptionsAudioQualityLevelsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current)
305 {
306   if (!AE)
307     return;
308
309   if(AE->SupportsQualityLevel(AE_QUALITY_LOW))
310     list.push_back(std::make_pair(g_localizeStrings.Get(13506), AE_QUALITY_LOW));
311   if(AE->SupportsQualityLevel(AE_QUALITY_MID))
312     list.push_back(std::make_pair(g_localizeStrings.Get(13507), AE_QUALITY_MID));
313   if(AE->SupportsQualityLevel(AE_QUALITY_HIGH))
314     list.push_back(std::make_pair(g_localizeStrings.Get(13508), AE_QUALITY_HIGH));
315   if(AE->SupportsQualityLevel(AE_QUALITY_REALLYHIGH))
316     list.push_back(std::make_pair(g_localizeStrings.Get(13509), AE_QUALITY_REALLYHIGH));
317 }
318
319 void CAEFactory::SettingOptionsAudioStreamsilenceFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current)
320 {
321   if (!AE)
322     return;
323
324   list.push_back(std::make_pair(g_localizeStrings.Get(20422), XbmcThreads::EndTime::InfiniteValue));
325   list.push_back(std::make_pair(g_localizeStrings.Get(13551), 0));
326
327   if (AE->SupportsSilenceTimeout())
328   {
329     list.push_back(std::make_pair(StringUtils::Format(g_localizeStrings.Get(13554).c_str(), 1), 1));
330     for (int i = 2; i <= 10; i++)
331     {
332       list.push_back(std::make_pair(StringUtils::Format(g_localizeStrings.Get(13555).c_str(), i), i));
333     }
334   }
335 }
336
337 void CAEFactory::SettingOptionsAudioDevicesFillerGeneral(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string &current, bool passthrough)
338 {
339   current = ((const CSettingString*)setting)->GetValue();
340   std::string firstDevice;
341
342   bool foundValue = false;
343   AEDeviceList sinkList;
344   EnumerateOutputDevices(sinkList, passthrough);
345   if (sinkList.size() == 0)
346     list.push_back(std::make_pair("Error - no devices found", "error"));
347   else
348   {
349     for (AEDeviceList::const_iterator sink = sinkList.begin(); sink != sinkList.end(); ++sink)
350     {
351       if (sink == sinkList.begin())
352         firstDevice = sink->second;
353
354       list.push_back(std::make_pair(sink->first, sink->second));
355
356       if (StringUtils::EqualsNoCase(current, sink->second))
357         foundValue = true;
358     }
359   }
360
361   if (!foundValue)
362     current = firstDevice;
363 }
364
365 void CAEFactory::RegisterAudioCallback(IAudioCallback* pCallback)
366 {
367   if (AE)
368     AE->RegisterAudioCallback(pCallback);
369 }
370
371 void CAEFactory::UnregisterAudioCallback()
372 {
373   if (AE)
374     AE->UnregisterAudioCallback();
375 }
376
377 bool CAEFactory::IsSettingVisible(const std::string &condition, const std::string &value, const std::string &settingId)
378 {
379   if (settingId.empty() || value.empty() || !AE)
380     return false;
381
382   return AE->IsSettingVisible(value);
383 }
384
385 void CAEFactory::KeepConfiguration(unsigned int millis)
386 {
387   if (AE)
388     AE->KeepConfiguration(millis);
389 }
390
391 void CAEFactory::DeviceChange()
392 {
393   if (AE)
394     AE->DeviceChange();
395 }