Browse Source

Add template preset for modules, which are loaded when created from the Module Browser.

tags/v2.0.0
Andrew Belt 5 years ago
parent
commit
8423ce87aa
7 changed files with 141 additions and 50 deletions
  1. +4
    -1
      include/app/ModuleWidget.hpp
  2. +3
    -0
      include/plugin/Model.hpp
  3. +4
    -0
      include/system.hpp
  4. +5
    -1
      src/app/ModuleBrowser.cpp
  5. +93
    -48
      src/app/ModuleWidget.cpp
  6. +12
    -0
      src/plugin/Model.cpp
  7. +20
    -0
      src/system.cpp

+ 4
- 1
include/app/ModuleWidget.hpp View File

@@ -66,9 +66,12 @@ struct ModuleWidget : widget::OpaqueWidget {
void fromJson(json_t* rootJ); void fromJson(json_t* rootJ);
void copyClipboard(); void copyClipboard();
void pasteClipboardAction(); void pasteClipboardAction();
void load(std::string filename);
void loadAction(std::string filename); void loadAction(std::string filename);
void save(std::string filename);
void loadTemplate();
void loadDialog(); void loadDialog();
void save(std::string filename);
void saveTemplate();
void saveDialog(); void saveDialog();


/** Disconnects cables from all ports /** Disconnects cables from all ports


+ 3
- 0
include/plugin/Model.hpp View File

@@ -53,7 +53,10 @@ struct Model {
} }


void fromJson(json_t* rootJ); void fromJson(json_t* rootJ);
/** Returns the branded name of the model, e.g. VCV VCO-1. */
std::string getFullName(); std::string getFullName();
std::string getFactoryPresetDir();
std::string getUserPresetDir();
}; };






+ 4
- 0
include/system.hpp View File

@@ -26,10 +26,14 @@ void copyFile(const std::string& srcPath, const std::string& destPath);
The parent directory must exist. The parent directory must exist.
*/ */
void createDirectory(const std::string& path); void createDirectory(const std::string& path);
/** Creates all directories up to the path.
*/
void createDirectories(const std::string& path);
/** Deletes a directory. /** Deletes a directory.
The directory must be empty. Fails silently. The directory must be empty. Fails silently.
*/ */
void removeDirectory(const std::string& path); void removeDirectory(const std::string& path);
void removeDirectories(const std::string& path);
/** Returns the number of logical simultaneous multithreading (SMT) (e.g. Intel Hyperthreaded) threads on the CPU. */ /** Returns the number of logical simultaneous multithreading (SMT) (e.g. Intel Hyperthreaded) threads on the CPU. */
int getLogicalCoreCount(); int getLogicalCoreCount();
/** Sets a name of the current thread for debuggers and OS-specific process viewers. */ /** Sets a name of the current thread for debuggers and OS-specific process viewers. */


+ 5
- 1
src/app/ModuleBrowser.cpp View File

@@ -90,9 +90,13 @@ static ModuleWidget* chooseModel(plugin::Model* model) {
ModuleWidget* moduleWidget = model->createModuleWidget(module); ModuleWidget* moduleWidget = model->createModuleWidget(module);
APP->scene->rack->addModuleAtMouse(moduleWidget); APP->scene->rack->addModuleAtMouse(moduleWidget);


// Push ModuleAdd history action
// Load template preset
moduleWidget->loadTemplate();

// history::ModuleAdd
history::ModuleAdd* h = new history::ModuleAdd; history::ModuleAdd* h = new history::ModuleAdd;
h->name = "create module"; h->name = "create module";
// This serializes the module so redoing returns to the current state.
h->setModule(moduleWidget); h->setModule(moduleWidget);
APP->history->push(h); APP->history->push(h);




+ 93
- 48
src/app/ModuleWidget.cpp View File

@@ -170,6 +170,14 @@ struct ModuleSaveItem : ui::MenuItem {
}; };




struct ModuleSaveTemplateItem : ui::MenuItem {
ModuleWidget* moduleWidget;
void onAction(const event::Action& e) override {
moduleWidget->saveTemplate();
}
};


struct ModuleLoadItem : ui::MenuItem { struct ModuleLoadItem : ui::MenuItem {
ModuleWidget* moduleWidget; ModuleWidget* moduleWidget;
void onAction(const event::Action& e) override { void onAction(const event::Action& e) override {
@@ -182,7 +190,12 @@ struct ModulePresetPathItem : ui::MenuItem {
ModuleWidget* moduleWidget; ModuleWidget* moduleWidget;
std::string presetPath; std::string presetPath;
void onAction(const event::Action& e) override { void onAction(const event::Action& e) override {
moduleWidget->loadAction(presetPath);
try {
moduleWidget->loadAction(presetPath);
}
catch (Exception& e) {
osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK, e.what());
}
} }
}; };


@@ -214,6 +227,11 @@ struct ModulePresetItem : ui::MenuItem {
saveItem->moduleWidget = moduleWidget; saveItem->moduleWidget = moduleWidget;
menu->addChild(saveItem); menu->addChild(saveItem);


ModuleSaveTemplateItem* saveTemplateItem = new ModuleSaveTemplateItem;
saveTemplateItem->text = "Save template";
saveTemplateItem->moduleWidget = moduleWidget;
menu->addChild(saveTemplateItem);

// Create ModulePresetPathItems for each patch in a directory. // Create ModulePresetPathItems for each patch in a directory.
auto createPresetItems = [&](std::string presetDir) { auto createPresetItems = [&](std::string presetDir) {
bool hasPresets = false; bool hasPresets = false;
@@ -238,12 +256,12 @@ struct ModulePresetItem : ui::MenuItem {
// Scan `<user dir>/presets/<plugin slug>/<module slug>` for presets. // Scan `<user dir>/presets/<plugin slug>/<module slug>` for presets.
menu->addChild(new ui::MenuSeparator); menu->addChild(new ui::MenuSeparator);
menu->addChild(createMenuLabel("User presets")); menu->addChild(createMenuLabel("User presets"));
createPresetItems(asset::user("presets/" + moduleWidget->model->plugin->slug + "/" + moduleWidget->model->slug));
createPresetItems(moduleWidget->model->getUserPresetDir());


// Scan `<plugin dir>/presets/<module slug>` for presets. // Scan `<plugin dir>/presets/<module slug>` for presets.
menu->addChild(new ui::MenuSeparator); menu->addChild(new ui::MenuSeparator);
menu->addChild(createMenuLabel("Factory presets")); menu->addChild(createMenuLabel("Factory presets"));
createPresetItems(asset::plugin(moduleWidget->model->plugin, "presets/" + moduleWidget->model->slug));
createPresetItems(moduleWidget->model->getFactoryPresetDir());


return menu; return menu;
} }
@@ -599,41 +617,87 @@ void ModuleWidget::pasteClipboardAction() {
APP->history->push(h); APP->history->push(h);
} }


void ModuleWidget::loadAction(std::string filename) {
INFO("Loading preset %s", filename.c_str());

FILE* file = fopen(filename.c_str(), "r");
if (!file) {
WARN("Could not load patch file %s", filename.c_str());
return;
}
void ModuleWidget::load(std::string filename) {
FILE* file = std::fopen(filename.c_str(), "r");
if (!file)
throw Exception(string::f("Could not load patch file %s", filename.c_str()));
DEFER({ DEFER({
fclose(file);
std::fclose(file);
}); });


INFO("Loading preset %s", filename.c_str());

json_error_t error; json_error_t error;
json_t* moduleJ = json_loadf(file, 0, &error); json_t* moduleJ = json_loadf(file, 0, &error);
if (!moduleJ) {
std::string message = string::f("File is not a valid patch file. JSON parsing error at %s %d:%d %s", error.source, error.line, error.column, error.text);
osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK, message.c_str());
return;
}
if (!moduleJ)
throw Exception(string::f("File is not a valid patch file. JSON parsing error at %s %d:%d %s", error.source, error.line, error.column, error.text));
DEFER({ DEFER({
json_decref(moduleJ); json_decref(moduleJ);
}); });


fromJson(moduleJ);
}

void ModuleWidget::loadAction(std::string filename) {
// history::ModuleChange // history::ModuleChange
history::ModuleChange* h = new history::ModuleChange; history::ModuleChange* h = new history::ModuleChange;
h->name = "load module preset"; h->name = "load module preset";
h->moduleId = module->id; h->moduleId = module->id;
h->oldModuleJ = toJson(); h->oldModuleJ = toJson();


fromJson(moduleJ);
try {
load(filename);
}
catch (Exception& e) {
delete h;
throw;
}


h->newModuleJ = toJson(); h->newModuleJ = toJson();
APP->history->push(h); APP->history->push(h);
} }


void ModuleWidget::loadTemplate() {
std::string templatePath = model->getUserPresetDir() + "/" + "template.vcvm";
try {
load(templatePath);
}
catch (Exception& e) {
// Do nothing
}
}

void ModuleWidget::loadDialog() {
std::string presetDir = model->getUserPresetDir();
system::createDirectories(presetDir);

// Delete directories if empty
DEFER({
system::removeDirectories(presetDir);
});

osdialog_filters* filters = osdialog_filters_parse(PRESET_FILTERS);
DEFER({
osdialog_filters_free(filters);
});

char* path = osdialog_file(OSDIALOG_OPEN, presetDir.c_str(), NULL, filters);
if (!path) {
// No path selected
return;
}
DEFER({
free(path);
});

try {
loadAction(path);
}
catch (Exception& e) {
osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK, e.what());
}
}

void ModuleWidget::save(std::string filename) { void ModuleWidget::save(std::string filename) {
INFO("Saving preset %s", filename.c_str()); INFO("Saving preset %s", filename.c_str());


@@ -654,40 +718,21 @@ void ModuleWidget::save(std::string filename) {
json_dumpf(moduleJ, file, JSON_INDENT(2) | JSON_REAL_PRECISION(9)); json_dumpf(moduleJ, file, JSON_INDENT(2) | JSON_REAL_PRECISION(9));
} }


void ModuleWidget::loadDialog() {
std::string presetDir = asset::user("presets");
std::string pluginPresetDir = presetDir + "/" + model->plugin->slug;
std::string modulePresetDir = pluginPresetDir + "/" + model->slug;
system::createDirectory(modulePresetDir);
void ModuleWidget::saveTemplate() {
std::string presetDir = model->getUserPresetDir();
system::createDirectories(presetDir);


osdialog_filters* filters = osdialog_filters_parse(PRESET_FILTERS);
DEFER({
osdialog_filters_free(filters);
});

char* path = osdialog_file(OSDIALOG_OPEN, modulePresetDir.c_str(), NULL, filters);
if (!path) {
// No path selected
return;
}
DEFER({
free(path);
});

loadAction(path);
std::string templatePath = presetDir + "/" + "template.vcvm";
save(templatePath);
} }


void ModuleWidget::saveDialog() { void ModuleWidget::saveDialog() {
std::string presetDir = asset::user("presets");
system::createDirectory(presetDir);
std::string pluginPresetDir = presetDir + "/" + model->plugin->slug;
system::createDirectory(pluginPresetDir);
std::string modulePresetDir = pluginPresetDir + "/" + model->slug;
system::createDirectory(modulePresetDir);
// Delete directory if empty
std::string presetDir = model->getUserPresetDir();
system::createDirectories(presetDir);

// Delete directories if empty
DEFER({ DEFER({
system::removeDirectory(modulePresetDir);
system::removeDirectory(pluginPresetDir);
system::removeDirectories(presetDir);
}); });


osdialog_filters* filters = osdialog_filters_parse(PRESET_FILTERS); osdialog_filters* filters = osdialog_filters_parse(PRESET_FILTERS);
@@ -695,7 +740,7 @@ void ModuleWidget::saveDialog() {
osdialog_filters_free(filters); osdialog_filters_free(filters);
}); });


char* path = osdialog_file(OSDIALOG_SAVE, modulePresetDir.c_str(), "Untitled.vcvm", filters);
char* path = osdialog_file(OSDIALOG_SAVE, presetDir.c_str(), "Untitled.vcvm", filters);
if (!path) { if (!path) {
// No path selected // No path selected
return; return;


+ 12
- 0
src/plugin/Model.cpp View File

@@ -50,5 +50,17 @@ std::string Model::getFullName() {
} }




std::string Model::getFactoryPresetDir() {
return asset::plugin(plugin, "presets/" + slug);
}


std::string Model::getUserPresetDir() {
return asset::user("presets/" + plugin->slug + "/" + slug);
}




} // namespace plugin } // namespace plugin
} // namespace rack } // namespace rack

+ 20
- 0
src/system.cpp View File

@@ -137,11 +137,31 @@ void createDirectory(const std::string& path) {
} }




void createDirectories(const std::string& path) {
for (size_t i = 1; i < path.size(); i++) {
char c = path[i];
if (c == '/' || c == '\\')
createDirectory(path.substr(0, i));
}
createDirectory(path);
}


void removeDirectory(const std::string& path) { void removeDirectory(const std::string& path) {
rmdir(path.c_str()); rmdir(path.c_str());
} }




void removeDirectories(const std::string& path) {
removeDirectory(path);
for (size_t i = path.size() - 1; i >= 1; i--) {
char c = path[i];
if (c == '/' || c == '\\')
removeDirectory(path.substr(0, i));
}
}


int getLogicalCoreCount() { int getLogicalCoreCount() {
return std::thread::hardware_concurrency(); return std::thread::hardware_concurrency();
} }


Loading…
Cancel
Save