From 1b65eaac2ed9343c33135477a27ab58719ee33d5 Mon Sep 17 00:00:00 2001 From: Leon Styhre Date: Tue, 14 Jul 2020 19:16:21 +0200 Subject: [PATCH] Improved input device configuration. Default keyboard mappings are now applied if the user has not configured the keyboard. --- CONTRIBUTING.md | 1 + NEWS.md | 1 + es-app/src/main.cpp | 5 ++ es-app/src/views/UIModeController.cpp | 64 +++++++++++----------- es-app/src/views/ViewController.cpp | 24 ++++++++- es-core/src/InputConfig.cpp | 7 +-- es-core/src/InputConfig.h | 5 ++ es-core/src/InputManager.cpp | 38 ++++++++++---- es-core/src/InputManager.h | 46 ++++++++-------- es-core/src/Settings.cpp | 3 +- es-core/src/Window.cpp | 11 ++-- es-core/src/Window.h | 6 ++- es-core/src/guis/GuiDetectDevice.cpp | 2 +- es-core/src/guis/GuiInputConfig.cpp | 76 +++++++++++++++------------ 14 files changed, 178 insertions(+), 111 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c0048323a..1ac26f5a3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,6 +38,7 @@ https://google.github.io/styleguide/cppguide.html * Comments should be proper sentences, starting with a capital letter and ending with a dot * Use K&R placements of braces, read the Linux Kernel coding style document for clarifications * Always use spaces between keywords and opening brackets, i.e. `if ()`, `for ()`, `while ()` etc. +* Indentation of switch/case statements is optional, but it's usually easier to read the code with indentations in place * Use `std::string` instead of `char *` or `char []` unless there is a specific reason requiring the latter * If the arguments (and initializer list) for a function or class exceeds 4 items, arrange them vertically to make the code easier to read * Always declare one variable per line, never combine multiple declarations of the same type diff --git a/NEWS.md b/NEWS.md index e3a374659..b5d939404 100644 --- a/NEWS.md +++ b/NEWS.md @@ -18,6 +18,7 @@ v1.0.0 * Per-game launch command override, so that different cores or emulators can be used on a per-game basis (saved to gamelist.xml) * Core location can be defined relative to the emulator binary using the %EMUPATH% varible in es_systems.cfg (mostly useful for Windows) * Help system updated and expanded to the complete application (previously it was only partially implemented) +* Improved input device configuration, and default keyboard mappings are now applied if the keyboard has not been configured by the user * GUI-configurable option to sort favorite games on the top of the game lists (favorites marked with stars) * Added new component GuiComplexTextEditPopup to handle changes to configuration file entries and similar * Speed improvements and optimizations, the application now starts faster and feels more responsive diff --git a/es-app/src/main.cpp b/es-app/src/main.cpp index 8223c7892..4f703f8d7 100644 --- a/es-app/src/main.cpp +++ b/es-app/src/main.cpp @@ -495,6 +495,11 @@ int main(int argc, char* argv[]) ViewController::get()->goToStart(); } else { + // Always reset ShowDefaultKeyboardWarning to true if the es_input.cfg + // file is missing. + Settings::getInstance()->setBool("ShowDefaultKeyboardWarning", true); + Settings::getInstance()->saveFile(); + window.pushGui(new GuiDetectDevice(&window, true, [] { ViewController::get()->goToStart(); })); } diff --git a/es-app/src/views/UIModeController.cpp b/es-app/src/views/UIModeController.cpp index 8cd506c0a..824f53ab2 100644 --- a/es-app/src/views/UIModeController.cpp +++ b/es-app/src/views/UIModeController.cpp @@ -12,9 +12,9 @@ #include "Log.h" #include "Window.h" -UIModeController * UIModeController::sInstance = nullptr; +UIModeController* UIModeController::sInstance = nullptr; -UIModeController * UIModeController::getInstance() +UIModeController* UIModeController::getInstance() { if (sInstance == nullptr) sInstance = new UIModeController(); @@ -39,7 +39,7 @@ void UIModeController::monitorUIMode() } } -bool UIModeController::listen(InputConfig * config, Input input) +bool UIModeController::listen(InputConfig* config, Input input) { // Reads the current input to listen for the passkey sequence to unlock // the UI mode. The progress is saved in mPassKeyCounter. @@ -59,7 +59,7 @@ bool UIModeController::listen(InputConfig * config, Input input) return false; } -bool UIModeController::inputIsMatch(InputConfig * config, Input input) +bool UIModeController::inputIsMatch(InputConfig* config, Input input) { for (auto valstring : mInputVals) { if (config->isMappedLike(valstring, input) && @@ -107,36 +107,36 @@ std::string UIModeController::getFormattedPassKeyStr() out += (out == "") ? "" : ", "; // Add a comma after the first entry. switch (c) { - case 'u': - out += Utils::String::unicode2Chars(0x2191); // Arrow pointing up. - break; - case 'd': - out += Utils::String::unicode2Chars(0x2193); // Arrow pointing down. - break; - case 'l': - out += Utils::String::unicode2Chars(0x2190); // Arrow pointing left. - break; - case 'r': - out += Utils::String::unicode2Chars(0x2192); // Arrow pointing right. - break; - case 'a': - out += "A"; - break; - case 'b': - out += "B"; - break; - case 'x': - out += "X"; - break; - case 'y': - out += "Y"; - break; + case 'u': + out += Utils::String::unicode2Chars(0x2191); // Arrow pointing up. + break; + case 'd': + out += Utils::String::unicode2Chars(0x2193); // Arrow pointing down. + break; + case 'l': + out += Utils::String::unicode2Chars(0x2190); // Arrow pointing left. + break; + case 'r': + out += Utils::String::unicode2Chars(0x2192); // Arrow pointing right. + break; + case 'a': + out += "A"; + break; + case 'b': + out += "B"; + break; + case 'x': + out += "X"; + break; + case 'y': + out += "Y"; + break; } } return out; } -void UIModeController::logInput(InputConfig * config, Input input) +void UIModeController::logInput(InputConfig* config, Input input) { std::string mapname = ""; std::vector maps = config->getMappedTo(input); @@ -146,11 +146,11 @@ void UIModeController::logInput(InputConfig * config, Input input) mapname += ", "; } - LOG(LogDebug) << "UIModeController::logInput(" << config->getDeviceName() << - "): " << input.string() << ", isMappedTo=" << mapname << ", value=" << input.value; + LOG(LogDebug) << "UIModeController::logInput(" << config->getDeviceName() << "): " << + input.string() << ", isMappedTo=" << mapname << ", value=" << input.value; } -bool UIModeController::isValidInput(InputConfig * config, Input input) +bool UIModeController::isValidInput(InputConfig* config, Input input) { if ((config->getMappedTo(input).size() == 0) || // Not a mapped input, so ignore.. (input.type == TYPE_HAT) || // Ignore all hat inputs. diff --git a/es-app/src/views/ViewController.cpp b/es-app/src/views/ViewController.cpp index 903173141..556cd3b31 100644 --- a/es-app/src/views/ViewController.cpp +++ b/es-app/src/views/ViewController.cpp @@ -14,6 +14,7 @@ #include "animations/LaunchAnimation.h" #include "animations/MoveCameraAnimation.h" #include "guis/GuiMenu.h" +#include "guis/GuiMsgBox.h" #include "views/gamelist/DetailedGameListView.h" #include "views/gamelist/IGameListView.h" #include "views/gamelist/GridGameListView.h" @@ -21,11 +22,12 @@ #include "views/SystemView.h" #include "views/UIModeController.h" #include "FileFilterIndex.h" +#include "InputManager.h" #include "Log.h" #include "Settings.h" +#include "Sound.h" #include "SystemData.h" #include "Window.h" -#include "Sound.h" ViewController* ViewController::sInstance = nullptr; @@ -60,6 +62,26 @@ ViewController::~ViewController() void ViewController::goToStart() { + // Check if the keyboard config is set as application default, meaning no user + // configuration has been performed. + if (InputManager::getInstance()-> + getInputConfigByDevice(DEVICE_KEYBOARD)->getDefaultConfigFlag()) { + if (Settings::getInstance()->getBool("ShowDefaultKeyboardWarning")) { + std::string message = "NO KEYBOARD CONFIGURATION COULD BE\n" + "FOUND IN ES_INPUT.CFG, SO APPLYING THE\n" + "DEFAULT KEYBOARD MAPPINGS. IT'S HOWEVER\n" + "RECOMMENDED TO SETUP YOUR OWN KEYBOARD\n" + "CONFIGURATION. TO DO SO, CHOOSE THE ENTRY\n" + "\"CONFIGURE INPUT\" ON THE MAIN MENU."; + + mWindow->pushGui(new GuiMsgBox(mWindow, HelpStyle(), message.c_str(), + "OK", nullptr, "DON'T SHOW AGAIN", [] { + Settings::getInstance()->setBool("ShowDefaultKeyboardWarning", false); + Settings::getInstance()->saveFile(); + })); + } + } + // If a specific system is requested, go directly to its game list. auto requestedSystem = Settings::getInstance()->getString("StartupSystem"); if ("" != requestedSystem && "retropie" != requestedSystem) { diff --git a/es-core/src/InputConfig.cpp b/es-core/src/InputConfig.cpp index 86c262dcb..e610528f8 100644 --- a/es-core/src/InputConfig.cpp +++ b/es-core/src/InputConfig.cpp @@ -59,7 +59,8 @@ InputConfig::InputConfig( const std::string& deviceGUID) : mDeviceId(deviceId), mDeviceName(deviceName), - mDeviceGUID(deviceGUID) + mDeviceGUID(deviceGUID), + mDefaultConfigFlag(false) { } @@ -186,7 +187,7 @@ void InputConfig::loadFromXML(pugi::xml_node& node) InputType typeEnum = stringToInputType(type); if (typeEnum == TYPE_COUNT) { - LOG(LogError) << "InputConfig load error - input of type \"" << type << + LOG(LogError) << "Error - InputConfig load error - input of type \"" << type << "\" is invalid! Skipping input \"" << name << "\".\n"; continue; } @@ -195,7 +196,7 @@ void InputConfig::loadFromXML(pugi::xml_node& node) int value = input.attribute("value").as_int(); if (value == 0) { - LOG(LogWarning) << "WARNING: InputConfig value is 0 for " << + LOG(LogWarning) << "Warning - InputConfig value is 0 for " << type << " " << id << "!\n"; } diff --git a/es-core/src/InputConfig.h b/es-core/src/InputConfig.h index 3bbdf7215..d38a37ff0 100644 --- a/es-core/src/InputConfig.h +++ b/es-core/src/InputConfig.h @@ -128,6 +128,10 @@ public: inline const std::string& getDeviceName() { return mDeviceName; } inline const std::string& getDeviceGUIDString() { return mDeviceGUID; } + void setDefaultConfigFlag() { mDefaultConfigFlag = true; }; + void unsetDefaultConfigFlag() { mDefaultConfigFlag = false; }; + bool getDefaultConfigFlag() { return mDefaultConfigFlag; }; + // Returns true if Input is mapped to this name, false otherwise. bool isMappedTo(const std::string& name, Input input); bool isMappedLike(const std::string& name, Input input); @@ -149,6 +153,7 @@ private: const int mDeviceId; const std::string mDeviceName; const std::string mDeviceGUID; + bool mDefaultConfigFlag; }; #endif // ES_CORE_INPUT_CONFIG_H diff --git a/es-core/src/InputManager.cpp b/es-core/src/InputManager.cpp index 947095490..66ef837cc 100644 --- a/es-core/src/InputManager.cpp +++ b/es-core/src/InputManager.cpp @@ -299,8 +299,15 @@ bool InputManager::parseEvent(const SDL_Event& ev, Window* window) bool InputManager::loadInputConfig(InputConfig* config) { std::string path = getConfigPath(); - if (!Utils::FileSystem::exists(path)) + if (!Utils::FileSystem::exists(path)) { + if (config->getDeviceName() == "Keyboard") { + LOG(LogDebug) << "InputManager::loadInputConfig(): Assigning default keyboard " + "mappings as there is no es_input.cfg configuration file."; + loadDefaultKBConfig(); + config->setDefaultConfigFlag(); + } return false; + } pugi::xml_document doc; #ifdef _WIN64 @@ -323,17 +330,25 @@ bool InputManager::loadInputConfig(InputConfig* config) if (!configNode) configNode = root.find_child_by_attribute("inputConfig", "deviceName", config->getDeviceName().c_str()); - if (!configNode) - return false; + if (!configNode) { + if (config->getDeviceName() == "Keyboard") { + LOG(LogDebug) << "InputManager::loadInputConfig(): Assigning default keyboard " + "mappings as there is no keyboard configuration in es_input.cfg."; + loadDefaultKBConfig(); + config->setDefaultConfigFlag(); + return true; + } + else { + return false; + } + } config->loadFromXML(configNode); return true; } -// Used in an "emergency" where no keyboard config could be loaded from the inputmanager -// config file. Allows the user to select to reconfigure in menus if this happens without -// having to delete es_input.cfg manually. -// Note: Not currently used. +// If there is no es_input.cfg file or if the user has not yet configured the keyboard +// mappings, then load these defaults. void InputManager::loadDefaultKBConfig() { InputConfig* cfg = getInputConfigByDevice(DEVICE_KEYBOARD); @@ -363,6 +378,9 @@ void InputManager::writeDeviceConfig(InputConfig* config) std::string path = getConfigPath(); + LOG(LogDebug) << "InputManager::writeDeviceConfig(): " + "Saving input configuration file to " << path; + pugi::xml_document doc; if (Utils::FileSystem::exists(path)) { @@ -420,7 +438,7 @@ void InputManager::writeDeviceConfig(InputConfig* config) Scripting::fireEvent("config-changed"); Scripting::fireEvent("controls-changed"); - // Execute any doOnFinish commands and re-load the config for changes. + // Execute any doOnFinish commands and reload the config for changes. doOnFinish(); loadInputConfig(config); } @@ -440,7 +458,7 @@ void InputManager::doOnFinish() #endif if (!result) { - LOG(LogError) << "Error parsing input config: " << result.description(); + LOG(LogError) << "Error - Couldn't parse input config: " << result.description(); } else { pugi::xml_node root = doc.child("inputList"); @@ -514,7 +532,7 @@ std::string InputManager::getDeviceGUIDString(int deviceId) auto it = mJoysticks.find(deviceId); if (it == mJoysticks.cend()) { - LOG(LogError) << "getDeviceGUIDString - deviceId " << deviceId << " not found!"; + LOG(LogError) << "Error - getDeviceGUIDString - deviceId " << deviceId << " not found!"; return "something went horribly wrong"; } diff --git a/es-core/src/InputManager.h b/es-core/src/InputManager.h index 0fd0c09d5..ce8a82300 100644 --- a/es-core/src/InputManager.h +++ b/es-core/src/InputManager.h @@ -25,29 +25,6 @@ union SDL_Event; // You should only ever instantiate one of these, by the way. class InputManager { -private: - InputManager(); - - static InputManager* mInstance; - - static const int DEADZONE = 23000; - - void loadDefaultKBConfig(); - - std::map mJoysticks; - std::map mInputConfigs; - InputConfig* mKeyboardInputConfig; - InputConfig* mCECInputConfig; - - std::map mPrevAxisValues; - - bool initialized() const; - - void addJoystickByDeviceIndex(int id); - void removeJoystickByJoystickID(SDL_JoystickID id); - // Returns true if successfully loaded, false if not (or if it didn't exist). - bool loadInputConfig(InputConfig* config); - public: virtual ~InputManager(); @@ -71,6 +48,29 @@ public: InputConfig* getInputConfigByDevice(int deviceId); bool parseEvent(const SDL_Event& ev, Window* window); + +private: + InputManager(); + + static InputManager* mInstance; + + static const int DEADZONE = 23000; + + void loadDefaultKBConfig(); + + std::map mJoysticks; + std::map mInputConfigs; + InputConfig* mKeyboardInputConfig; + InputConfig* mCECInputConfig; + + std::map mPrevAxisValues; + + bool initialized() const; + + void addJoystickByDeviceIndex(int id); + void removeJoystickByJoystickID(SDL_JoystickID id); + // Returns true if successfully loaded, false if not (or if it didn't exist). + bool loadInputConfig(InputConfig* config); }; #endif // ES_CORE_INPUT_MANAGER_H diff --git a/es-core/src/Settings.cpp b/es-core/src/Settings.cpp index d55cbf1e3..a0fae1243 100644 --- a/es-core/src/Settings.cpp +++ b/es-core/src/Settings.cpp @@ -214,9 +214,10 @@ void Settings::setDefaults() // // Settings that can be changed in es_settings.cfg - // but that are not configurable via the GUI (yet). + // but that are not configurable via the GUI. // + mBoolMap["ShowDefaultKeyboardWarning"] = true; mStringMap["DefaultSortOrder"] = "filename, ascending"; mStringMap["MediaDirectory"] = ""; mStringMap["ROMDirectory"] = ""; diff --git a/es-core/src/Window.cpp b/es-core/src/Window.cpp index 88215a46c..204e1e63e 100644 --- a/es-core/src/Window.cpp +++ b/es-core/src/Window.cpp @@ -13,6 +13,7 @@ #include "InputManager.h" #include "Log.h" #include "Scripting.h" + #include #include @@ -130,7 +131,8 @@ void Window::input(InputConfig* config, Input input) if (mScreenSaver->isScreenSaverActive() && Settings::getInstance()->getBool("ScreenSaverControls") && (Settings::getInstance()->getString("ScreenSaverBehavior") == "random video")) { - if (mScreenSaver->getCurrentGame() != nullptr && (config->isMappedLike("right", input) || + if (mScreenSaver->getCurrentGame() != nullptr && + (config->isMappedLike("right", input) || config->isMappedTo("start", input) || config->isMappedTo("select", input))) { if (config->isMappedLike("right", input) || config->isMappedTo("select", input)) { if (input.value != 0) { @@ -140,7 +142,7 @@ void Window::input(InputConfig* config, Input input) return; } else if (config->isMappedTo("start", input) && input.value != 0) { - // Launch game! + // Launch game. cancelScreenSaver(); mScreenSaver->launchGame(); // To force handling the wake up process. @@ -217,7 +219,7 @@ void Window::update(int deltaTime) float fontVramUsageMb = Font::getTotalMemUsage() / 1000.0f / 1000.0f; ss << "\nFont VRAM: " << fontVramUsageMb << " Tex VRAM: " << textureVramUsageMb << - " Tex Max: " << textureTotalUsageMb; + " Tex Max: " << textureTotalUsageMb; mFrameDataText = std::unique_ptr (mDefaultFonts.at(1)->buildTextCache(ss.str(), 50.f, 50.f, 0xFF00FFFF)); } @@ -388,8 +390,7 @@ void Window::setHelpPrompts(const std::vector& prompts, const HelpSt int i = 0; int aVal = 0; int bVal = 0; - while (map[i] != nullptr) - { + while (map[i] != nullptr) { if (a.first == map[i]) aVal = i; if (b.first == map[i]) diff --git a/es-core/src/Window.h b/es-core/src/Window.h index 77b450f20..567687ca2 100644 --- a/es-core/src/Window.h +++ b/es-core/src/Window.h @@ -27,7 +27,8 @@ struct HelpStyle; class Window { public: - class ScreenSaver { + class ScreenSaver + { public: virtual void startScreenSaver() = 0; virtual void stopScreenSaver() = 0; @@ -41,7 +42,8 @@ public: virtual void resetCounts() = 0; }; - class InfoPopup { + class InfoPopup + { public: virtual void render(const Transform4x4f& parentTrans) = 0; virtual void stop() = 0; diff --git a/es-core/src/guis/GuiDetectDevice.cpp b/es-core/src/guis/GuiDetectDevice.cpp index 9dfb82c9e..adefabb41 100644 --- a/es-core/src/guis/GuiDetectDevice.cpp +++ b/es-core/src/guis/GuiDetectDevice.cpp @@ -51,7 +51,7 @@ GuiDetectDevice::GuiDetectDevice( // Message. mMsg1 = std::make_shared(mWindow, - "HOLD A BUTTON ON YOUR DEVICE TO CONFIGURE IT.", + "HOLD A BUTTON ON YOUR DEVICE OR KEYBOARD TO CONFIGURE IT.", Font::get(FONT_SIZE_SMALL), 0x777777FF, ALIGN_CENTER); mGrid.setEntry(mMsg1, Vector2i(0, 2), false, true); diff --git a/es-core/src/guis/GuiInputConfig.cpp b/es-core/src/guis/GuiInputConfig.cpp index 909f639ed..a859b1054 100755 --- a/es-core/src/guis/GuiInputConfig.cpp +++ b/es-core/src/guis/GuiInputConfig.cpp @@ -200,41 +200,51 @@ GuiInputConfig::GuiInputConfig( // Buttons. std::vector< std::shared_ptr > buttons; std::function okFunction = [this, okCallback] { - InputManager::getInstance()->writeDeviceConfig(mTargetConfig); // save + // If we have just configured the keyboard, then unset the flag to indicate that + // we are using the default keyboard mappings. + if (mTargetConfig->getDeviceId() == DEVICE_KEYBOARD) { + InputManager::getInstance()-> + getInputConfigByDevice(DEVICE_KEYBOARD)->unsetDefaultConfigFlag(); + } + InputManager::getInstance()->writeDeviceConfig(mTargetConfig); // Save. if (okCallback) okCallback(); delete this; }; - buttons.push_back(std::make_shared(mWindow, "OK", "ok", [this, okFunction] { - // Check if the hotkey enable button is set. if not prompt the - // user to use select or nothing. - Input input; - okFunction(); - // Temporarily commented out, needs to be properly cleaned up later. -// if (!mTargetConfig->getInputByName("HotKeyEnable", &input)) { -// mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(), -// "YOU DIDN'T CHOOSE A HOTKEY ENABLE BUTTON. THIS IS REQUIRED FOR EXITING GAMES " -// "WITH A CONTROLLER. DO YOU WANT TO USE THE SELECT BUTTON DEFAULT ? PLEASE ANSWER " -// "YES TO USE SELECT OR NO TO NOT SET A HOTKEY ENABLE BUTTON.", -// "YES", [this, okFunction] { -// Input input; -// mTargetConfig->getInputByName("Select", &input); -// mTargetConfig->mapInput("HotKeyEnable", input); -// okFunction(); -// }, -// "NO", [this, okFunction] { -// // for a disabled hotkey enable button, set to a key with id 0, -// // so the input configuration script can be backwards compatible. -// mTargetConfig->mapInput("HotKeyEnable", Input(DEVICE_KEYBOARD, -// TYPE_KEY, 0, 1, true)); -// okFunction(); -// } -// )); -// } -// else { -// okFunction(); -// } - })); + + buttons.push_back(std::make_shared + (mWindow, "OK", "ok", [this, okFunction] { okFunction(); })); + +// This code is disabled as there is no intention to provide emulator configuration or +// control via ES Desktop Edition. Let's keep the code for reference though. +// buttons.push_back(std::make_shared(mWindow, "OK", "ok", [this, okFunction] { +// // Check if the hotkey enable button is set. if not prompt the +// // user to use select or nothing. +// Input input; +// okFunction(); +// if (!mTargetConfig->getInputByName("HotKeyEnable", &input)) { +// mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(), +// "YOU DIDN'T CHOOSE A HOTKEY ENABLE BUTTON. THIS IS REQUIRED FOR EXITING " +// "GAMES WITH A CONTROLLER. DO YOU WANT TO USE THE SELECT BUTTON DEFAULT ? " +// "PLEASE ANSWER YES TO USE SELECT OR NO TO NOT SET A HOTKEY ENABLE BUTTON.", +// "YES", [this, okFunction] { +// Input input; +// mTargetConfig->getInputByName("Select", &input); +// mTargetConfig->mapInput("HotKeyEnable", input); +// okFunction(); +// }, +// "NO", [this, okFunction] { +// // For a disabled hotkey enable button, set to a key with id 0, +// // so the input configuration script can be backwards compatible. +// mTargetConfig->mapInput("HotKeyEnable", Input(DEVICE_KEYBOARD, +// TYPE_KEY, 0, 1, true)); +// okFunction(); +// })); +// } +// else { +// okFunction(); +// } +// })); mButtonGrid = makeButtonGrid(mWindow, buttons); mGrid.setEntry(mButtonGrid, Vector2i(0, 6), true, false); @@ -354,8 +364,8 @@ bool GuiInputConfig::assign(Input input, int inputId) input.configured = true; mTargetConfig->mapInput(GUI_INPUT_CONFIG_LIST[inputId].name, input); - LOG(LogInfo) << " Mapping [" << input.string() << "] -> " << - GUI_INPUT_CONFIG_LIST[inputId].name; + LOG(LogInfo) << "Mapping [" << input.string() << "] to [" << + GUI_INPUT_CONFIG_LIST[inputId].name << "]"; return true; }