add config integration for keymap and logger

This commit is contained in:
2026-06-09 22:39:38 -05:00
parent 30b06e077c
commit 7231d948bc
7 changed files with 437 additions and 81 deletions

View File

@@ -1,5 +1,5 @@
Loggers = ( Logger = (
{ {
Id = "Engine"; Id = "Engine";
@@ -18,3 +18,340 @@ Loggers = (
FilePath = "Engine.log"; FilePath = "Engine.log";
} }
); );
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;
};
}
);

View File

@@ -1,7 +1,6 @@
#include "ConfigService.hpp" #include "ConfigService.hpp"
#include <iostream>
#include <exception> #include <exception>
ConfigService::ConfigService(const std::string& filePath) { ConfigService::ConfigService(const std::string& filePath) {
@@ -30,51 +29,7 @@ bool ConfigService::loadFromFile(const std::string& filePath) {
return false; 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 { const std::string& ConfigService::lastError() const {
return lastError_; 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<const char*>(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;
}

View File

@@ -6,6 +6,8 @@
#include <optional> #include <optional>
#include <string> #include <string>
#include <vector> #include <vector>
#include <iostream>
#include <unordered_map>
struct LoggerConfig { struct LoggerConfig {
std::string id; std::string id;
@@ -15,6 +17,30 @@ struct LoggerConfig {
bool coutEnabled = false; bool coutEnabled = false;
bool fileEnabled = false; bool fileEnabled = false;
std::string filePath; 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<const char*>(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 { struct AudioConfig {
@@ -27,6 +53,40 @@ struct AudioConfig {
int32_t notesPerOctave; int32_t notesPerOctave;
}; };
struct KeymapConfig {
std::string id;
std::unordered_map<int32_t, uint8_t> 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<int>(notesGroup[note]) % INT8_MAX;
int32_t keyId = static_cast<int>(keysGroup[key]) % INT8_MAX;
keymap.emplace(keyId, noteId);
}
} catch (const libconfig::SettingException&) {
return false;
}
return true;
}
};
class ConfigService { class ConfigService {
public: public:
@@ -36,11 +96,31 @@ public:
bool loadFromFile(const std::string& filePath); bool loadFromFile(const std::string& filePath);
bool getLoggerConfig(const std::string& id, LoggerConfig* loggerConfig) const; template<typename T>
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; const std::string& lastError() const;
private: private:
bool parseLoggerConfig(const libconfig::Setting& loggerSetting, LoggerConfig* loggerConfig) const;
libconfig::Config config_; libconfig::Config config_;
std::string lastError_; std::string lastError_;

View File

@@ -12,7 +12,7 @@ namespace fs = std::filesystem;
LoggerService::LoggerService(ConfigService* config, const std::string& loggerId) { LoggerService::LoggerService(ConfigService* config, const std::string& loggerId) {
if(!(config->getLoggerConfig(loggerId, &configuration_))) { if(!(config->getConfig<LoggerConfig>("Logger", loggerId, &configuration_))) {
std::cout << "Failed to get logger configuration fom config service" << std::endl; std::cout << "Failed to get logger configuration fom config service" << std::endl;
return; return;
} }

View File

@@ -9,6 +9,7 @@
#include "LoggerService.hpp" #include "LoggerService.hpp"
#include "ConfigService.hpp" #include "ConfigService.hpp"
#include "synth/AudioEngine.hpp" #include "synth/AudioEngine.hpp"
#include "synth/KeyboardController.hpp"
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
@@ -33,6 +34,8 @@ int main(int argc, char* argv[]) {
// create app objects // create app objects
ConfigService config = ConfigService("config/sonobulus.cfg"); ConfigService config = ConfigService("config/sonobulus.cfg");
LoggerService logger = LoggerService(&config, "Engine"); LoggerService logger = LoggerService(&config, "Engine");
NoteQueue queue = NoteQueue();
KeyboardController keyboard = KeyboardController(&config, &logger, &queue);
// audio synthesizer doohickey // audio synthesizer doohickey
AudioEngine audioEngine = AudioEngine(&logger); AudioEngine audioEngine = AudioEngine(&logger);

View File

@@ -5,37 +5,14 @@
// #include <yaml-cpp/yaml.h> // #include <yaml-cpp/yaml.h>
#include <filesystem> #include <filesystem>
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 // load keymap from config service
std::string filepath = "config/keymap.yaml"; if(!(config->getConfig<KeymapConfig>("KeyboardController", "Main", &configuration_))) {
filepath = std::filesystem::absolute(filepath).string(); logger_->log("Keyboard", LogFlag::Error, "Failed to get logger configuration fom config service");
// YAML::Node file;
try {
// file = YAML::LoadFile(filepath);
} catch(const std::exception& e) {
std::cerr << e.what() << std::endl;
return; 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>();
// std::string noteString = entry.second.as<std::string>();
// // match the strings to ints
// uint8_t noteValue = notesNode[noteString].as<uint8_t>();
// uint32_t keyValue = keysNode[keyString].as<uint32_t>();
// // insert into map
// keymap_.emplace(keyValue, noteValue);
// }
} }
void KeyboardController::handleKeyPress(QKeyEvent* e) { void KeyboardController::handleKeyPress(QKeyEvent* e) {
@@ -44,7 +21,7 @@ void KeyboardController::handleKeyPress(QKeyEvent* e) {
auto it = keymap_.find(e->key()); auto it = keymap_.find(e->key());
if (it == keymap_.end()) return; if (it == keymap_.end()) return;
queue_.push({ queue_->push({
NoteEventType::NoteOn, NoteEventType::NoteOn,
it->second, it->second,
0.8f, 0.8f,
@@ -58,7 +35,7 @@ void KeyboardController::handleKeyRelease(QKeyEvent* e) {
auto it = keymap_.find(e->key()); auto it = keymap_.find(e->key());
if (it == keymap_.end()) return; if (it == keymap_.end()) return;
queue_.push({ queue_->push({
NoteEventType::NoteOff, NoteEventType::NoteOff,
it->second, it->second,
0.8f, 0.8f,

View File

@@ -7,12 +7,13 @@
#include "NoteQueue.hpp" #include "NoteQueue.hpp"
#include "ConfigService.hpp" #include "ConfigService.hpp"
#include "LoggerService.hpp"
// The keyboardcontroller handles user inputs from a keyboard and maps them to note events // The keyboardcontroller handles user inputs from a keyboard and maps them to note events
class KeyboardController { class KeyboardController {
public: public:
explicit KeyboardController(NoteQueue& queue, ConfigService* config); explicit KeyboardController(ConfigService* config, LoggerService* logger, NoteQueue* queue);
~KeyboardController() = default; ~KeyboardController() = default;
void handleKeyPress(QKeyEvent* e); void handleKeyPress(QKeyEvent* e);
@@ -20,10 +21,13 @@ public:
private: private:
NoteQueue& queue_; NoteQueue* queue_;
ConfigService* config_; ConfigService* config_;
LoggerService* logger_;
// keymap is key -> midi note id // keymap is key -> midi note id
std::unordered_map<int32_t, uint8_t> keymap_; std::unordered_map<int32_t, uint8_t> keymap_;
KeymapConfig configuration_;
}; };