From 2e32c991a497fc8cf357d6205b478a2c1ca729bb Mon Sep 17 00:00:00 2001 From: Michael Dewberry Date: Thu, 14 Sep 2023 00:34:35 -0400 Subject: [PATCH] Firmware switching menu reads eligible alt firmwares from disk --- src/common/core/FirmwareManager.cpp | 17 +++++++++++ src/common/core/FirmwareManager.hpp | 2 ++ src/common/core/LibAVR32ModuleWidget.cpp | 39 ++++++++++++++++-------- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/common/core/FirmwareManager.cpp b/src/common/core/FirmwareManager.cpp index 61cd2c1..7918ffc 100644 --- a/src/common/core/FirmwareManager.cpp +++ b/src/common/core/FirmwareManager.cpp @@ -6,6 +6,9 @@ #include #include #include +#include + +namespace fs = ghc::filesystem; extern rack::Plugin* pluginInstance; @@ -108,6 +111,14 @@ struct FirmwareManagerImpl std::string librarySource; librarySource = rack::asset::plugin(pluginInstance, "res/firmware/" + firmwareName + LIB_EXTENSION); + + std::error_code ec; + if (!fs::is_regular_file(fs::status(librarySource, ec))) + { + WARN("Requested firmware not found or invalid"); + return false; + } + std::string libraryToLoad = librarySource; // If we have already loaded this firmware at least once, create a temp copy so it will have its own address space @@ -230,12 +241,18 @@ FirmwareManager::~FirmwareManager() delete impl; } +const std::string FirmwareManager::getLibExtension() +{ + return LIB_EXTENSION; +} + bool FirmwareManager::load(std::string firmwareName) { delete impl; impl = new FirmwareManagerImpl(); if (!impl->load(firmwareName)) { + delete impl; impl = nullptr; WARN("Could not load firmware %s", firmwareName.c_str()); return false; diff --git a/src/common/core/FirmwareManager.hpp b/src/common/core/FirmwareManager.hpp index cc84dc1..d6401f0 100644 --- a/src/common/core/FirmwareManager.hpp +++ b/src/common/core/FirmwareManager.hpp @@ -16,6 +16,8 @@ struct FirmwareManager FirmwareManager(); ~FirmwareManager(); + const std::string getLibExtension(); + bool load(std::string firmwareName); void unload(); diff --git a/src/common/core/LibAVR32ModuleWidget.cpp b/src/common/core/LibAVR32ModuleWidget.cpp index d04059e..4da621c 100644 --- a/src/common/core/LibAVR32ModuleWidget.cpp +++ b/src/common/core/LibAVR32ModuleWidget.cpp @@ -5,6 +5,10 @@ #include "SerialOscInterface.hpp" #include "Screenshot.hpp" +#include + +namespace fs = ghc::filesystem; + using namespace rack; struct ConnectGridItem : rack::ui::MenuItem @@ -37,15 +41,27 @@ struct SwitchFirmwareItem : rack::ui::MenuItem ui::Menu* createChildMenu() override { - ui::Menu* menu = new ui::Menu; + // duplicate filenames that may be left in res folder by prior versions + std::vector ignoreList = {"teletype", "ansible 2", "earthsea 2", "meadowphysics 2", "teletype 2", "whitewhale 2"}; + std::vector fwNames = {}; - // TODO: populate this from looking in the firmware folder for binaries starting with the module basename - std::string tt_names[] = { "teletype4", "teletype5" }; - std::string ww_names[] = { "whitewhale", "whitewhale-kria" }; + const fs::path fwPath{rack::asset::plugin(pluginInstance, "res/firmware")}; + for (auto const& file : fs::directory_iterator{fwPath}) + { + auto name = file.path().stem().string(); + auto extension = file.path().extension().string(); + if (extension == module->firmware.getLibExtension() && + name.substr(0, module->firmwarePrefix.size()) == module->firmwarePrefix && + std::find(std::begin(ignoreList), std::end(ignoreList), name) == std::end(ignoreList)) + { + fwNames.push_back(name); + } + } - for (int i = 0; i < 2; i++) + ui::Menu* menu = new ui::Menu; + + for (auto const& name : fwNames) { - std::string name = module->firmwarePrefix == "teletype" ? tt_names[i] : ww_names[i]; menu->addChild(createCheckMenuItem( name, "", @@ -120,13 +136,10 @@ struct FirmwareSubmenuItem : MenuItem menu->addChild(new MenuSeparator()); - // TODO: enable for other modules - if (m->firmwarePrefix == "teletype" || m->firmwarePrefix == "whitewhale") { - menu->addChild(construct( - &MenuItem::text, "Switch Firmware", &MenuItem::rightText, RIGHT_ARROW, - &SwitchFirmwareItem::module, m - )); - } + menu->addChild(construct( + &MenuItem::text, "Switch Firmware", &MenuItem::rightText, RIGHT_ARROW, + &SwitchFirmwareItem::module, m + )); auto reloadItem = new ReloadFirmwareItem(); reloadItem->text = "Reload & Restart";