From 7231d948bc05309360d8e283e6d4ba9ae8fb990c Mon Sep 17 00:00:00 2001 From: Bliblank Date: Tue, 9 Jun 2026 22:39:38 -0500 Subject: [PATCH] add config integration for keymap and logger --- config/sonobulus.cfg | 341 ++++++++++++++++++++++++++++++- src/ConfigService.cpp | 45 ---- src/ConfigService.hpp | 84 +++++++- src/LoggerService.cpp | 2 +- src/main.cpp | 3 + src/synth/KeyboardController.cpp | 35 +--- src/synth/KeyboardController.hpp | 8 +- 7 files changed, 437 insertions(+), 81 deletions(-) diff --git a/config/sonobulus.cfg b/config/sonobulus.cfg index 7498971..7cdcc76 100644 --- a/config/sonobulus.cfg +++ b/config/sonobulus.cfg @@ -1,5 +1,5 @@ -Loggers = ( +Logger = ( { Id = "Engine"; @@ -17,4 +17,341 @@ Loggers = ( FileEnabled = true; FilePath = "Engine.log"; } -); \ No newline at end of file +); + +KeyboardController = ( + { + Id = "Main"; + + Keymap = { + Key_Shift = "B_2"; + Key_Z = "C_3"; + Key_S = "Db3"; + Key_X = "D_3"; + Key_D = "Eb3"; + Key_C = "E_3"; + Key_V = "F_3"; + Key_G = "Gb3"; + Key_B = "G_3"; + Key_H = "Ab3"; + Key_N = "A_3"; + Key_J = "Bb3"; + Key_M = "B_3"; + Key_Q = "C_4"; + Key_2 = "Db4"; + Key_W = "D_4"; + Key_3 = "Eb4"; + Key_E = "E_4"; + Key_R = "F_4"; + Key_5 = "Gb4"; + Key_T = "G_4"; + Key_6 = "Ab4"; + Key_Y = "A_4"; + Key_7 = "Bb4"; + Key_U = "B_4"; + Key_I = "C_5"; + Key_9 = "Db5"; + Key_O = "D_5"; + }; + + Notes = { + A_0 = 21; + Bb0 = 22; + B_0 = 23; + C_1 = 24; + Db1 = 25; + D_1 = 26; + Eb1 = 27; + E_1 = 28; + F_1 = 29; + Gb1 = 30; + G_1 = 31; + Ab1 = 32; + A_1 = 33; + Bb1 = 34; + B_1 = 35; + C_2 = 36; + Db2 = 37; + D_2 = 38; + Eb2 = 39; + E_2 = 40; + F_2 = 41; + Gb2 = 42; + G_2 = 43; + Ab2 = 44; + A_2 = 45; + Bb2 = 46; + B_2 = 47; + C_3 = 48; + Db3 = 49; + D_3 = 50; + Eb3 = 51; + E_3 = 52; + F_3 = 53; + Gb3 = 54; + G_3 = 55; + Ab3 = 56; + A_3 = 57; + Bb3 = 58; + B_3 = 59; + C_4 = 60; + Db4 = 61; + D_4 = 62; + Eb4 = 63; + E_4 = 64; + F_4 = 65; + Gb4 = 66; + G_4 = 67; + Ab4 = 68; + A_4 = 69; + Bb4 = 70; + B_4 = 71; + C_5 = 72; + Db5 = 73; + D_5 = 74; + Eb5 = 75; + E_5 = 76; + F_5 = 77; + Gb5 = 78; + G_5 = 79; + Ab5 = 80; + A_5 = 81; + Bb5 = 82; + B_5 = 83; + C_6 = 84; + Db6 = 85; + D_6 = 86; + Eb6 = 87; + E_6 = 88; + F_6 = 89; + Gb6 = 90; + G_6 = 91; + Ab6 = 92; + A_6 = 93; + Bb6 = 94; + B_6 = 95; + C_7 = 96; + Db7 = 97; + D_7 = 98; + Eb7 = 99; + E_7 = 100; + F_7 = 101; + Gb7 = 102; + G_7 = 103; + Ab7 = 104; + A_7 = 105; + Bb7 = 106; + B_7 = 107; + C_8 = 108; + }; + + Keys = { + Key_Space = 0x20; + Key_Any = 0x20; + Key_Exclam = 0x21; + Key_QuoteDbl = 0x22; + Key_NumberSign = 0x23; + Key_Dollar = 0x24; + Key_Percent = 0x25; + Key_Ampersand = 0x26; + Key_Apostrophe = 0x27; + Key_ParenLeft = 0x28; + Key_ParenRight = 0x29; + Key_Asterisk = 0x2a; + Key_Plus = 0x2b; + Key_Comma = 0x2c; + Key_Minus = 0x2d; + Key_Period = 0x2e; + Key_Slash = 0x2f; + Key_0 = 0x30; + Key_1 = 0x31; + Key_2 = 0x32; + Key_3 = 0x33; + Key_4 = 0x34; + Key_5 = 0x35; + Key_6 = 0x36; + Key_7 = 0x37; + Key_8 = 0x38; + Key_9 = 0x39; + Key_Colon = 0x3a; + Key_Semicolon = 0x3b; + Key_Less = 0x3c; + Key_Equal = 0x3d; + Key_Greater = 0x3e; + Key_Question = 0x3f; + Key_At = 0x40; + Key_A = 0x41; + Key_B = 0x42; + Key_C = 0x43; + Key_D = 0x44; + Key_E = 0x45; + Key_F = 0x46; + Key_G = 0x47; + Key_H = 0x48; + Key_I = 0x49; + Key_J = 0x4a; + Key_K = 0x4b; + Key_L = 0x4c; + Key_M = 0x4d; + Key_N = 0x4e; + Key_O = 0x4f; + Key_P = 0x50; + Key_Q = 0x51; + Key_R = 0x52; + Key_S = 0x53; + Key_T = 0x54; + Key_U = 0x55; + Key_V = 0x56; + Key_W = 0x57; + Key_X = 0x58; + Key_Y = 0x59; + Key_Z = 0x5a; + Key_BracketLeft = 0x5b; + Key_Backslash = 0x5c; + Key_BracketRight = 0x5d; + Key_AsciiCircum = 0x5e; + Key_Underscore = 0x5f; + Key_QuoteLeft = 0x60; + Key_BraceLeft = 0x7b; + Key_Bar = 0x7c; + Key_BraceRight = 0x7d; + Key_AsciiTilde = 0x7e; + Key_nobreakspace = 0x0a0; + Key_exclamdown = 0x0a1; + Key_cent = 0x0a2; + Key_sterling = 0x0a3; + Key_currency = 0x0a4; + Key_yen = 0x0a5; + Key_brokenbar = 0x0a6; + Key_section = 0x0a7; + Key_diaeresis = 0x0a8; + Key_copyright = 0x0a9; + Key_ordfeminine = 0x0aa; + Key_guillemotleft = 0x0ab; + Key_notsign = 0x0ac; + Key_hyphen = 0x0ad; + Key_registered = 0x0ae; + Key_macron = 0x0af; + Key_degree = 0x0b0; + Key_plusminus = 0x0b1; + Key_twosuperior = 0x0b2; + Key_threesuperior = 0x0b3; + Key_acute = 0x0b4; + Key_micro = 0x0b5; + Key_paragraph = 0x0b6; + Key_periodcentered = 0x0b7; + Key_cedilla = 0x0b8; + Key_onesuperior = 0x0b9; + Key_masculine = 0x0ba; + Key_guillemotright = 0x0bb; + Key_onequarter = 0x0bc; + Key_onehalf = 0x0bd; + Key_threequarters = 0x0be; + Key_questiondown = 0x0bf; + Key_Agrave = 0x0c0; + Key_Aacute = 0x0c1; + Key_Acircumflex = 0x0c2; + Key_Atilde = 0x0c3; + Key_Adiaeresis = 0x0c4; + Key_Aring = 0x0c5; + Key_AE = 0x0c6; + Key_Ccedilla = 0x0c7; + Key_Egrave = 0x0c8; + Key_Eacute = 0x0c9; + Key_Ecircumflex = 0x0ca; + Key_Ediaeresis = 0x0cb; + Key_Igrave = 0x0cc; + Key_Iacute = 0x0cd; + Key_Icircumflex = 0x0ce; + Key_Idiaeresis = 0x0cf; + Key_ETH = 0x0d0; + Key_Ntilde = 0x0d1; + Key_Ograve = 0x0d2; + Key_Oacute = 0x0d3; + Key_Ocircumflex = 0x0d4; + Key_Otilde = 0x0d5; + Key_Odiaeresis = 0x0d6; + Key_multiply = 0x0d7; + Key_Ooblique = 0x0d8; + Key_Ugrave = 0x0d9; + Key_Uacute = 0x0da; + Key_Ucircumflex = 0x0db; + Key_Udiaeresis = 0x0dc; + Key_Yacute = 0x0dd; + Key_THORN = 0x0de; + Key_ssharp = 0x0df; + Key_division = 0x0f7; + Key_ydiaeresis = 0x0ff; + Key_Escape = 0x01000000; + Key_Tab = 0x01000001; + Key_Backtab = 0x01000002; + Key_Backspace = 0x01000003; + Key_Return = 0x01000004; + Key_Enter = 0x01000005; + Key_Insert = 0x01000006; + Key_Delete = 0x01000007; + Key_Pause = 0x01000008; + Key_Print = 0x01000009; + Key_SysReq = 0x0100000a; + Key_Clear = 0x0100000b; + Key_Home = 0x01000010; + Key_End = 0x01000011; + Key_Left = 0x01000012; + Key_Up = 0x01000013; + Key_Right = 0x01000014; + Key_Down = 0x01000015; + Key_PageUp = 0x01000016; + Key_PageDown = 0x01000017; + Key_Shift = 0x01000020; + Key_Control = 0x01000021; + Key_Meta = 0x01000022; + Key_Alt = 0x01000023; + Key_CapsLock = 0x01000024; + Key_NumLock = 0x01000025; + Key_ScrollLock = 0x01000026; + Key_F1 = 0x01000030; + Key_F2 = 0x01000031; + Key_F3 = 0x01000032; + Key_F4 = 0x01000033; + Key_F5 = 0x01000034; + Key_F6 = 0x01000035; + Key_F7 = 0x01000036; + Key_F8 = 0x01000037; + Key_F9 = 0x01000038; + Key_F10 = 0x01000039; + Key_F11 = 0x0100003a; + Key_F12 = 0x0100003b; + Key_F13 = 0x0100003c; + Key_F14 = 0x0100003d; + Key_F15 = 0x0100003e; + Key_F16 = 0x0100003f; + Key_F17 = 0x01000040; + Key_F18 = 0x01000041; + Key_F19 = 0x01000042; + Key_F20 = 0x01000043; + Key_F21 = 0x01000044; + Key_F22 = 0x01000045; + Key_F23 = 0x01000046; + Key_F24 = 0x01000047; + Key_F25 = 0x01000048; + Key_F26 = 0x01000049; + Key_F27 = 0x0100004a; + Key_F28 = 0x0100004b; + Key_F29 = 0x0100004c; + Key_F30 = 0x0100004d; + Key_F31 = 0x0100004e; + Key_F32 = 0x0100004f; + Key_F33 = 0x01000050; + Key_F34 = 0x01000051; + Key_F35 = 0x01000052; + Key_Super_L = 0x01000053; + Key_Super_R = 0x01000054; + Key_Menu = 0x01000055; + Key_Hyper_L = 0x01000056; + Key_Hyper_R = 0x01000057; + Key_Help = 0x01000058; + Key_Direction_L = 0x01000059; + Key_Direction_R = 0x01000060; + }; + } +); diff --git a/src/ConfigService.cpp b/src/ConfigService.cpp index da4d2d5..f62fc58 100644 --- a/src/ConfigService.cpp +++ b/src/ConfigService.cpp @@ -1,7 +1,6 @@ #include "ConfigService.hpp" -#include #include ConfigService::ConfigService(const std::string& filePath) { @@ -30,51 +29,7 @@ bool ConfigService::loadFromFile(const std::string& filePath) { return false; } -bool ConfigService::getLoggerConfig(const std::string& id, LoggerConfig* loggerConfig) const { - try { - const libconfig::Setting& loggers = config_.lookup("Loggers"); - for (int index = 0; index < loggers.getLength(); ++index) { - const libconfig::Setting& loggerSetting = loggers[index]; - - std::string loggerId; - if (!loggerSetting.lookupValue("Id", loggerId) || loggerId != id) { - continue; - } - - return parseLoggerConfig(loggerSetting, loggerConfig); - } - } catch (const libconfig::SettingException& ex) { - std::cout << "libconfig setting exception: " << ex.what() << std::endl; - return false; - } - - return false; -} - const std::string& ConfigService::lastError() const { return lastError_; } -bool ConfigService::parseLoggerConfig(const libconfig::Setting& loggerSetting, LoggerConfig* loggerConfig) const { - - if (!loggerSetting.lookupValue("Id", loggerConfig->id)) { - return false; - } - - try { - const libconfig::Setting& flags = loggerSetting.lookup("FlagsEnabled"); - for (int index = 0; index < flags.getLength(); ++index) { - loggerConfig->flagsEnabled.push_back(static_cast(flags[index])); - } - } catch (const libconfig::SettingException&) { - loggerConfig->flagsEnabled.clear(); - } - - loggerSetting.lookupValue("ShowTime", loggerConfig->showTime); - loggerSetting.lookupValue("ShowSourceTrace", loggerConfig->showSourceTrace); - loggerSetting.lookupValue("CoutEnabled", loggerConfig->coutEnabled); - loggerSetting.lookupValue("FileEnabled", loggerConfig->fileEnabled); - loggerSetting.lookupValue("FilePath", loggerConfig->filePath); - - return true; -} \ No newline at end of file diff --git a/src/ConfigService.hpp b/src/ConfigService.hpp index c135da0..c0b9260 100644 --- a/src/ConfigService.hpp +++ b/src/ConfigService.hpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include struct LoggerConfig { std::string id; @@ -15,6 +17,30 @@ struct LoggerConfig { bool coutEnabled = false; bool fileEnabled = false; std::string filePath; + + bool parseConfig(const libconfig::Setting& setting) { + + if (!setting.lookupValue("Id", id)) { + return false; + } + + try { + const libconfig::Setting& flags = setting.lookup("FlagsEnabled"); + for (int index = 0; index < flags.getLength(); ++index) { + flagsEnabled.push_back(static_cast(flags[index])); + } + } catch (const libconfig::SettingException&) { + flagsEnabled.clear(); + } + + setting.lookupValue("ShowTime", showTime); + setting.lookupValue("ShowSourceTrace", showSourceTrace); + setting.lookupValue("CoutEnabled", coutEnabled); + setting.lookupValue("FileEnabled", fileEnabled); + setting.lookupValue("FilePath", filePath); + + return true; + } }; struct AudioConfig { @@ -27,6 +53,40 @@ struct AudioConfig { int32_t notesPerOctave; }; +struct KeymapConfig { + std::string id; + std::unordered_map keymap; + + bool parseConfig(const libconfig::Setting& setting) { + + if (!setting.lookupValue("Id", id)) { + return false; + } + + try { + const libconfig::Setting& keymapGroup = setting.lookup("Keymap"); + const libconfig::Setting& notesGroup = setting.lookup("Notes"); + const libconfig::Setting& keysGroup = setting.lookup("Keys"); + + for(size_t i = 0; i < keymapGroup.getLength(); i++) { + libconfig::Setting& item = keymapGroup[i]; + std::string key = item.getName(); + std::string note = ""; + if(item.getType() == libconfig::Setting::TypeString) note = std::string(item.c_str()); + + int8_t noteId = static_cast(notesGroup[note]) % INT8_MAX; + int32_t keyId = static_cast(keysGroup[key]) % INT8_MAX; + keymap.emplace(keyId, noteId); + } + + } catch (const libconfig::SettingException&) { + return false; + } + + return true; + } +}; + class ConfigService { public: @@ -36,11 +96,31 @@ public: bool loadFromFile(const std::string& filePath); - bool getLoggerConfig(const std::string& id, LoggerConfig* loggerConfig) const; + template + bool getConfig(const std::string& type, const std::string& id, T* config) const { + try { + const libconfig::Setting& configs = config_.lookup(type); + for (int index = 0; index < configs.getLength(); ++index) { + const libconfig::Setting& configSetting = configs[index]; + + std::string configId; + if (!configSetting.lookupValue("Id", configId) || configId != id) { + continue; + } + + return config->parseConfig(configSetting); + } + } catch (const libconfig::SettingException& ex) { + std::cout << "libconfig setting exception: " << ex.what() << std::endl; + return false; + } + + return false; + } + const std::string& lastError() const; private: - bool parseLoggerConfig(const libconfig::Setting& loggerSetting, LoggerConfig* loggerConfig) const; libconfig::Config config_; std::string lastError_; diff --git a/src/LoggerService.cpp b/src/LoggerService.cpp index c88d9e2..4217009 100644 --- a/src/LoggerService.cpp +++ b/src/LoggerService.cpp @@ -12,7 +12,7 @@ namespace fs = std::filesystem; LoggerService::LoggerService(ConfigService* config, const std::string& loggerId) { - if(!(config->getLoggerConfig(loggerId, &configuration_))) { + if(!(config->getConfig("Logger", loggerId, &configuration_))) { std::cout << "Failed to get logger configuration fom config service" << std::endl; return; } diff --git a/src/main.cpp b/src/main.cpp index fc9f0bc..873cf58 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,6 +9,7 @@ #include "LoggerService.hpp" #include "ConfigService.hpp" #include "synth/AudioEngine.hpp" +#include "synth/KeyboardController.hpp" int main(int argc, char* argv[]) { @@ -33,6 +34,8 @@ int main(int argc, char* argv[]) { // create app objects ConfigService config = ConfigService("config/sonobulus.cfg"); LoggerService logger = LoggerService(&config, "Engine"); + NoteQueue queue = NoteQueue(); + KeyboardController keyboard = KeyboardController(&config, &logger, &queue); // audio synthesizer doohickey AudioEngine audioEngine = AudioEngine(&logger); diff --git a/src/synth/KeyboardController.cpp b/src/synth/KeyboardController.cpp index 687b521..1aef283 100644 --- a/src/synth/KeyboardController.cpp +++ b/src/synth/KeyboardController.cpp @@ -5,37 +5,14 @@ // #include #include -KeyboardController::KeyboardController(NoteQueue& queue, ConfigService* config) : queue_(queue), config_(config) { +KeyboardController::KeyboardController(ConfigService* config, LoggerService* logger, NoteQueue* queue) : config_(config), logger_(logger), queue_(queue) { - // load keymap from config file - std::string filepath = "config/keymap.yaml"; - filepath = std::filesystem::absolute(filepath).string(); - // YAML::Node file; - try { - // file = YAML::LoadFile(filepath); - } catch(const std::exception& e) { - std::cerr << e.what() << std::endl; + // load keymap from config service + if(!(config->getConfig("KeyboardController", "Main", &configuration_))) { + logger_->log("Keyboard", LogFlag::Error, "Failed to get logger configuration fom config service"); return; } - // YAML::Node keymapNode = file["keymap"]; // node for string to string mappings - // YAML::Node notesNode = file["notes"]; // string to midi int mappings - // YAML::Node keysNode = file["keys"]; // string to qt key id mappings - - // for each element in the keymap - // for (const auto& entry : keymapNode) { - - // std::string keyString = entry.first.as(); - // std::string noteString = entry.second.as(); - - // // match the strings to ints - // uint8_t noteValue = notesNode[noteString].as(); - // uint32_t keyValue = keysNode[keyString].as(); - - // // insert into map - // keymap_.emplace(keyValue, noteValue); - // } - } void KeyboardController::handleKeyPress(QKeyEvent* e) { @@ -44,7 +21,7 @@ void KeyboardController::handleKeyPress(QKeyEvent* e) { auto it = keymap_.find(e->key()); if (it == keymap_.end()) return; - queue_.push({ + queue_->push({ NoteEventType::NoteOn, it->second, 0.8f, @@ -58,7 +35,7 @@ void KeyboardController::handleKeyRelease(QKeyEvent* e) { auto it = keymap_.find(e->key()); if (it == keymap_.end()) return; - queue_.push({ + queue_->push({ NoteEventType::NoteOff, it->second, 0.8f, diff --git a/src/synth/KeyboardController.hpp b/src/synth/KeyboardController.hpp index 3103328..06e71f2 100644 --- a/src/synth/KeyboardController.hpp +++ b/src/synth/KeyboardController.hpp @@ -7,12 +7,13 @@ #include "NoteQueue.hpp" #include "ConfigService.hpp" +#include "LoggerService.hpp" // The keyboardcontroller handles user inputs from a keyboard and maps them to note events class KeyboardController { public: - explicit KeyboardController(NoteQueue& queue, ConfigService* config); + explicit KeyboardController(ConfigService* config, LoggerService* logger, NoteQueue* queue); ~KeyboardController() = default; void handleKeyPress(QKeyEvent* e); @@ -20,10 +21,13 @@ public: private: - NoteQueue& queue_; + NoteQueue* queue_; ConfigService* config_; + LoggerService* logger_; // keymap is key -> midi note id std::unordered_map keymap_; + KeymapConfig configuration_; + };