diff --git a/CMakeLists.txt b/CMakeLists.txt index b7269df7..17046915 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,8 +31,8 @@ set(JOYSTICK_SOURCES src/addon.cpp src/api/PeripheralScanner.cpp src/buttonmapper/ButtonMapper.cpp src/buttonmapper/ButtonMapTranslator.cpp - src/buttonmapper/ControllerMapper.cpp src/buttonmapper/ControllerModel.cpp + src/buttonmapper/ControllerTransformer.cpp src/buttonmapper/DriverGeometry.cpp src/buttonmapper/JoystickFamily.cpp src/filesystem/DirectoryCache.cpp diff --git a/peripheral.joystick/resources/joystickfamilies/joystickfamilies.xml b/peripheral.joystick/resources/joystickfamilies/joystickfamilies.xml new file mode 100644 index 00000000..8be3eeeb --- /dev/null +++ b/peripheral.joystick/resources/joystickfamilies/joystickfamilies.xml @@ -0,0 +1,133 @@ + + + + Alienware Alienware Dual Compatible Game Pad + + + AppleRemote + + + Harmony + + + STD AxisPad + Interact AxisPad + + + Logitech Logitech Cordless RumblePad 2 + Logitech Cordless RumblePad 2 + Logitech RumblePad 2 USB + + + Microsoft X-Box 360 pad + Xbox 360 Wireless Receiver (XBOX) + Xbox 360 Wireless Receiver + Xbox Gamepad (userspace driver) + Thrustmaster Gamepad GP XID + Logitech Gamepad F310 + Logitech Gamepad F510 + Logitech Gamepad F710 + Generic X-Box pad + Logitech Chillstream Controller + Mad Catz Wired Xbox 360 Controller + Mad Catz Street Fighter IV FightStick SE + Mad Catz Xbox 360 Controller + Mad Catz Street Fighter IV FightPad + Mad Catz Wired Xbox 360 Controller (SFIV) + Mad Catz Beat Pad + Mad Catz Xbox controller - MW2 + Mad Catz JOYTECH NEO SE Advanced GamePad + Saitek Cyborg Rumble Pad - PC/Xbox 360 + Saitek P3200 Rumble Pad - PC/Xbox 360 + Super SFIV FightStick TE S + HSM3 Xbox360 dancepad + Afterglow AX.1 Gamepad for Xbox 360 + Pelican PL-3601 'TSZ' Wired Xbox 360 Controller + Afterglow Gamepad for Xbox 360 + Rock Candy Gamepad for Xbox 360 + Logic3 Controller + Logic3 Controller + Hori Fighting Stick EX2 + Hori Real Arcade Pro.EX + Honey Bee Xbox360 dancepad + PDP AFTERGLOW AX.1 + RedOctane Guitar Hero X-plorer + BigBen Interactive XBOX 360 Controller + Razer Sabertooth + Power A Mini Pro Elite + Xbox Airflo wired controller + Batarang Xbox 360 controller + Joytech Neo-Se Take2 + Razer Onza Tournament Edition + Razer Onza Classic Edition + Razer Sabertooth + Harmonix Rock Band Guitar + Harmonix Rock Band Drumkit + Mad Catz Xbox 360 Controller + MLG Pro Circuit Controller (Xbox) + Street Fighter IV FightPad + Street Fighter IV FightStick TE + Harmonix Xbox 360 Controller + Gamestop Xbox 360 Controller + Tron Xbox 360 controller + Razer Atrox Arcade Stick + PowerA MINI PROEX Controller + Xbox Airflo wired controller + Hori XBOX 360 EX 2 with Turbo + Hori Real Arcade Pro VX-SA + Hori SOULCALIBUR V Stick + Thrustmaster, Inc. GPX Controller + Thrustmaster Ferrari 458 Racing Wheel + Microsoft X-Box One pad + + + Afterglow Gamepad for Xbox 360 (Controller) + Controller (Gamepad F310) + Controller (Gamepad for Xbox 360) + Controller (Rumble Gamepad F510) + Controller (Wireless Gamepad F710) + Controller (Xbox 360 Wireless Receiver for Windows) + Controller (Xbox wireless receiver for windows) + Controller (XBOX360 GAMEPAD) + Controller (Batarang wired controller (XBOX)) + Wireless Gamepad F710 (Controller) + XBOX 360 For Windows + XBOX 360 For Windows (Controller) + Xbox 360 Wireless Controller + Xbox Receiver for Windows (Wireless Controller) + Xbox wireless receiver for windows (Controller) + Gamepad F310 (Controller) + Razer Sabertooth Elite (Controller) + Controller (Razer Sabertooth Elite) + Controller (XBOX One For Windows) + + + Microsoft Xbox Controller S + Mad Catz MicroCON + Logitech Xbox Cordless Controller + Microsoft X-Box pad (Japan) + + + WiiRemote + + + Nintendo Wii Remote Pro Controller + + + OUYA Game Controller + + + PLAYSTATION(R)3 Controller + PS3 Controller + Sony Computer Entertainment Wireless Controller + + + PLAYSTATION(R)3 Remote Keyboard + PS3 Remote Keyboard + MoSart PS3 Remote Keyboard + + + Wireless Controller + + + diff --git a/src/buttonmapper/ButtonMapper.cpp b/src/buttonmapper/ButtonMapper.cpp index 80b90aa8..71476818 100644 --- a/src/buttonmapper/ButtonMapper.cpp +++ b/src/buttonmapper/ButtonMapper.cpp @@ -19,6 +19,7 @@ */ #include "ButtonMapper.h" +#include "ControllerTransformer.h" #include "storage/IDatabase.h" #include "kodi_peripheral_utils.hpp" @@ -38,6 +39,23 @@ CButtonMapper::~CButtonMapper() { } +bool CButtonMapper::Initialize(CJoystickFamilyManager& familyManager) +{ + m_controllerTransformer.reset(new CControllerTransformer(familyManager)); + return true; +} + +void CButtonMapper::Deinitialize() +{ + m_controllerTransformer.reset(); + m_databases.clear(); +} + +IDatabaseCallbacks* CButtonMapper::GetCallbacks() +{ + return m_controllerTransformer.get(); +} + bool CButtonMapper::GetFeatures(const ADDON::Joystick& joystick, const std::string& strControllerId, FeatureVector& features) @@ -121,6 +139,9 @@ bool CButtonMapper::GetFeatures(const ADDON::Joystick& joystick, ButtonMap&& but void CButtonMapper::DeriveFeatures(const ADDON::Joystick& joystick, const std::string& toController, const ButtonMap& buttonMap, FeatureVector& transformedFeatures) { + if (!m_controllerTransformer) + return; + // Obtain an iterator to the controller profile with the highest count of features defined unsigned int maxFeatures = 0; auto maxFeaturesIt = buttonMap.end(); @@ -141,7 +162,7 @@ void CButtonMapper::DeriveFeatures(const ADDON::Joystick& joystick, const std::s const std::string& fromController = maxFeaturesIt->first; const FeatureVector& features = maxFeaturesIt->second; - m_controllerMapper.TransformFeatures(joystick, fromController, toController, features, transformedFeatures); + m_controllerTransformer->TransformFeatures(joystick, fromController, toController, features, transformedFeatures); } } diff --git a/src/buttonmapper/ButtonMapper.h b/src/buttonmapper/ButtonMapper.h index f691024a..e73cca2d 100644 --- a/src/buttonmapper/ButtonMapper.h +++ b/src/buttonmapper/ButtonMapper.h @@ -20,9 +20,9 @@ #pragma once #include "ButtonMapTypes.h" -#include "ControllerMapper.h" #include "storage/StorageTypes.h" +#include #include namespace ADDON @@ -33,7 +33,8 @@ namespace ADDON namespace JOYSTICK { - class IDatabase; + class CControllerTransformer; + class CJoystickFamilyManager; class IDatabaseCallbacks; class CButtonMapper @@ -42,9 +43,12 @@ namespace JOYSTICK CButtonMapper(ADDON::CHelper_libKODI_peripheral* peripheralLib); ~CButtonMapper(); - bool GetFeatures(const ADDON::Joystick& joystick, const std::string& strDeviceId, FeatureVector& features); + bool Initialize(CJoystickFamilyManager& familyManager); + void Deinitialize(); + + IDatabaseCallbacks* GetCallbacks(); - IDatabaseCallbacks* GetCallbacks() { return &m_controllerMapper; } + bool GetFeatures(const ADDON::Joystick& joystick, const std::string& strDeviceId, FeatureVector& features); void RegisterDatabase(const DatabasePtr& database); void UnregisterDatabase(const DatabasePtr& database); @@ -57,7 +61,7 @@ namespace JOYSTICK void DeriveFeatures(const ADDON::Joystick& joystick, const std::string& toController, const ButtonMap& buttonMap, FeatureVector& transformedFeatures); DatabaseVector m_databases; - CControllerMapper m_controllerMapper; + std::unique_ptr m_controllerTransformer; ADDON::CHelper_libKODI_peripheral* m_peripheralLib; }; diff --git a/src/buttonmapper/ControllerMapper.cpp b/src/buttonmapper/ControllerTransformer.cpp similarity index 79% rename from src/buttonmapper/ControllerMapper.cpp rename to src/buttonmapper/ControllerTransformer.cpp index 2d82e3f5..d7dff96c 100644 --- a/src/buttonmapper/ControllerMapper.cpp +++ b/src/buttonmapper/ControllerTransformer.cpp @@ -18,7 +18,7 @@ * */ -#include "ControllerMapper.h" +#include "ControllerTransformer.h" #include "storage/Device.h" #include "kodi_peripheral_utils.hpp" @@ -29,7 +29,16 @@ using namespace JOYSTICK; -void CControllerMapper::OnAdd(const DevicePtr& driverInfo, const ButtonMap& buttonMap) +CControllerTransformer::CControllerTransformer(CJoystickFamilyManager& familyManager) : + m_familyManager(familyManager) +{ +} + +CControllerTransformer::~CControllerTransformer() +{ +} + +void CControllerTransformer::OnAdd(const DevicePtr& driverInfo, const ButtonMap& buttonMap) { // Skip devices we've already encountered. if (m_observedDevices.find(driverInfo) == m_observedDevices.end()) @@ -37,7 +46,9 @@ void CControllerMapper::OnAdd(const DevicePtr& driverInfo, const ButtonMap& butt else return; - CJoystickFamily family(driverInfo->Name(), driverInfo->Provider()); + const std::string& familyName = m_familyManager.GetFamily(driverInfo->Name(), driverInfo->Provider()); + + CJoystickFamily family(familyName); CDriverGeometry geometry(driverInfo->ButtonCount(), driverInfo->HatCount(), driverInfo->AxisCount()); @@ -58,9 +69,9 @@ void CControllerMapper::OnAdd(const DevicePtr& driverInfo, const ButtonMap& butt } } -bool CControllerMapper::AddControllerMap(CControllerModel& model, - const std::string& controllerFrom, const FeatureVector& featuresFrom, - const std::string& controllerTo, const FeatureVector& featuresTo) +bool CControllerTransformer::AddControllerMap(CControllerModel& model, + const std::string& controllerFrom, const FeatureVector& featuresFrom, + const std::string& controllerTo, const FeatureVector& featuresTo) { bool bChanged = false; @@ -121,18 +132,20 @@ bool CControllerMapper::AddControllerMap(CControllerModel& model, return bChanged; } -void CControllerMapper::TransformFeatures(const ADDON::Joystick& driverInfo, - const std::string& fromController, - const std::string& toController, - const FeatureVector& features, - FeatureVector& transformedFeatures) +void CControllerTransformer::TransformFeatures(const ADDON::Joystick& driverInfo, + const std::string& fromController, + const std::string& toController, + const FeatureVector& features, + FeatureVector& transformedFeatures) { bool bSwap = (fromController >= toController); ControllerMapItem needle = { bSwap ? toController : fromController, bSwap ? fromController : toController }; - CJoystickFamily family(driverInfo.Name(), driverInfo.Provider()); + const std::string& familyName = m_familyManager.GetFamily(driverInfo.Name(), driverInfo.Provider()); + + CJoystickFamily family(familyName); CDriverGeometry geometry(driverInfo.ButtonCount(), driverInfo.HatCount(), driverInfo.AxisCount()); diff --git a/src/buttonmapper/ControllerMapper.h b/src/buttonmapper/ControllerTransformer.h similarity index 83% rename from src/buttonmapper/ControllerMapper.h rename to src/buttonmapper/ControllerTransformer.h index b8850316..ceb35a7a 100644 --- a/src/buttonmapper/ControllerMapper.h +++ b/src/buttonmapper/ControllerTransformer.h @@ -33,11 +33,14 @@ namespace ADDON namespace JOYSTICK { - class CControllerMapper : public IDatabaseCallbacks + class CJoystickFamilyManager; + + class CControllerTransformer : public IDatabaseCallbacks { public: - CControllerMapper() = default; - virtual ~CControllerMapper() = default; + CControllerTransformer(CJoystickFamilyManager& familyManager); + + virtual ~CControllerTransformer(); // implementation of IDatabaseCallbacks virtual void OnAdd(const DevicePtr& driverInfo, const ButtonMap& buttonMap); @@ -56,8 +59,9 @@ namespace JOYSTICK typedef std::map FamilyMap; typedef std::map GeomoetryMap; - FamilyMap m_familyModels; - GeomoetryMap m_geometryModels; - DeviceSet m_observedDevices; + FamilyMap m_familyModels; + GeomoetryMap m_geometryModels; + DeviceSet m_observedDevices; + CJoystickFamilyManager& m_familyManager; }; } diff --git a/src/buttonmapper/JoystickFamily.cpp b/src/buttonmapper/JoystickFamily.cpp index b736a8f1..7219caaa 100644 --- a/src/buttonmapper/JoystickFamily.cpp +++ b/src/buttonmapper/JoystickFamily.cpp @@ -20,13 +20,14 @@ #include "JoystickFamily.h" #include "storage/xml/JoystickFamiliesXml.h" +#include "storage/xml/JoystickFamilyDefinitions.h" using namespace JOYSTICK; // --- CJoystickFamily --------------------------------------------------------- -CJoystickFamily::CJoystickFamily(const std::string& name, const std::string& provider) : - m_familyName(CJoystickFamilyManager::Get().GetFamily(name, provider)) +CJoystickFamily::CJoystickFamily(const std::string& familyName) : + m_familyName(familyName) { } @@ -42,15 +43,16 @@ bool CJoystickFamily::operator<(const CJoystickFamily& other) const // --- CJoystickFamilyManager -------------------------------------------------- -CJoystickFamilyManager& CJoystickFamilyManager::Get() +bool CJoystickFamilyManager::Initialize(const std::string& addonPath) { - static CJoystickFamilyManager instance; - return instance; + std::string path = addonPath + "/" JOYSTICK_FAMILIES_FOLDER "/" JOYSTICK_FAMILIES_RESOURCE; + return LoadFamilies(path); } -bool CJoystickFamilyManager::Load() +bool CJoystickFamilyManager::LoadFamilies(const std::string& path) { - m_families = CJoystickFamiliesXml::LoadFamilies(); + CJoystickFamiliesXml::LoadFamilies(path, m_families); + return !m_families.empty(); } diff --git a/src/buttonmapper/JoystickFamily.h b/src/buttonmapper/JoystickFamily.h index 081e8f49..2507c53f 100644 --- a/src/buttonmapper/JoystickFamily.h +++ b/src/buttonmapper/JoystickFamily.h @@ -27,35 +27,38 @@ namespace JOYSTICK { + // --- CJoystickFamily ------------------------------------------------------- + class CJoystickFamily { public: - CJoystickFamily(const std::string& name, const std::string& provider); + CJoystickFamily(const std::string& familyName); CJoystickFamily(const CJoystickFamily& other); bool operator<(const CJoystickFamily& other) const; - const std::string& Name() const { return m_familyName; } - + const std::string& FamilyName() const { return m_familyName; } bool IsValid() const { return !m_familyName.empty(); } private: const std::string m_familyName; }; + // --- CJoystickFamilyManager ------------------------------------------------ + class CJoystickFamilyManager { - private: - CJoystickFamilyManager() = default; - public: - static CJoystickFamilyManager& Get(); + CJoystickFamilyManager() = default; - bool Load(); + bool Initialize(const std::string& addonPath); + void Deinitialize() { m_families.clear(); } const std::string& GetFamily(const std::string& name, const std::string& provider) const; private: + bool LoadFamilies(const std::string& path); + JoystickFamilyMap m_families; }; } diff --git a/src/storage/JustABunchOfFiles.cpp b/src/storage/JustABunchOfFiles.cpp index c8dcd8b0..54665457 100644 --- a/src/storage/JustABunchOfFiles.cpp +++ b/src/storage/JustABunchOfFiles.cpp @@ -19,7 +19,7 @@ */ #include "JustABunchOfFiles.h" -#include "ButtonMapDefinitions.h" +#include "StorageDefinitions.h" #include "StorageUtils.h" #include "filesystem/DirectoryUtils.h" #include "log/Log.h" diff --git a/src/storage/StorageDefinitions.h b/src/storage/StorageDefinitions.h new file mode 100644 index 00000000..7e30a243 --- /dev/null +++ b/src/storage/StorageDefinitions.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2014-2015 Garrett Brown + * Copyright (C) 2014-2015 Team XBMC + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#pragma once + +#define RESOURCE_XML_EXTENSION ".xml" +#define RESOURCE_RETROARCH_EXTENSION ".cfg" + +#define RESOURCE_XML_FOLDER "xml" +#define RESOURCE_RETROARCH_FOLDER "retroarch" + +#define DEVICES_XML_ROOT "devices" +#define DEVICES_XML_ELEM_DEVICE "device" diff --git a/src/storage/StorageManager.cpp b/src/storage/StorageManager.cpp index c6a76f3a..80b4ad98 100644 --- a/src/storage/StorageManager.cpp +++ b/src/storage/StorageManager.cpp @@ -42,7 +42,7 @@ using namespace JOYSTICK; #define BUTTONMAP_FOLDER "buttonmaps" CStorageManager::CStorageManager(void) : - m_peripheralLib(NULL) + m_peripheralLib(nullptr) { } @@ -70,6 +70,9 @@ bool CStorageManager::Initialize(ADDON::CHelper_libKODI_peripheral* peripheralLi m_buttonMapper.reset(new CButtonMapper(peripheralLib)); + if (!m_buttonMapper->Initialize(m_familyManager)) + return false; + // Remove slash at end StringUtils::TrimRight(strUserPath, "\\/"); StringUtils::TrimRight(strAddonPath, "\\/"); @@ -80,30 +83,33 @@ bool CStorageManager::Initialize(ADDON::CHelper_libKODI_peripheral* peripheralLi // Ensure resources path exists in user data CStorageUtils::EnsureDirectoryExists(strUserPath); - strUserPath += "/" BUTTONMAP_FOLDER; - strAddonPath += "/" BUTTONMAP_FOLDER; + std::string strUserButtonMapPath = strUserPath + "/" BUTTONMAP_FOLDER; + std::string strAddonButtonMapPath = strAddonPath + "/" BUTTONMAP_FOLDER; // Ensure button map path exists in user data - CStorageUtils::EnsureDirectoryExists(strUserPath); + CStorageUtils::EnsureDirectoryExists(strUserButtonMapPath); - m_databases.push_back(DatabasePtr(new CDatabaseXml(strUserPath, true, m_buttonMapper->GetCallbacks()))); - //m_databases.push_back(DatabasePtr(new CDatabaseRetroArch(strUserPath, true, &m_controllerMapper))); // TODO - m_databases.push_back(DatabasePtr(new CDatabaseXml(strAddonPath, false, m_buttonMapper->GetCallbacks()))); - //m_databases.push_back(DatabasePtr(new CDatabaseRetroArch(strAddonPath, false))); // TODO + m_databases.push_back(DatabasePtr(new CDatabaseXml(strUserButtonMapPath, true, m_buttonMapper->GetCallbacks()))); + //m_databases.push_back(DatabasePtr(new CDatabaseRetroArch(strUserButtonMapPath, true, &m_controllerMapper))); // TODO + m_databases.push_back(DatabasePtr(new CDatabaseXml(strAddonButtonMapPath, false, m_buttonMapper->GetCallbacks()))); + //m_databases.push_back(DatabasePtr(new CDatabaseRetroArch(strAddonButtonMapPath, false))); // TODO m_databases.push_back(DatabasePtr(new CDatabaseJoystickAPI(m_buttonMapper->GetCallbacks()))); for (auto& database : m_databases) m_buttonMapper->RegisterDatabase(database); + m_familyManager.Initialize(strAddonPath); + return true; } void CStorageManager::Deinitialize(void) { + m_familyManager.Deinitialize(); m_databases.clear(); m_buttonMapper.reset(); - m_peripheralLib = NULL; + m_peripheralLib = nullptr; } bool CStorageManager::GetFeatures(const ADDON::Joystick& joystick, diff --git a/src/storage/StorageManager.h b/src/storage/StorageManager.h index ada17e73..6d2b217d 100644 --- a/src/storage/StorageManager.h +++ b/src/storage/StorageManager.h @@ -21,6 +21,7 @@ #include "StorageTypes.h" #include "buttonmapper/ButtonMapTypes.h" +#include "buttonmapper/JoystickFamily.h" #include #include @@ -114,5 +115,6 @@ namespace JOYSTICK DatabaseVector m_databases; std::unique_ptr m_buttonMapper; + CJoystickFamilyManager m_familyManager; }; } diff --git a/src/storage/ButtonMapDefinitions.h b/src/storage/xml/ButtonMapDefinitions.h similarity index 86% rename from src/storage/ButtonMapDefinitions.h rename to src/storage/xml/ButtonMapDefinitions.h index 1013a5ab..332f6bcf 100644 --- a/src/storage/ButtonMapDefinitions.h +++ b/src/storage/xml/ButtonMapDefinitions.h @@ -19,16 +19,8 @@ */ #pragma once -#define RESOURCE_XML_EXTENSION ".xml" -#define RESOURCE_RETROARCH_EXTENSION ".cfg" - -#define RESOURCE_XML_FOLDER "xml" -#define RESOURCE_RETROARCH_FOLDER "retroarch" - -#define DEVICES_XML_ROOT "devices" -#define DEVICES_XML_ELEM_DEVICE "device" - #define BUTTONMAP_XML_ROOT "buttonmap" +#define BUTTONMAP_XML_ELEM_DEVICE "device" #define BUTTONMAP_XML_ELEM_CONTROLLER "controller" #define BUTTONMAP_XML_ELEM_FEATURE "feature" diff --git a/src/storage/xml/ButtonMapXml.cpp b/src/storage/xml/ButtonMapXml.cpp index 4e8b56f5..ff0e3e3c 100644 --- a/src/storage/xml/ButtonMapXml.cpp +++ b/src/storage/xml/ButtonMapXml.cpp @@ -19,9 +19,9 @@ */ #include "ButtonMapXml.h" +#include "ButtonMapDefinitions.h" #include "DeviceXml.h" #include "buttonmapper/ButtonMapTranslator.h" -#include "storage/ButtonMapDefinitions.h" #include "storage/Device.h" #include "log/Log.h" @@ -60,11 +60,11 @@ bool CButtonMapXml::Load(void) return false; } - const TiXmlElement* pDevice = pRootElement->FirstChildElement(DEVICES_XML_ELEM_DEVICE); + const TiXmlElement* pDevice = pRootElement->FirstChildElement(BUTTONMAP_XML_ELEM_DEVICE); if (!pDevice) { - esyslog("Can't find <%s> tag", DEVICES_XML_ELEM_DEVICE); + esyslog("Can't find <%s> tag", BUTTONMAP_XML_ELEM_DEVICE); return false; } @@ -134,7 +134,7 @@ bool CButtonMapXml::Save(void) const if (!pElem) return false; - TiXmlElement deviceElement(DEVICES_XML_ELEM_DEVICE); + TiXmlElement deviceElement(BUTTONMAP_XML_ELEM_DEVICE); TiXmlNode* deviceNode = pElem->InsertEndChild(deviceElement); if (deviceNode == NULL) return false; diff --git a/src/storage/xml/DatabaseXml.cpp b/src/storage/xml/DatabaseXml.cpp index 339b51e2..64276ad5 100644 --- a/src/storage/xml/DatabaseXml.cpp +++ b/src/storage/xml/DatabaseXml.cpp @@ -20,7 +20,7 @@ #include "DatabaseXml.h" #include "ButtonMapXml.h" -#include "storage/ButtonMapDefinitions.h" +#include "storage/StorageDefinitions.h" using namespace JOYSTICK; diff --git a/src/storage/xml/DeviceXml.cpp b/src/storage/xml/DeviceXml.cpp index 9833cf4c..fc5bbcd5 100644 --- a/src/storage/xml/DeviceXml.cpp +++ b/src/storage/xml/DeviceXml.cpp @@ -19,7 +19,7 @@ */ #include "DeviceXml.h" -#include "storage/ButtonMapDefinitions.h" +#include "ButtonMapDefinitions.h" #include "storage/Device.h" #include "storage/StorageUtils.h" #include "log/Log.h" @@ -55,7 +55,7 @@ bool CDeviceXml::Deserialize(const TiXmlElement* pElement, CDevice& record) const char* name = pElement->Attribute(BUTTONMAP_XML_ATTR_DEVICE_NAME); if (!name) { - esyslog("<%s> tag has no \"%s\" attribute", DEVICES_XML_ELEM_DEVICE, BUTTONMAP_XML_ATTR_DEVICE_NAME); + esyslog("<%s> tag has no \"%s\" attribute", BUTTONMAP_XML_ELEM_DEVICE, BUTTONMAP_XML_ATTR_DEVICE_NAME); return false; } record.SetName(name); @@ -63,7 +63,7 @@ bool CDeviceXml::Deserialize(const TiXmlElement* pElement, CDevice& record) const char* provider = pElement->Attribute(BUTTONMAP_XML_ATTR_DEVICE_PROVIDER); if (!provider) { - esyslog("<%s> tag has no \"%s\" attribute", DEVICES_XML_ELEM_DEVICE, BUTTONMAP_XML_ATTR_DEVICE_PROVIDER); + esyslog("<%s> tag has no \"%s\" attribute", BUTTONMAP_XML_ELEM_DEVICE, BUTTONMAP_XML_ATTR_DEVICE_PROVIDER); return false; } record.SetProvider(provider); diff --git a/src/storage/xml/JoystickFamiliesXml.cpp b/src/storage/xml/JoystickFamiliesXml.cpp index 25fdde78..3601285c 100644 --- a/src/storage/xml/JoystickFamiliesXml.cpp +++ b/src/storage/xml/JoystickFamiliesXml.cpp @@ -19,14 +19,88 @@ */ #include "JoystickFamiliesXml.h" +#include "JoystickFamilyDefinitions.h" +#include "log/Log.h" + +#include "tinyxml.h" using namespace JOYSTICK; -JoystickFamilyMap CJoystickFamiliesXml::LoadFamilies() +bool CJoystickFamiliesXml::LoadFamilies(const std::string& path, JoystickFamilyMap& result) { - JoystickFamilyMap result; + TiXmlDocument xmlFile; + if (!xmlFile.LoadFile(path)) + { + esyslog("Error opening %s: %s", path.c_str(), xmlFile.ErrorDesc()); + return false; + } + + TiXmlElement* pRootElement = xmlFile.RootElement(); + if (!pRootElement || pRootElement->NoChildren() || pRootElement->ValueStr() != JOYSTICK_FAMILIES_XML_ELEM_FAMILIES) + { + esyslog("Can't find root <%s> tag", JOYSTICK_FAMILIES_XML_ELEM_FAMILIES); + return false; + } + + const TiXmlElement* pFamily = pRootElement->FirstChildElement(JOYSTICK_FAMILIES_XML_ELEM_FAMILY); + + if (pFamily == nullptr) + { + esyslog("Can't find <%s> tag", JOYSTICK_FAMILIES_XML_ELEM_FAMILY); + return false; + } + + return Deserialize(pFamily, result); +} + +bool CJoystickFamiliesXml::Deserialize(const TiXmlElement* pFamily, JoystickFamilyMap& result) +{ + // For logging purposes + unsigned int totalJoystickCount = 0; + + while (pFamily != nullptr) + { + const char* familyName = pFamily->Attribute(JOYSTICK_FAMILIES_XML_ATTR_FAMILY_NAME); + if (!familyName) + { + esyslog("<%s> tag has no attribute \"%s\"", JOYSTICK_FAMILIES_XML_ELEM_FAMILY, + JOYSTICK_FAMILIES_XML_ATTR_FAMILY_NAME); + return false; + } + + std::set& family = result[familyName]; + + const TiXmlElement* pJoystick = pFamily->FirstChildElement(JOYSTICK_FAMILIES_XML_ELEM_JOYSTICK); + + if (pJoystick == nullptr) + { + esyslog("Joystick family \"%s\": Can't find <%s> tag", familyName, JOYSTICK_FAMILIES_XML_ELEM_JOYSTICK); + return false; + } + + if (!DeserializeJoysticks(pJoystick, family)) + return false; + + totalJoystickCount += family.size(); + + pFamily = pFamily->NextSiblingElement(JOYSTICK_FAMILIES_XML_ELEM_FAMILY); + } + + dsyslog("Loaded %d joystick families with %d total joysticks", result.size(), totalJoystickCount); + + return true; +} + +bool CJoystickFamiliesXml::DeserializeJoysticks(const TiXmlElement* pJoystick, std::set& family) +{ + while (pJoystick != nullptr) + { + const std::string& joystickName = pJoystick->ValueStr(); + + family.insert(joystickName); - // TODO + pJoystick = pJoystick->NextSiblingElement(JOYSTICK_FAMILIES_XML_ELEM_JOYSTICK); + } - return result; + return true; } diff --git a/src/storage/xml/JoystickFamiliesXml.h b/src/storage/xml/JoystickFamiliesXml.h index f55733a5..f214e271 100644 --- a/src/storage/xml/JoystickFamiliesXml.h +++ b/src/storage/xml/JoystickFamiliesXml.h @@ -21,11 +21,17 @@ #include "buttonmapper/ButtonMapTypes.h" +class TiXmlElement; + namespace JOYSTICK { class CJoystickFamiliesXml { public: - static JoystickFamilyMap LoadFamilies(); + static bool LoadFamilies(const std::string& path, JoystickFamilyMap& result); + + private: + static bool Deserialize(const TiXmlElement* pFamily, JoystickFamilyMap& result); + static bool DeserializeJoysticks(const TiXmlElement* pJoystick, std::set& family); }; } diff --git a/src/storage/xml/JoystickFamilyDefinitions.h b/src/storage/xml/JoystickFamilyDefinitions.h new file mode 100644 index 00000000..7823035f --- /dev/null +++ b/src/storage/xml/JoystickFamilyDefinitions.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2016 Garrett Brown + * Copyright (C) 2016 Team Kodi + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this Program; see the file COPYING. If not, see + * . + * + */ +#pragma once + +#define JOYSTICK_FAMILIES_FOLDER "joystickfamilies" +#define JOYSTICK_FAMILIES_RESOURCE "joystickfamilies.xml" + +#define JOYSTICK_FAMILIES_XML_ELEM_FAMILIES "joystickfamilies" +#define JOYSTICK_FAMILIES_XML_ELEM_FAMILY "joystickfamily" +#define JOYSTICK_FAMILIES_XML_ELEM_JOYSTICK "joystick" + +#define JOYSTICK_FAMILIES_XML_ATTR_FAMILY_NAME "name"