diff --git a/.vscode/settings.json b/.vscode/settings.json index 40ad65881..a55c4e90c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -93,6 +93,11 @@ "vector": "cpp", "memory_resource": "cpp", "cfenv": "cpp", - "cinttypes": "cpp" + "cinttypes": "cpp", + "filesystem": "cpp", + "forward_list": "cpp", + "regex": "cpp", + "valarray": "cpp", + "ranges": "cpp" } } diff --git a/src/common/JoyMap.cxx b/src/common/JoyMap.cxx index a49c1be4d..10905f71a 100644 --- a/src/common/JoyMap.cxx +++ b/src/common/JoyMap.cxx @@ -17,6 +17,7 @@ #include "JoyMap.hxx" #include "jsonDefinitions.hxx" +#include "Logger.hxx" using json = nlohmann::json; @@ -209,6 +210,31 @@ json JoyMap::saveMapping(const EventMode mode) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int JoyMap::loadMapping(const json& eventMappings, const EventMode mode) +{ + int i = 0; + + for (const json& eventMapping: eventMappings) { + try { + add( + eventMapping.at("event").get(), + mode, + eventMapping.at("button").get(), + eventMapping.at("axis").get(), + eventMapping.at("axisDirection").get(), + eventMapping.at("hat").get(), + eventMapping.at("hatDirection").get() + ); + + i++; + } catch (json::exception) { + Logger::error("ignoring invalid joystick event"); + } + } + + return i; +} +#if 0 int JoyMap::loadMapping(string& list, const EventMode mode) { // Since istringstream swallows whitespace, we have to make the @@ -226,6 +252,7 @@ int JoyMap::loadMapping(string& list, const EventMode mode) return i; } +#endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void JoyMap::eraseMode(const EventMode mode) diff --git a/src/common/JoyMap.hxx b/src/common/JoyMap.hxx index b480aad1b..d013e82bc 100644 --- a/src/common/JoyMap.hxx +++ b/src/common/JoyMap.hxx @@ -112,7 +112,7 @@ class JoyMap JoyMappingArray getEventMapping(const Event::Type event, const EventMode mode) const; nlohmann::json saveMapping(const EventMode mode) const; - int loadMapping(string& list, const EventMode mode); + int loadMapping(const nlohmann::json& eventMappings, const EventMode mode); /** Erase all mappings for given mode */ void eraseMode(const EventMode mode); diff --git a/src/common/PJoystickHandler.cxx b/src/common/PJoystickHandler.cxx index 2deeaf111..590fcda44 100644 --- a/src/common/PJoystickHandler.cxx +++ b/src/common/PJoystickHandler.cxx @@ -22,13 +22,12 @@ #include "Settings.hxx" #include "EventHandler.hxx" #include "PJoystickHandler.hxx" +#include "Logger.hxx" #ifdef GUI_SUPPORT #include "DialogContainer.hxx" #endif -static constexpr char CTRL_DELIM = '^'; - using json = nlohmann::json; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -37,25 +36,29 @@ PhysicalJoystickHandler::PhysicalJoystickHandler( : myOSystem(system), myHandler(handler) { - Int32 version = myOSystem.settings().getInt("event_ver"); - // Load previously saved joystick mapping (if any) from settings - istringstream buf(myOSystem.settings().getString("joymap")); - string joymap, joyname; + if(myOSystem.settings().getInt("event_ver") != Event::VERSION) { + Logger::info("event version mismatch; dropping previous joystick mappings"); - // First compare if event list version has changed, and disregard the entire - // mapping if true - getline(buf, joymap, CTRL_DELIM); // event list size, ignore - if(version == Event::VERSION) - { - // Otherwise, put each joystick mapping entry into the database - while(getline(buf, joymap, CTRL_DELIM)) - { - istringstream namebuf(joymap); - getline(namebuf, joyname, PhysicalJoystick::MODE_DELIM); - if(joyname.length() != 0) - // TODO: convert old mapping to json - myDatabase.emplace(joyname, StickInfo()); + return; + } + + json mappings; + + try { + mappings = json::parse(myOSystem.settings().getString("joymap")); + } catch (json::exception) { + // TODO: error handling + migration + + mappings = json::array(); + } + + for (const json& mapping: mappings) { + if (!mapping.contains("name")) { + Logger::error("igmoring bad joystick mapping"); + continue; } + + myDatabase.emplace(mapping.at("name").get(), StickInfo(mapping)); } } diff --git a/src/common/PhysicalJoystick.cxx b/src/common/PhysicalJoystick.cxx index dc45d4a10..67abd435e 100644 --- a/src/common/PhysicalJoystick.cxx +++ b/src/common/PhysicalJoystick.cxx @@ -23,14 +23,21 @@ #include "bspf.hxx" #include "PhysicalJoystick.hxx" #include "jsonDefinitions.hxx" +#include "Logger.hxx" using json = nlohmann::json; namespace { string jsonName(EventMode eventMode) { - json serializedName = eventMode; + return json(eventMode).get(); + } - return serializedName.get(); + EventMode eventModeFromJsonName(const string& name) { + EventMode result; + + from_json(json(name), result); + + return result; } } @@ -71,6 +78,35 @@ json PhysicalJoystick::getMap() const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool PhysicalJoystick::setMap(const json& map) +{ + int i = 0; + + for (auto& entry: map.items()) { + if (entry.key() == "name") continue; + + try { + joyMap.loadMapping(entry.value(), eventModeFromJsonName(entry.key())); + } catch (json::exception) { + Logger::error("ignoring invalid json mapping for " + entry.key()); + } + + i++; + } + + if(i != 5) + { + Logger::error("invalid controller mappings found for " + + ((map.contains("name") && map.at("name").is_string()) ? ("stick " + map["name"].get()) : "unknown stick") + ); + + return false; + } + + return true; +} + +#if 0 bool PhysicalJoystick::setMap(const string& mapString) { istringstream buf(mapString); @@ -104,6 +140,7 @@ bool PhysicalJoystick::setMap(const string& mapString) return true; } +#endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PhysicalJoystick::eraseMap(EventMode mode) diff --git a/src/common/PhysicalJoystick.hxx b/src/common/PhysicalJoystick.hxx index 1c331e0e8..027aba47f 100644 --- a/src/common/PhysicalJoystick.hxx +++ b/src/common/PhysicalJoystick.hxx @@ -46,7 +46,7 @@ class PhysicalJoystick PhysicalJoystick() = default; nlohmann::json getMap() const; - bool setMap(const string& map); + bool setMap(const nlohmann::json& map); void eraseMap(EventMode mode); void eraseEvent(Event::Type event, EventMode mode); string about() const;