From e5a88dfad26c275fba576f311f20390530b38c3d Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Sun, 17 Feb 2019 07:09:19 -0500 Subject: [PATCH] Add factory preset submenu to module context menu. --- include/plugin/Model.hpp | 3 +- src/app/ModuleWidget.cpp | 99 +++++++++++++++++++++------------------- src/app/ParamWidget.cpp | 18 +++----- src/plugin.cpp | 31 ++++++++----- src/plugin/Model.cpp | 2 +- src/string.cpp | 2 + src/system.cpp | 2 + 7 files changed, 85 insertions(+), 72 deletions(-) diff --git a/include/plugin/Model.hpp b/include/plugin/Model.hpp index 296de8d1..32fa4422 100644 --- a/include/plugin/Model.hpp +++ b/include/plugin/Model.hpp @@ -23,6 +23,7 @@ namespace plugin { struct Model { Plugin *plugin = NULL; + std::vector presetPaths; /** Must be unique. Used for saving patches. Never change this. The model slug must be unique within your plugin, but it doesn't need to be unique among different plugins. @@ -31,7 +32,7 @@ struct Model { /** Human readable name for your model, e.g. "Voltage Controlled Oscillator" */ std::string name; /** List of tags representing the function(s) of the module */ - std::set tags; + std::vector tags; /** A one-line summary of the module's purpose */ std::string description; diff --git a/src/app/ModuleWidget.cpp b/src/app/ModuleWidget.cpp index 5a19fe57..7be3250a 100644 --- a/src/app/ModuleWidget.cpp +++ b/src/app/ModuleWidget.cpp @@ -31,9 +31,6 @@ struct ModuleUrlItem : ui::MenuItem { struct ModulePluginItem : ui::MenuItem { plugin::Plugin *plugin; - ModulePluginItem() { - disabled = true; - } ui::Menu *createChildMenu() override { ui::Menu *menu = new ui::Menu; @@ -97,10 +94,6 @@ struct ModulePluginItem : ui::MenuItem { struct ModuleDisconnectItem : ui::MenuItem { ModuleWidget *moduleWidget; - ModuleDisconnectItem() { - text = "Disconnect cables"; - rightText = WINDOW_MOD_CTRL_NAME "+U"; - } void onAction(const event::Action &e) override { moduleWidget->disconnectAction(); } @@ -108,10 +101,6 @@ struct ModuleDisconnectItem : ui::MenuItem { struct ModuleResetItem : ui::MenuItem { ModuleWidget *moduleWidget; - ModuleResetItem() { - text = "Initialize"; - rightText = WINDOW_MOD_CTRL_NAME "+I"; - } void onAction(const event::Action &e) override { moduleWidget->resetAction(); } @@ -119,10 +108,6 @@ struct ModuleResetItem : ui::MenuItem { struct ModuleRandomizeItem : ui::MenuItem { ModuleWidget *moduleWidget; - ModuleRandomizeItem() { - text = "Randomize"; - rightText = WINDOW_MOD_CTRL_NAME "+R"; - } void onAction(const event::Action &e) override { moduleWidget->randomizeAction(); } @@ -130,10 +115,6 @@ struct ModuleRandomizeItem : ui::MenuItem { struct ModuleCopyItem : ui::MenuItem { ModuleWidget *moduleWidget; - ModuleCopyItem() { - text = "Copy preset"; - rightText = WINDOW_MOD_CTRL_NAME "+C"; - } void onAction(const event::Action &e) override { moduleWidget->copyClipboard(); } @@ -141,10 +122,6 @@ struct ModuleCopyItem : ui::MenuItem { struct ModulePasteItem : ui::MenuItem { ModuleWidget *moduleWidget; - ModulePasteItem() { - text = "Paste preset"; - rightText = WINDOW_MOD_CTRL_NAME "+V"; - } void onAction(const event::Action &e) override { moduleWidget->pasteClipboardAction(); } @@ -152,9 +129,6 @@ struct ModulePasteItem : ui::MenuItem { struct ModuleSaveItem : ui::MenuItem { ModuleWidget *moduleWidget; - ModuleSaveItem() { - text = "Save preset as"; - } void onAction(const event::Action &e) override { moduleWidget->saveDialog(); } @@ -162,20 +136,39 @@ struct ModuleSaveItem : ui::MenuItem { struct ModuleLoadItem : ui::MenuItem { ModuleWidget *moduleWidget; - ModuleLoadItem() { - text = "Load preset"; - } void onAction(const event::Action &e) override { moduleWidget->loadDialog(); } }; -struct ModuleCloneItem : ui::MenuItem { +struct ModulePresetItem : ui::MenuItem { + ModuleWidget *moduleWidget; + std::string presetPath; + void onAction(const event::Action &e) override { + moduleWidget->loadAction(presetPath); + } +}; + +struct ModuleListPresetsItem : ui::MenuItem { ModuleWidget *moduleWidget; - ModuleCloneItem() { - text = "Duplicate"; - rightText = WINDOW_MOD_CTRL_NAME "+D"; + ui::Menu *createChildMenu() override { + ui::Menu *menu = new ui::Menu; + + for (const std::string &presetPath : moduleWidget->model->presetPaths) { + ModulePresetItem *presetItem = new ModulePresetItem; + std::string presetName = string::basename(string::filename(presetPath)); + presetItem->text = presetName; + presetItem->presetPath = presetPath; + presetItem->moduleWidget = moduleWidget; + menu->addChild(presetItem); + } + + return menu; } +}; + +struct ModuleCloneItem : ui::MenuItem { + ModuleWidget *moduleWidget; void onAction(const event::Action &e) override { moduleWidget->cloneAction(); } @@ -183,15 +176,6 @@ struct ModuleCloneItem : ui::MenuItem { struct ModuleBypassItem : ui::MenuItem { ModuleWidget *moduleWidget; - ModuleBypassItem() { - text = "Disable"; - } - void setModule(ModuleWidget *moduleWidget) { - this->moduleWidget = moduleWidget; - rightText = WINDOW_MOD_CTRL_NAME "+E"; - if (moduleWidget->module && moduleWidget->module->bypass) - rightText = CHECKMARK_STRING " " + rightText; - } void onAction(const event::Action &e) override { moduleWidget->bypassAction(); } @@ -199,10 +183,6 @@ struct ModuleBypassItem : ui::MenuItem { struct ModuleDeleteItem : ui::MenuItem { ModuleWidget *moduleWidget; - ModuleDeleteItem() { - text = "Delete"; - rightText = "Backspace/Delete"; - } void onAction(const event::Action &e) override { moduleWidget->removeAction(); } @@ -766,42 +746,67 @@ void ModuleWidget::createContextMenu() { menu->addChild(pluginItem); ModuleResetItem *resetItem = new ModuleResetItem; + resetItem->text = "Initialize"; + resetItem->rightText = WINDOW_MOD_CTRL_NAME "+I"; resetItem->moduleWidget = this; menu->addChild(resetItem); ModuleRandomizeItem *randomizeItem = new ModuleRandomizeItem; + randomizeItem->text = "Randomize"; + randomizeItem->rightText = WINDOW_MOD_CTRL_NAME "+R"; randomizeItem->moduleWidget = this; menu->addChild(randomizeItem); ModuleDisconnectItem *disconnectItem = new ModuleDisconnectItem; + disconnectItem->text = "Disconnect cables"; + disconnectItem->rightText = WINDOW_MOD_CTRL_NAME "+U"; disconnectItem->moduleWidget = this; menu->addChild(disconnectItem); ModuleCloneItem *cloneItem = new ModuleCloneItem; + cloneItem->text = "Duplicate"; + cloneItem->rightText = WINDOW_MOD_CTRL_NAME "+D"; cloneItem->moduleWidget = this; menu->addChild(cloneItem); ModuleCopyItem *copyItem = new ModuleCopyItem; + copyItem->text = "Copy preset"; + copyItem->rightText = WINDOW_MOD_CTRL_NAME "+C"; copyItem->moduleWidget = this; menu->addChild(copyItem); ModulePasteItem *pasteItem = new ModulePasteItem; + pasteItem->text = "Paste preset"; + pasteItem->rightText = WINDOW_MOD_CTRL_NAME "+V"; pasteItem->moduleWidget = this; menu->addChild(pasteItem); ModuleLoadItem *loadItem = new ModuleLoadItem; + loadItem->text = "Open preset"; loadItem->moduleWidget = this; menu->addChild(loadItem); ModuleSaveItem *saveItem = new ModuleSaveItem; + saveItem->text = "Save preset as"; saveItem->moduleWidget = this; menu->addChild(saveItem); + ModuleListPresetsItem *presetsItem = new ModuleListPresetsItem; + presetsItem->text = "Factory presets"; + presetsItem->moduleWidget = this; + menu->addChild(presetsItem); + ModuleBypassItem *bypassItem = new ModuleBypassItem; - bypassItem->setModule(this); + bypassItem->text = "Disable"; + bypassItem->rightText = WINDOW_MOD_CTRL_NAME "+E"; + if (module && module->bypass) + bypassItem->rightText = CHECKMARK_STRING " " + bypassItem->rightText; + bypassItem->moduleWidget = this; menu->addChild(bypassItem); ModuleDeleteItem *deleteItem = new ModuleDeleteItem; + deleteItem->text = "Delete"; + deleteItem->rightText = "Backspace/Delete"; deleteItem->moduleWidget = this; menu->addChild(deleteItem); diff --git a/src/app/ParamWidget.cpp b/src/app/ParamWidget.cpp index 58bbc57c..a6546919 100644 --- a/src/app/ParamWidget.cpp +++ b/src/app/ParamWidget.cpp @@ -89,10 +89,6 @@ struct ParamLabel : ui::MenuLabel { struct ParamResetItem : ui::MenuItem { ParamWidget *paramWidget; - ParamResetItem() { - text = "Initialize"; - rightText = "Double-click"; - } void onAction(const event::Action &e) override { paramWidget->resetAction(); } @@ -100,19 +96,11 @@ struct ParamResetItem : ui::MenuItem { struct ParamFineItem : ui::MenuItem { - ParamFineItem() { - text = "Fine adjust"; - rightText = WINDOW_MOD_CTRL_NAME "+drag"; - disabled = true; - } }; struct ParamUnmapItem : ui::MenuItem { ParamWidget *paramWidget; - ParamUnmapItem() { - text = "Unmap"; - } void onAction(const event::Action &e) override { engine::ParamHandle *paramHandle = APP->engine->getParamHandle(paramWidget->paramQuantity->module, paramWidget->paramQuantity->paramId); if (paramHandle) { @@ -231,15 +219,21 @@ void ParamWidget::createContextMenu() { menu->addChild(paramField); ParamResetItem *resetItem = new ParamResetItem; + resetItem->text = "Initialize"; + resetItem->rightText = "Double-click"; resetItem->paramWidget = this; menu->addChild(resetItem); // ParamFineItem *fineItem = new ParamFineItem; + // fineItem->text = "Fine adjust"; + // fineItem->rightText = WINDOW_MOD_CTRL_NAME "+drag"; + // fineItem->disabled = true; // menu->addChild(fineItem); engine::ParamHandle *paramHandle = paramQuantity ? APP->engine->getParamHandle(paramQuantity->module, paramQuantity->paramId) : NULL; if (paramHandle) { ParamUnmapItem *unmapItem = new ParamUnmapItem; + unmapItem->text = "Unmap"; unmapItem->paramWidget = this; menu->addChild(unmapItem); } diff --git a/src/plugin.cpp b/src/plugin.cpp index 13d970d2..1035bec8 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -116,17 +116,6 @@ static bool loadPlugin(std::string path) { initCallback(plugin); plugin->fromJson(rootJ); - // Normalize tags - for (Model *model : plugin->models) { - std::set normalizedTags; - for (const std::string &tag : model->tags) { - std::string normalizedTag = normalizeTag(tag); - if (!normalizedTag.empty()) - normalizedTags.insert(normalizedTag); - } - model->tags = normalizedTags; - } - // Check slug if (!isSlugValid(plugin->slug)) { WARN("Plugin slug \"%s\" is invalid", plugin->slug.c_str()); @@ -146,6 +135,26 @@ static bool loadPlugin(std::string path) { plugins.push_back(plugin); INFO("Loaded plugin %s v%s from %s", plugin->slug.c_str(), plugin->version.c_str(), libraryFilename.c_str()); + // Normalize tags + for (Model *model : plugin->models) { + std::vector normalizedTags; + for (const std::string &tag : model->tags) { + std::string normalizedTag = normalizeTag(tag); + if (!normalizedTag.empty()) + normalizedTags.push_back(normalizedTag); + } + model->tags = normalizedTags; + } + + // Search for presets + for (Model *model : plugin->models) { + std::string presetDir = asset::plugin(plugin, "presets/" + model->slug); + for (const std::string &presetPath : system::listEntries(presetDir)) { + DEBUG("%s", presetPath.c_str()); + model->presetPaths.push_back(presetPath); + } + } + return true; } diff --git a/src/plugin/Model.cpp b/src/plugin/Model.cpp index 8542cc84..912987ee 100644 --- a/src/plugin/Model.cpp +++ b/src/plugin/Model.cpp @@ -20,7 +20,7 @@ void Model::fromJson(json_t *rootJ) { json_t *tagJ; json_array_foreach(tagsJ, i, tagJ) { std::string tag = json_string_value(tagJ); - tags.insert(tag); + tags.push_back(tag); } } } diff --git a/src/string.cpp b/src/string.cpp index 7622695d..eb1342a0 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -65,6 +65,8 @@ std::string filename(const std::string &path) { return filename; } +// libgen.h defines a `basename` macro +#undef basename std::string basename(const std::string &path) { size_t pos = path.rfind('.'); if (pos == std::string::npos) diff --git a/src/system.cpp b/src/system.cpp index 9b94f215..a2cd3742 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -1,5 +1,6 @@ #include "system.hpp" #include "string.hpp" + #include #include #include @@ -35,6 +36,7 @@ std::list listEntries(const std::string &path) { } closedir(dir); } + filenames.sort(); return filenames; }