2 * Copyright (C) 2005-2013 Team XBMC
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)
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.
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/>.
21 #include "Peripheral.h"
22 #include "peripherals/Peripherals.h"
23 #include "utils/log.h"
24 #include "utils/StringUtils.h"
25 #include "settings/lib/Setting.h"
26 #include "utils/XBMCTinyXML.h"
27 #include "utils/URIUtils.h"
28 #include "guilib/LocalizeStrings.h"
30 using namespace PERIPHERALS;
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),
47 PeripheralTypeTranslator::FormatHexString(scanResult.m_iVendorId, m_strVendorId);
48 PeripheralTypeTranslator::FormatHexString(scanResult.m_iProductId, m_strProductId);
49 m_strFileLocation = StringUtils::Format(scanResult.m_iSequence > 0 ? "peripherals://%s/%s_%d.dev" : "peripherals://%s/%s.dev",
50 PeripheralTypeTranslator::BusTypeToString(scanResult.m_busType),
51 scanResult.m_strLocation.c_str(),
52 scanResult.m_iSequence);
55 CPeripheral::~CPeripheral(void)
57 PersistSettings(true);
59 for (unsigned int iSubdevicePtr = 0; iSubdevicePtr < m_subDevices.size(); iSubdevicePtr++)
60 delete m_subDevices.at(iSubdevicePtr);
66 bool CPeripheral::operator ==(const CPeripheral &right) const
68 return m_type == right.m_type &&
69 m_strLocation == right.m_strLocation &&
70 m_iVendorId == right.m_iVendorId &&
71 m_iProductId == right.m_iProductId;
74 bool CPeripheral::operator !=(const CPeripheral &right) const
76 return !(*this == right);
79 bool CPeripheral::HasFeature(const PeripheralFeature feature) const
83 for (unsigned int iFeaturePtr = 0; iFeaturePtr < m_features.size(); iFeaturePtr++)
85 if (m_features.at(iFeaturePtr) == feature)
94 for (unsigned int iSubdevicePtr = 0; iSubdevicePtr < m_subDevices.size(); iSubdevicePtr++)
96 if (m_subDevices.at(iSubdevicePtr)->HasFeature(feature))
107 void CPeripheral::GetFeatures(std::vector<PeripheralFeature> &features) const
109 for (unsigned int iFeaturePtr = 0; iFeaturePtr < m_features.size(); iFeaturePtr++)
110 features.push_back(m_features.at(iFeaturePtr));
112 for (unsigned int iSubdevicePtr = 0; iSubdevicePtr < m_subDevices.size(); iSubdevicePtr++)
113 m_subDevices.at(iSubdevicePtr)->GetFeatures(features);
116 bool CPeripheral::Initialise(void)
127 g_peripherals.GetSettingsFromMapping(*this);
128 m_strSettingsFile = StringUtils::Format("special://profile/peripheral_data/%s_%s_%s.xml",
129 PeripheralTypeTranslator::BusTypeToString(m_mappedBusType),
130 m_strVendorId.c_str(),
131 m_strProductId.c_str());
132 LoadPersistedSettings();
134 for (unsigned int iFeaturePtr = 0; iFeaturePtr < m_features.size(); iFeaturePtr++)
136 PeripheralFeature feature = m_features.at(iFeaturePtr);
137 bReturn &= InitialiseFeature(feature);
140 for (unsigned int iSubdevicePtr = 0; iSubdevicePtr < m_subDevices.size(); iSubdevicePtr++)
141 bReturn &= m_subDevices.at(iSubdevicePtr)->Initialise();
145 CLog::Log(LOGDEBUG, "%s - initialised peripheral on '%s' with %d features and %d sub devices",
146 __FUNCTION__, m_strLocation.c_str(), (int)m_features.size(), (int)m_subDevices.size());
147 m_bInitialised = true;
153 void CPeripheral::GetSubdevices(vector<CPeripheral *> &subDevices) const
155 for (unsigned int iSubdevicePtr = 0; iSubdevicePtr < m_subDevices.size(); iSubdevicePtr++)
156 subDevices.push_back(m_subDevices.at(iSubdevicePtr));
159 bool CPeripheral::IsMultiFunctional(void) const
161 return m_subDevices.size() > 0;
164 vector<CSetting *> CPeripheral::GetSettings(void) const
166 vector<CSetting *> settings;
167 for (map<CStdString, CSetting *>::const_iterator it = m_settings.begin(); it != m_settings.end(); it++)
168 settings.push_back(it->second);
172 void CPeripheral::AddSetting(const CStdString &strKey, const CSetting *setting)
176 CLog::Log(LOGERROR, "%s - invalid setting", __FUNCTION__);
180 if (!HasSetting(strKey))
182 switch(setting->GetType())
184 case SettingTypeBool:
186 const CSettingBool *mappedSetting = (const CSettingBool *) setting;
187 CSettingBool *boolSetting = new CSettingBool(strKey, *mappedSetting);
190 boolSetting->SetVisible(mappedSetting->IsVisible());
191 m_settings.insert(make_pair(strKey, boolSetting));
195 case SettingTypeInteger:
197 const CSettingInt *mappedSetting = (const CSettingInt *) setting;
198 CSettingInt *intSetting = new CSettingInt(strKey, *mappedSetting);
201 intSetting->SetVisible(mappedSetting->IsVisible());
202 m_settings.insert(make_pair(strKey, intSetting));
206 case SettingTypeNumber:
208 const CSettingNumber *mappedSetting = (const CSettingNumber *) setting;
209 CSettingNumber *floatSetting = new CSettingNumber(strKey, *mappedSetting);
212 floatSetting->SetVisible(mappedSetting->IsVisible());
213 m_settings.insert(make_pair(strKey, floatSetting));
217 case SettingTypeString:
219 const CSettingString *mappedSetting = (const CSettingString *) setting;
220 CSettingString *stringSetting = new CSettingString(strKey, *mappedSetting);
223 stringSetting->SetVisible(mappedSetting->IsVisible());
224 m_settings.insert(make_pair(strKey, stringSetting));
229 //TODO add more types if needed
235 bool CPeripheral::HasSetting(const CStdString &strKey) const
237 map<CStdString, CSetting *>:: const_iterator it = m_settings.find(strKey);
238 return it != m_settings.end();
241 bool CPeripheral::HasSettings(void) const
243 return !m_settings.empty();
246 bool CPeripheral::HasConfigurableSettings(void) const
249 map<CStdString, CSetting *>::const_iterator it = m_settings.begin();
250 while (it != m_settings.end() && !bReturn)
252 if ((*it).second->IsVisible())
264 bool CPeripheral::GetSettingBool(const CStdString &strKey) const
266 map<CStdString, CSetting *>::const_iterator it = m_settings.find(strKey);
267 if (it != m_settings.end() && (*it).second->GetType() == SettingTypeBool)
269 CSettingBool *boolSetting = (CSettingBool *) (*it).second;
271 return boolSetting->GetValue();
277 int CPeripheral::GetSettingInt(const CStdString &strKey) const
279 map<CStdString, CSetting *>::const_iterator it = m_settings.find(strKey);
280 if (it != m_settings.end() && (*it).second->GetType() == SettingTypeInteger)
282 CSettingInt *intSetting = (CSettingInt *) (*it).second;
284 return intSetting->GetValue();
290 float CPeripheral::GetSettingFloat(const CStdString &strKey) const
292 map<CStdString, CSetting *>::const_iterator it = m_settings.find(strKey);
293 if (it != m_settings.end() && (*it).second->GetType() == SettingTypeNumber)
295 CSettingNumber *floatSetting = (CSettingNumber *) (*it).second;
297 return (float)floatSetting->GetValue();
303 const CStdString CPeripheral::GetSettingString(const CStdString &strKey) const
305 map<CStdString, CSetting *>::const_iterator it = m_settings.find(strKey);
306 if (it != m_settings.end() && (*it).second->GetType() == SettingTypeString)
308 CSettingString *stringSetting = (CSettingString *) (*it).second;
310 return stringSetting->GetValue();
313 return StringUtils::EmptyString;
316 bool CPeripheral::SetSetting(const CStdString &strKey, bool bValue)
318 bool bChanged(false);
319 map<CStdString, CSetting *>::iterator it = m_settings.find(strKey);
320 if (it != m_settings.end() && (*it).second->GetType() == SettingTypeBool)
322 CSettingBool *boolSetting = (CSettingBool *) (*it).second;
325 bChanged = boolSetting->GetValue() != bValue;
326 boolSetting->SetValue(bValue);
327 if (bChanged && m_bInitialised)
328 m_changedSettings.insert(strKey);
334 bool CPeripheral::SetSetting(const CStdString &strKey, int iValue)
336 bool bChanged(false);
337 map<CStdString, CSetting *>::iterator it = m_settings.find(strKey);
338 if (it != m_settings.end() && (*it).second->GetType() == SettingTypeInteger)
340 CSettingInt *intSetting = (CSettingInt *) (*it).second;
343 bChanged = intSetting->GetValue() != iValue;
344 intSetting->SetValue(iValue);
345 if (bChanged && m_bInitialised)
346 m_changedSettings.insert(strKey);
352 bool CPeripheral::SetSetting(const CStdString &strKey, float fValue)
354 bool bChanged(false);
355 map<CStdString, CSetting *>::iterator it = m_settings.find(strKey);
356 if (it != m_settings.end() && (*it).second->GetType() == SettingTypeNumber)
358 CSettingNumber *floatSetting = (CSettingNumber *) (*it).second;
361 bChanged = floatSetting->GetValue() != fValue;
362 floatSetting->SetValue(fValue);
363 if (bChanged && m_bInitialised)
364 m_changedSettings.insert(strKey);
370 void CPeripheral::SetSettingVisible(const CStdString &strKey, bool bSetTo)
372 map<CStdString, CSetting *>::iterator it = m_settings.find(strKey);
373 if (it != m_settings.end())
374 (*it).second->SetVisible(bSetTo);
377 bool CPeripheral::IsSettingVisible(const CStdString &strKey) const
379 map<CStdString, CSetting *>::const_iterator it = m_settings.find(strKey);
380 if (it != m_settings.end())
381 return (*it).second->IsVisible();
385 bool CPeripheral::SetSetting(const CStdString &strKey, const CStdString &strValue)
387 bool bChanged(false);
388 map<CStdString, CSetting *>::iterator it = m_settings.find(strKey);
389 if (it != m_settings.end())
391 if ((*it).second->GetType() == SettingTypeString)
393 CSettingString *stringSetting = (CSettingString *) (*it).second;
396 bChanged = !StringUtils::EqualsNoCase(stringSetting->GetValue(), strValue);
397 stringSetting->SetValue(strValue);
398 if (bChanged && m_bInitialised)
399 m_changedSettings.insert(strKey);
402 else if ((*it).second->GetType() == SettingTypeInteger)
403 bChanged = SetSetting(strKey, (int) (strValue.empty() ? 0 : atoi(strValue.c_str())));
404 else if ((*it).second->GetType() == SettingTypeNumber)
405 bChanged = SetSetting(strKey, (float) (strValue.empty() ? 0 : atof(strValue.c_str())));
406 else if ((*it).second->GetType() == SettingTypeBool)
407 bChanged = SetSetting(strKey, strValue.Equals("1"));
412 void CPeripheral::PersistSettings(bool bExiting /* = false */)
415 TiXmlElement node("settings");
416 doc.InsertEndChild(node);
417 for (map<CStdString, CSetting *>::const_iterator itr = m_settings.begin(); itr != m_settings.end(); itr++)
419 TiXmlElement nodeSetting("setting");
420 nodeSetting.SetAttribute("id", itr->first.c_str());
422 switch ((*itr).second->GetType())
424 case SettingTypeString:
426 CSettingString *stringSetting = (CSettingString *) (*itr).second;
428 strValue = stringSetting->GetValue();
431 case SettingTypeInteger:
433 CSettingInt *intSetting = (CSettingInt *) (*itr).second;
435 strValue = StringUtils::Format("%d", intSetting->GetValue());
438 case SettingTypeNumber:
440 CSettingNumber *floatSetting = (CSettingNumber *) (*itr).second;
442 strValue = StringUtils::Format("%.2f", floatSetting->GetValue());
445 case SettingTypeBool:
447 CSettingBool *boolSetting = (CSettingBool *) (*itr).second;
449 strValue = StringUtils::Format("%d", boolSetting->GetValue() ? 1:0);
455 nodeSetting.SetAttribute("value", strValue.c_str());
456 doc.RootElement()->InsertEndChild(nodeSetting);
459 doc.SaveFile(m_strSettingsFile);
463 for (set<CStdString>::const_iterator it = m_changedSettings.begin(); it != m_changedSettings.end(); it++)
464 OnSettingChanged(*it);
466 m_changedSettings.clear();
469 void CPeripheral::LoadPersistedSettings(void)
472 if (doc.LoadFile(m_strSettingsFile))
474 const TiXmlElement *setting = doc.RootElement()->FirstChildElement("setting");
477 CStdString strId(setting->Attribute("id"));
478 CStdString strValue(setting->Attribute("value"));
479 SetSetting(strId, strValue);
481 setting = setting->NextSiblingElement("setting");
486 void CPeripheral::ResetDefaultSettings(void)
489 g_peripherals.GetSettingsFromMapping(*this);
491 map<CStdString, CSetting *>::iterator it = m_settings.begin();
492 while (it != m_settings.end())
494 m_changedSettings.insert((*it).first);
501 void CPeripheral::ClearSettings(void)
503 map<CStdString, CSetting *>::iterator it = m_settings.begin();
504 while (it != m_settings.end())
512 bool CPeripheral::operator ==(const PeripheralScanResult& right) const
514 return m_strLocation.Equals(right.m_strLocation);
517 bool CPeripheral::operator !=(const PeripheralScanResult& right) const
519 return !(*this == right);