1 /*
2 * Copyright (C) 2015-2020 Garrett Brown
3 * Copyright (C) 2015-2020 Team Kodi
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSE.md for more information.
7 */
8
9 #include "StorageManager.h"
10 #include "JustABunchOfFiles.h"
11 #include "StorageUtils.h"
12 #include "buttonmapper/ButtonMapper.h"
13 #include "log/Log.h"
14 #include "storage/api/DatabaseJoystickAPI.h"
15 //#include "storage/retroarch/DatabaseRetroarch.h" // TODO
16 #include "storage/xml/DatabaseXml.h"
17
18 #include "addon.h"
19
20 #include <kodi/tools/StringUtils.h>
21
22 using namespace JOYSTICK;
23
24 // Resources folder for add-on and user data
25 #define USER_RESOURCES_FOLDER "resources"
26 #define ADDON_RESOURCES_FOLDER "resources"
27
28 // Subdirectory under resources folder for storing button maps
29 #define BUTTONMAP_FOLDER "buttonmaps"
30
CStorageManager(void)31 CStorageManager::CStorageManager(void) :
32 m_peripheralLib(nullptr)
33 {
34 }
35
~CStorageManager()36 CStorageManager::~CStorageManager()
37 {
38 Deinitialize();
39 }
40
Get(void)41 CStorageManager& CStorageManager::Get(void)
42 {
43 static CStorageManager _instance;
44 return _instance;
45 }
46
Initialize(CPeripheralJoystick * peripheralLib)47 bool CStorageManager::Initialize(CPeripheralJoystick* peripheralLib)
48 {
49 std::string strUserPath = peripheralLib->UserPath();
50 std::string strAddonPath = peripheralLib->AddonPath();
51
52 if (peripheralLib == NULL || strUserPath.empty() || strAddonPath.empty())
53 return false;
54
55 m_peripheralLib = peripheralLib;
56
57 m_buttonMapper.reset(new CButtonMapper(peripheralLib));
58
59 if (!m_buttonMapper->Initialize(m_familyManager))
60 return false;
61
62 // Remove slash at end
63 kodi::tools::StringUtils::TrimRight(strUserPath, "\\/");
64 kodi::tools::StringUtils::TrimRight(strAddonPath, "\\/");
65
66 strUserPath += "/" USER_RESOURCES_FOLDER;
67 strAddonPath += "/" ADDON_RESOURCES_FOLDER;
68
69 // Ensure resources path exists in user data
70 CStorageUtils::EnsureDirectoryExists(strUserPath);
71
72 std::string strUserButtonMapPath = strUserPath + "/" BUTTONMAP_FOLDER;
73 std::string strAddonButtonMapPath = strAddonPath + "/" BUTTONMAP_FOLDER;
74
75 // Ensure button map path exists in user data
76 CStorageUtils::EnsureDirectoryExists(strUserButtonMapPath);
77
78 m_databases.push_back(DatabasePtr(new CDatabaseXml(strUserButtonMapPath, true, m_buttonMapper->GetCallbacks(), this)));
79 //m_databases.push_back(DatabasePtr(new CDatabaseRetroArch(strUserButtonMapPath, true, &m_controllerMapper))); // TODO
80 m_databases.push_back(DatabasePtr(new CDatabaseXml(strAddonButtonMapPath, false, m_buttonMapper->GetCallbacks(), this)));
81 //m_databases.push_back(DatabasePtr(new CDatabaseRetroArch(strAddonButtonMapPath, false))); // TODO
82
83 m_databases.push_back(DatabasePtr(new CDatabaseJoystickAPI(m_buttonMapper->GetCallbacks())));
84
85 for (auto& database : m_databases)
86 m_buttonMapper->RegisterDatabase(database);
87
88 m_familyManager.Initialize(strAddonPath);
89
90 return true;
91 }
92
Deinitialize(void)93 void CStorageManager::Deinitialize(void)
94 {
95 m_familyManager.Deinitialize();
96 m_databases.clear();
97 m_buttonMapper.reset();
98 m_peripheralLib = nullptr;
99 }
100
GetFeatures(const kodi::addon::Joystick & joystick,const std::string & strControllerId,FeatureVector & features)101 void CStorageManager::GetFeatures(const kodi::addon::Joystick& joystick,
102 const std::string& strControllerId,
103 FeatureVector& features)
104 {
105 if (m_buttonMapper)
106 m_buttonMapper->GetFeatures(joystick, strControllerId, features);
107 }
108
MapFeatures(const kodi::addon::Joystick & joystick,const std::string & strControllerId,const FeatureVector & features)109 bool CStorageManager::MapFeatures(const kodi::addon::Joystick& joystick,
110 const std::string& strControllerId,
111 const FeatureVector& features)
112 {
113 bool bSuccess = false;
114
115 for (DatabaseVector::const_iterator it = m_databases.begin(); it != m_databases.end(); ++it)
116 bSuccess |= (*it)->MapFeatures(joystick, strControllerId, features);
117
118 return bSuccess;
119 }
120
GetIgnoredPrimitives(const kodi::addon::Joystick & joystick,PrimitiveVector & primitives)121 void CStorageManager::GetIgnoredPrimitives(const kodi::addon::Joystick& joystick, PrimitiveVector& primitives)
122 {
123 for (DatabaseVector::const_iterator it = m_databases.begin(); it != m_databases.end(); ++it)
124 {
125 if ((*it)->GetIgnoredPrimitives(joystick, primitives))
126 break;
127 }
128 }
129
SetIgnoredPrimitives(const kodi::addon::Joystick & joystick,const PrimitiveVector & primitives)130 bool CStorageManager::SetIgnoredPrimitives(const kodi::addon::Joystick& joystick, const PrimitiveVector& primitives)
131 {
132 bool bSuccess = false;
133
134 for (DatabaseVector::const_iterator it = m_databases.begin(); it != m_databases.end(); ++it)
135 bSuccess |= (*it)->SetIgnoredPrimitives(joystick, primitives);
136
137 return bSuccess;
138 }
139
SaveButtonMap(const kodi::addon::Joystick & joystick)140 bool CStorageManager::SaveButtonMap(const kodi::addon::Joystick& joystick)
141 {
142 bool bModified = false;
143
144 for (DatabaseVector::const_iterator it = m_databases.begin(); it != m_databases.end(); ++it)
145 bModified |= (*it)->SaveButtonMap(joystick);
146
147 return bModified;
148 }
149
RevertButtonMap(const kodi::addon::Joystick & joystick)150 bool CStorageManager::RevertButtonMap(const kodi::addon::Joystick& joystick)
151 {
152 bool bModified = false;
153
154 for (DatabaseVector::const_iterator it = m_databases.begin(); it != m_databases.end(); ++it)
155 bModified |= (*it)->RevertButtonMap(joystick);
156
157 return bModified;
158 }
159
ResetButtonMap(const kodi::addon::Joystick & joystick,const std::string & strControllerId)160 bool CStorageManager::ResetButtonMap(const kodi::addon::Joystick& joystick, const std::string& strControllerId)
161 {
162 bool bModified = false;
163
164 for (DatabaseVector::const_iterator it = m_databases.begin(); it != m_databases.end(); ++it)
165 bModified |= (*it)->ResetButtonMap(joystick, strControllerId);
166
167 return bModified;
168 }
169
RefreshButtonMaps(const std::string & strDeviceName)170 void CStorageManager::RefreshButtonMaps(const std::string& strDeviceName /* = "" */)
171 {
172 // Request the frontend to refresh its button maps
173 if (m_peripheralLib)
174 m_peripheralLib->RefreshButtonMaps(strDeviceName);
175 }
176
FeatureType(const std::string & strControllerId,const std::string & featureName)177 JOYSTICK_FEATURE_TYPE CStorageManager::FeatureType(const std::string& strControllerId, const std::string &featureName)
178 {
179 if (m_peripheralLib)
180 return m_peripheralLib->FeatureType(strControllerId, featureName);
181
182 return JOYSTICK_FEATURE_TYPE_UNKNOWN;
183 }
184