084dea0d84039dbdd40732c8a46280ac5ef1681a
[vuplus_xbmc] / xbmc / peripherals / devices / Peripheral.cpp
1 /*
2  *      Copyright (C) 2005-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 "Peripheral.h"
22 #include "peripherals/Peripherals.h"
23 #include "utils/log.h"
24 #include "utils/StringUtils.h"
25 #include "settings/Setting.h"
26 #include "utils/XBMCTinyXML.h"
27 #include "utils/URIUtils.h"
28 #include "guilib/LocalizeStrings.h"
29
30 using namespace PERIPHERALS;
31 using namespace std;
32
33 CPeripheral::CPeripheral(const PeripheralScanResult& scanResult) :
34   m_type(scanResult.m_mappedType),
35   m_busType(scanResult.m_busType),
36   m_mappedBusType(scanResult.m_mappedBusType),
37   m_strLocation(scanResult.m_strLocation),
38   m_strDeviceName(scanResult.m_strDeviceName),
39   m_strFileLocation(StringUtils::EmptyString),
40   m_iVendorId(scanResult.m_iVendorId),
41   m_iProductId(scanResult.m_iProductId),
42   m_strVersionInfo(g_localizeStrings.Get(13205)), // "unknown"
43   m_bInitialised(false),
44   m_bHidden(false),
45   m_bError(false)
46 {
47   PeripheralTypeTranslator::FormatHexString(scanResult.m_iVendorId, m_strVendorId);
48   PeripheralTypeTranslator::FormatHexString(scanResult.m_iProductId, m_strProductId);
49   m_strFileLocation.Format(scanResult.m_iSequence > 0 ? "peripherals://%s/%s_%d.dev" : "peripherals://%s/%s.dev", PeripheralTypeTranslator::BusTypeToString(scanResult.m_busType), scanResult.m_strLocation.c_str(), scanResult.m_iSequence);
50 }
51
52 CPeripheral::~CPeripheral(void)
53 {
54   PersistSettings(true);
55
56   for (unsigned int iSubdevicePtr = 0; iSubdevicePtr < m_subDevices.size(); iSubdevicePtr++)
57     delete m_subDevices.at(iSubdevicePtr);
58   m_subDevices.clear();
59
60   ClearSettings();
61 }
62
63 bool CPeripheral::operator ==(const CPeripheral &right) const
64 {
65   return m_type == right.m_type &&
66       m_strLocation == right.m_strLocation &&
67       m_iVendorId == right.m_iVendorId &&
68       m_iProductId == right.m_iProductId;
69 }
70
71 bool CPeripheral::operator !=(const CPeripheral &right) const
72 {
73   return !(*this == right);
74 }
75
76 bool CPeripheral::HasFeature(const PeripheralFeature feature) const
77 {
78   bool bReturn(false);
79
80   for (unsigned int iFeaturePtr = 0; iFeaturePtr < m_features.size(); iFeaturePtr++)
81   {
82     if (m_features.at(iFeaturePtr) == feature)
83     {
84       bReturn = true;
85       break;
86     }
87   }
88
89   if (!bReturn)
90   {
91     for (unsigned int iSubdevicePtr = 0; iSubdevicePtr < m_subDevices.size(); iSubdevicePtr++)
92     {
93       if (m_subDevices.at(iSubdevicePtr)->HasFeature(feature))
94       {
95         bReturn = true;
96         break;
97       }
98     }
99   }
100
101   return bReturn;
102 }
103
104 void CPeripheral::GetFeatures(std::vector<PeripheralFeature> &features) const
105 {
106   for (unsigned int iFeaturePtr = 0; iFeaturePtr < m_features.size(); iFeaturePtr++)
107     features.push_back(m_features.at(iFeaturePtr));
108
109   for (unsigned int iSubdevicePtr = 0; iSubdevicePtr < m_subDevices.size(); iSubdevicePtr++)
110     m_subDevices.at(iSubdevicePtr)->GetFeatures(features);
111 }
112
113 bool CPeripheral::Initialise(void)
114 {
115   bool bReturn(false);
116
117   if (m_bError)
118     return bReturn;
119
120   bReturn = true;
121   if (m_bInitialised)
122     return bReturn;
123
124   g_peripherals.GetSettingsFromMapping(*this);
125   m_strSettingsFile.Format("special://profile/peripheral_data/%s_%s_%s.xml", PeripheralTypeTranslator::BusTypeToString(m_mappedBusType), m_strVendorId.c_str(), m_strProductId.c_str());
126   LoadPersistedSettings();
127
128   for (unsigned int iFeaturePtr = 0; iFeaturePtr < m_features.size(); iFeaturePtr++)
129   {
130     PeripheralFeature feature = m_features.at(iFeaturePtr);
131     bReturn &= InitialiseFeature(feature);
132   }
133
134   for (unsigned int iSubdevicePtr = 0; iSubdevicePtr < m_subDevices.size(); iSubdevicePtr++)
135     bReturn &= m_subDevices.at(iSubdevicePtr)->Initialise();
136
137   if (bReturn)
138   {
139     CLog::Log(LOGDEBUG, "%s - initialised peripheral on '%s' with %d features and %d sub devices",
140       __FUNCTION__, m_strLocation.c_str(), (int)m_features.size(), (int)m_subDevices.size());
141     m_bInitialised = true;
142   }
143
144   return bReturn;
145 }
146
147 void CPeripheral::GetSubdevices(vector<CPeripheral *> &subDevices) const
148 {
149   for (unsigned int iSubdevicePtr = 0; iSubdevicePtr < m_subDevices.size(); iSubdevicePtr++)
150     subDevices.push_back(m_subDevices.at(iSubdevicePtr));
151 }
152
153 bool CPeripheral::IsMultiFunctional(void) const
154 {
155   return m_subDevices.size() > 0;
156 }
157
158 vector<CSetting *> CPeripheral::GetSettings(void) const
159 {
160   vector<CSetting *> settings;
161   for (map<CStdString, CSetting *>::const_iterator it = m_settings.begin(); it != m_settings.end(); it++)
162     settings.push_back(it->second);
163   return settings;
164 }
165
166 void CPeripheral::AddSetting(const CStdString &strKey, const CSetting *setting)
167 {
168   if (!setting)
169   {
170     CLog::Log(LOGERROR, "%s - invalid setting", __FUNCTION__);
171     return;
172   }
173
174   if (!HasSetting(strKey))
175   {
176     switch(setting->GetType())
177     {
178     case SettingTypeBool:
179       {
180         const CSettingBool *mappedSetting = (const CSettingBool *) setting;
181         CSettingBool *boolSetting = new CSettingBool(strKey, *mappedSetting);
182         if (boolSetting)
183         {
184           boolSetting->SetVisible(mappedSetting->IsVisible());
185           m_settings.insert(make_pair(strKey, boolSetting));
186         }
187       }
188       break;
189     case SettingTypeInteger:
190       {
191         const CSettingInt *mappedSetting = (const CSettingInt *) setting;
192         CSettingInt *intSetting = new CSettingInt(strKey, *mappedSetting);
193         if (intSetting)
194         {
195           intSetting->SetVisible(mappedSetting->IsVisible());
196           m_settings.insert(make_pair(strKey, intSetting));
197         }
198       }
199       break;
200     case SettingTypeNumber:
201       {
202         const CSettingNumber *mappedSetting = (const CSettingNumber *) setting;
203         CSettingNumber *floatSetting = new CSettingNumber(strKey, *mappedSetting);
204         if (floatSetting)
205         {
206           floatSetting->SetVisible(mappedSetting->IsVisible());
207           m_settings.insert(make_pair(strKey, floatSetting));
208         }
209       }
210       break;
211     case SettingTypeString:
212       {
213         const CSettingString *mappedSetting = (const CSettingString *) setting;
214         CSettingString *stringSetting = new CSettingString(strKey, *mappedSetting);
215         if (stringSetting)
216         {
217           stringSetting->SetVisible(mappedSetting->IsVisible());
218           m_settings.insert(make_pair(strKey, stringSetting));
219         }
220       }
221       break;
222     default:
223       //TODO add more types if needed
224       break;
225     }
226   }
227 }
228
229 bool CPeripheral::HasSetting(const CStdString &strKey) const
230 {
231   map<CStdString, CSetting *>:: const_iterator it = m_settings.find(strKey);
232   return it != m_settings.end();
233 }
234
235 bool CPeripheral::HasSettings(void) const
236 {
237   return m_settings.size() > 0;
238 }
239
240 bool CPeripheral::HasConfigurableSettings(void) const
241 {
242   bool bReturn(false);
243   map<CStdString, CSetting *>::const_iterator it = m_settings.begin();
244   while (it != m_settings.end() && !bReturn)
245   {
246     if ((*it).second->IsVisible())
247     {
248       bReturn = true;
249       break;
250     }
251
252     ++it;
253   }
254
255   return bReturn;
256 }
257
258 bool CPeripheral::GetSettingBool(const CStdString &strKey) const
259 {
260   map<CStdString, CSetting *>::const_iterator it = m_settings.find(strKey);
261   if (it != m_settings.end() && (*it).second->GetType() == SettingTypeBool)
262   {
263       CSettingBool *boolSetting = (CSettingBool *) (*it).second;
264     if (boolSetting)
265       return boolSetting->GetValue();
266   }
267
268   return false;
269 }
270
271 int CPeripheral::GetSettingInt(const CStdString &strKey) const
272 {
273   map<CStdString, CSetting *>::const_iterator it = m_settings.find(strKey);
274   if (it != m_settings.end() && (*it).second->GetType() == SettingTypeInteger)
275   {
276       CSettingInt *intSetting = (CSettingInt *) (*it).second;
277     if (intSetting)
278       return intSetting->GetValue();
279   }
280
281   return 0;
282 }
283
284 float CPeripheral::GetSettingFloat(const CStdString &strKey) const
285 {
286   map<CStdString, CSetting *>::const_iterator it = m_settings.find(strKey);
287   if (it != m_settings.end() && (*it).second->GetType() == SettingTypeNumber)
288   {
289       CSettingNumber *floatSetting = (CSettingNumber *) (*it).second;
290     if (floatSetting)
291       return (float)floatSetting->GetValue();
292   }
293
294   return 0;
295 }
296
297 const CStdString CPeripheral::GetSettingString(const CStdString &strKey) const
298 {
299   map<CStdString, CSetting *>::const_iterator it = m_settings.find(strKey);
300   if (it != m_settings.end() && (*it).second->GetType() == SettingTypeString)
301   {
302       CSettingString *stringSetting = (CSettingString *) (*it).second;
303     if (stringSetting)
304       return stringSetting->GetValue();
305   }
306
307   return StringUtils::EmptyString;
308 }
309
310 bool CPeripheral::SetSetting(const CStdString &strKey, bool bValue)
311 {
312   bool bChanged(false);
313   map<CStdString, CSetting *>::iterator it = m_settings.find(strKey);
314   if (it != m_settings.end() && (*it).second->GetType() == SettingTypeBool)
315   {
316       CSettingBool *boolSetting = (CSettingBool *) (*it).second;
317     if (boolSetting)
318     {
319       bChanged = boolSetting->GetValue() != bValue;
320       boolSetting->SetValue(bValue);
321       if (bChanged && m_bInitialised)
322         m_changedSettings.insert(strKey);
323     }
324   }
325   return bChanged;
326 }
327
328 bool CPeripheral::SetSetting(const CStdString &strKey, int iValue)
329 {
330   bool bChanged(false);
331   map<CStdString, CSetting *>::iterator it = m_settings.find(strKey);
332   if (it != m_settings.end() && (*it).second->GetType() == SettingTypeInteger)
333   {
334       CSettingInt *intSetting = (CSettingInt *) (*it).second;
335     if (intSetting)
336     {
337       bChanged = intSetting->GetValue() != iValue;
338       intSetting->SetValue(iValue);
339       if (bChanged && m_bInitialised)
340         m_changedSettings.insert(strKey);
341     }
342   }
343   return bChanged;
344 }
345
346 bool CPeripheral::SetSetting(const CStdString &strKey, float fValue)
347 {
348   bool bChanged(false);
349   map<CStdString, CSetting *>::iterator it = m_settings.find(strKey);
350   if (it != m_settings.end() && (*it).second->GetType() == SettingTypeNumber)
351   {
352       CSettingNumber *floatSetting = (CSettingNumber *) (*it).second;
353     if (floatSetting)
354     {
355       bChanged = floatSetting->GetValue() != fValue;
356       floatSetting->SetValue(fValue);
357       if (bChanged && m_bInitialised)
358         m_changedSettings.insert(strKey);
359     }
360   }
361   return bChanged;
362 }
363
364 void CPeripheral::SetSettingVisible(const CStdString &strKey, bool bSetTo)
365 {
366   map<CStdString, CSetting *>::iterator it = m_settings.find(strKey);
367   if (it != m_settings.end())
368     (*it).second->SetVisible(bSetTo);
369 }
370
371 bool CPeripheral::IsSettingVisible(const CStdString &strKey) const
372 {
373   map<CStdString, CSetting *>::const_iterator it = m_settings.find(strKey);
374   if (it != m_settings.end())
375     return (*it).second->IsVisible();
376   return false;
377 }
378
379 bool CPeripheral::SetSetting(const CStdString &strKey, const CStdString &strValue)
380 {
381   bool bChanged(false);
382   map<CStdString, CSetting *>::iterator it = m_settings.find(strKey);
383   if (it != m_settings.end())
384   {
385     if ((*it).second->GetType() == SettingTypeString)
386     {
387         CSettingString *stringSetting = (CSettingString *) (*it).second;
388       if (stringSetting)
389       {
390         bChanged = !StringUtils::EqualsNoCase(stringSetting->GetValue(), strValue);
391         stringSetting->SetValue(strValue);
392         if (bChanged && m_bInitialised)
393           m_changedSettings.insert(strKey);
394       }
395     }
396     else if ((*it).second->GetType() == SettingTypeInteger)
397       bChanged = SetSetting(strKey, (int) (strValue.IsEmpty() ? 0 : atoi(strValue.c_str())));
398     else if ((*it).second->GetType() == SettingTypeNumber)
399       bChanged = SetSetting(strKey, (float) (strValue.IsEmpty() ? 0 : atof(strValue.c_str())));
400     else if ((*it).second->GetType() == SettingTypeBool)
401       bChanged = SetSetting(strKey, strValue.Equals("1"));
402   }
403   return bChanged;
404 }
405
406 void CPeripheral::PersistSettings(bool bExiting /* = false */)
407 {
408   CXBMCTinyXML doc;
409   TiXmlElement node("settings");
410   doc.InsertEndChild(node);
411   for (map<CStdString, CSetting *>::const_iterator itr = m_settings.begin(); itr != m_settings.end(); itr++)
412   {
413     TiXmlElement nodeSetting("setting");
414     nodeSetting.SetAttribute("id", itr->first.c_str());
415     CStdString strValue;
416     switch ((*itr).second->GetType())
417     {
418     case SettingTypeString:
419       {
420         CSettingString *stringSetting = (CSettingString *) (*itr).second;
421         if (stringSetting)
422           strValue = stringSetting->GetValue();
423       }
424       break;
425     case SettingTypeInteger:
426       {
427         CSettingInt *intSetting = (CSettingInt *) (*itr).second;
428         if (intSetting)
429           strValue.Format("%d", intSetting->GetValue());
430       }
431       break;
432     case SettingTypeNumber:
433       {
434         CSettingNumber *floatSetting = (CSettingNumber *) (*itr).second;
435         if (floatSetting)
436           strValue.Format("%.2f", floatSetting->GetValue());
437       }
438       break;
439     case SettingTypeBool:
440       {
441         CSettingBool *boolSetting = (CSettingBool *) (*itr).second;
442         if (boolSetting)
443           strValue.Format("%d", boolSetting->GetValue() ? 1:0);
444       }
445       break;
446     default:
447       break;
448     }
449     nodeSetting.SetAttribute("value", strValue.c_str());
450     doc.RootElement()->InsertEndChild(nodeSetting);
451   }
452
453   doc.SaveFile(m_strSettingsFile);
454
455   if (!bExiting)
456   {
457     for (set<CStdString>::const_iterator it = m_changedSettings.begin(); it != m_changedSettings.end(); it++)
458       OnSettingChanged(*it);
459   }
460   m_changedSettings.clear();
461 }
462
463 void CPeripheral::LoadPersistedSettings(void)
464 {
465   CXBMCTinyXML doc;
466   if (doc.LoadFile(m_strSettingsFile))
467   {
468     const TiXmlElement *setting = doc.RootElement()->FirstChildElement("setting");
469     while (setting)
470     {
471       CStdString strId(setting->Attribute("id"));
472       CStdString strValue(setting->Attribute("value"));
473       SetSetting(strId, strValue);
474
475       setting = setting->NextSiblingElement("setting");
476     }
477   }
478 }
479
480 void CPeripheral::ResetDefaultSettings(void)
481 {
482   ClearSettings();
483   g_peripherals.GetSettingsFromMapping(*this);
484
485   map<CStdString, CSetting *>::iterator it = m_settings.begin();
486   while (it != m_settings.end())
487   {
488     m_changedSettings.insert((*it).first);
489     ++it;
490   }
491
492   PersistSettings();
493 }
494
495 void CPeripheral::ClearSettings(void)
496 {
497   map<CStdString, CSetting *>::iterator it = m_settings.begin();
498   while (it != m_settings.end())
499   {
500     delete (*it).second;
501     ++it;
502   }
503   m_settings.clear();
504 }
505
506 bool CPeripheral::operator ==(const PeripheralScanResult& right) const
507 {
508   return m_strLocation.Equals(right.m_strLocation);
509 }
510
511 bool CPeripheral::operator !=(const PeripheralScanResult& right) const
512 {
513   return !(*this == right);
514 }