diff --git a/include/helpers.hpp b/include/helpers.hpp index 9ad43050..fa6d8457 100644 --- a/include/helpers.hpp +++ b/include/helpers.hpp @@ -26,7 +26,7 @@ plugin::Model* createModel(const std::string& slug) { return m; } app::ModuleWidget* createModuleWidget(engine::Module* m) override { - TModule *tm = NULL; + TModule* tm = NULL; if (m) { assert(m->model == this); tm = dynamic_cast(m); diff --git a/src/app/ModuleWidget.cpp b/src/app/ModuleWidget.cpp index 4b915919..456785cd 100644 --- a/src/app/ModuleWidget.cpp +++ b/src/app/ModuleWidget.cpp @@ -611,8 +611,6 @@ PortWidget* ModuleWidget::getOutput(int portId) { json_t* ModuleWidget::toJson() { json_t* moduleJ = APP->engine->moduleToJson(module); - // When serializing ModuleWidget, don't include the ID. This ID is only meaningful when serializing the entire rack. - json_object_del(moduleJ, "id"); return moduleJ; } @@ -622,13 +620,9 @@ void ModuleWidget::fromJson(json_t* rootJ) { void ModuleWidget::copyClipboard() { json_t* moduleJ = toJson(); - DEFER({ - json_decref(moduleJ); - }); + DEFER({json_decref(moduleJ);}); char* moduleJson = json_dumps(moduleJ, JSON_INDENT(2) | JSON_REAL_PRECISION(9)); - DEFER({ - free(moduleJson); - }); + DEFER({std::free(moduleJson);}); glfwSetClipboardString(APP->window->win, moduleJson); } @@ -645,9 +639,12 @@ void ModuleWidget::pasteClipboardAction() { WARN("JSON parsing error at %s %d:%d %s", error.source, error.line, error.column, error.text); return; } - DEFER({ - json_decref(moduleJ); - }); + DEFER({json_decref(moduleJ);}); + + // Don't use IDs from JSON + json_object_del(moduleJ, "id"); + json_object_del(moduleJ, "leftModuleId"); + json_object_del(moduleJ, "rightModuleId"); // history::ModuleChange history::ModuleChange* h = new history::ModuleChange; @@ -665,9 +662,7 @@ 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({ - std::fclose(file); - }); + DEFER({std::fclose(file);}); INFO("Loading preset %s", filename.c_str()); @@ -675,9 +670,12 @@ void ModuleWidget::load(std::string filename) { json_t* moduleJ = json_loadf(file, 0, &error); 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({ - json_decref(moduleJ); - }); + DEFER({json_decref(moduleJ);}); + + // Don't use IDs from JSON + json_object_del(moduleJ, "id"); + json_object_del(moduleJ, "leftModuleId"); + json_object_del(moduleJ, "rightModuleId"); fromJson(moduleJ); } @@ -729,7 +727,7 @@ void ModuleWidget::loadDialog() { // No path selected return; } - DEFER({free(pathC);}); + DEFER({std::free(pathC);}); try { loadAction(pathC); @@ -744,17 +742,13 @@ void ModuleWidget::save(std::string filename) { json_t* moduleJ = toJson(); assert(moduleJ); - DEFER({ - json_decref(moduleJ); - }); + DEFER({json_decref(moduleJ);}); - FILE* file = fopen(filename.c_str(), "w"); + FILE* file = std::fopen(filename.c_str(), "w"); if (!file) { WARN("Could not write to patch file %s", filename.c_str()); } - DEFER({ - fclose(file); - }); + DEFER({std::fclose(file);}); json_dumpf(moduleJ, file, JSON_INDENT(2) | JSON_REAL_PRECISION(9)); } @@ -786,7 +780,7 @@ void ModuleWidget::saveDialog() { // No path selected return; } - DEFER({free(pathC);}); + DEFER({std::free(pathC);}); std::string path = pathC; if (system::getExtension(path) == "") @@ -872,15 +866,18 @@ void ModuleWidget::cloneAction() { // history::ComplexAction history::ComplexAction* h = new history::ComplexAction; - // Clone Module - engine::Module* clonedModule = model->createModule(); // JSON serialization is the obvious way to do this json_t* moduleJ = toJson(); + // Don't use IDs from JSON + json_object_del(moduleJ, "id"); + json_object_del(moduleJ, "leftModuleId"); + json_object_del(moduleJ, "rightModuleId"); + + // Clone Module + engine::Module* clonedModule = model->createModule(); // This doesn't need a lock (via Engine::moduleFromJson()) because the Module is not added to the Engine yet. clonedModule->fromJson(moduleJ); json_decref(moduleJ); - // Reset ID so the Engine automatically assigns a new one - clonedModule->id = -1; APP->engine->addModule(clonedModule); // Clone ModuleWidget diff --git a/src/app/RackWidget.cpp b/src/app/RackWidget.cpp index be53edb6..764693ff 100644 --- a/src/app/RackWidget.cpp +++ b/src/app/RackWidget.cpp @@ -22,8 +22,9 @@ namespace app { /** Creates a new Module and ModuleWidget */ -ModuleWidget* moduleWidgetFromJson(json_t* moduleJ) { +static ModuleWidget* moduleWidgetFromJson(json_t* moduleJ) { plugin::Model* model = plugin::modelFromJson(moduleJ); + assert(model); engine::Module* module = model->createModule(); assert(module); module->fromJson(moduleJ); @@ -287,10 +288,12 @@ void RackWidget::fromJson(json_t* rootJ) { } CableWidget* cw = new CableWidget; - // Legacy: Before v1, cable colors were not serialized. So we need to initialize the color here. - cw->setNextCableColor(); cw->setCable(cable); cw->fromJson(cableJ); + // In <=v1, cable colors were not serialized, so choose one from the available colors. + if (cw->color.a == 0.f) { + cw->setNextCableColor(); + } addCable(cw); } } @@ -308,20 +311,19 @@ void RackWidget::pastePresetClipboardAction() { WARN("JSON parsing error at %s %d:%d %s", error.source, error.line, error.column, error.text); return; } - DEFER({ - json_decref(moduleJ); - }); + DEFER({json_decref(moduleJ);}); + + // Because we are creating a new module, we don't want to use the IDs from the JSON. + json_object_del(moduleJ, "id"); + json_object_del(moduleJ, "leftModuleId"); + json_object_del(moduleJ, "rightModuleId"); try { - plugin::Model* model = plugin::modelFromJson(moduleJ); - engine::Module* module = model->createModule(); - assert(module); - module->fromJson(moduleJ); - // Reset ID so the Engine automatically assigns a new one - module->id = -1; - APP->engine->addModule(module); - - ModuleWidget* mw = module->model->createModuleWidget(module); + ModuleWidget* mw = moduleWidgetFromJson(moduleJ); + assert(mw); + assert(mw->module); + + APP->engine->addModule(mw->module); addModuleAtMouse(mw); // history::ModuleAdd diff --git a/src/engine/Module.cpp b/src/engine/Module.cpp index 08c778d7..aedf9d4f 100644 --- a/src/engine/Module.cpp +++ b/src/engine/Module.cpp @@ -152,13 +152,10 @@ void Module::fromJson(json_t* rootJ) { } } - // Only set ID if unset - if (id < 0) { - // id - json_t* idJ = json_object_get(rootJ, "id"); - if (idJ) - id = json_integer_value(idJ); - } + // id + json_t* idJ = json_object_get(rootJ, "id"); + if (idJ) + id = json_integer_value(idJ); // params json_t* paramsJ = json_object_get(rootJ, "params"); @@ -176,16 +173,15 @@ void Module::fromJson(json_t* rootJ) { if (bypassedJ) internal->bypassed = json_boolean_value(bypassedJ); - // These do not need to be deserialized, since the module positions will set them correctly when added to the rack. - // // leftModuleId - // json_t *leftModuleIdJ = json_object_get(rootJ, "leftModuleId"); - // if (leftModuleIdJ) - // leftExpander.moduleId = json_integer_value(leftModuleIdJ); + // leftModuleId + json_t *leftModuleIdJ = json_object_get(rootJ, "leftModuleId"); + if (leftModuleIdJ) + leftExpander.moduleId = json_integer_value(leftModuleIdJ); - // // rightModuleId - // json_t *rightModuleIdJ = json_object_get(rootJ, "rightModuleId"); - // if (rightModuleIdJ) - // rightExpander.moduleId = json_integer_value(rightModuleIdJ); + // rightModuleId + json_t *rightModuleIdJ = json_object_get(rootJ, "rightModuleId"); + if (rightModuleIdJ) + rightExpander.moduleId = json_integer_value(rightModuleIdJ); // data json_t* dataJ = json_object_get(rootJ, "data"); diff --git a/src/logger.cpp b/src/logger.cpp index 6476b463..730a009a 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -101,9 +101,7 @@ bool isTruncated() { FILE* file = std::fopen(asset::logPath.c_str(), "r"); if (!file) return false; - DEFER({ - std::fclose(file); - }); + DEFER({std::fclose(file);}); if (fileEndsWith(file, "END")) return false; diff --git a/src/network.cpp b/src/network.cpp index 610a9586..e1ea5f26 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -4,6 +4,7 @@ #include #include +#include #include @@ -160,7 +161,7 @@ static int xferInfoCallback(void* clientp, curl_off_t dltotal, curl_off_t dlnow, bool requestDownload(const std::string& url, const std::string& filename, float* progress, const CookieMap& cookies) { CURL* curl = createCurl(); - FILE* file = fopen(filename.c_str(), "wb"); + FILE* file = std::fopen(filename.c_str(), "wb"); if (!file) return false; @@ -182,10 +183,10 @@ bool requestDownload(const std::string& url, const std::string& filename, float* CURLcode res = curl_easy_perform(curl); curl_easy_cleanup(curl); - fclose(file); + std::fclose(file); if (res != CURLE_OK) - remove(filename.c_str()); + system::remove(filename); return res == CURLE_OK; } diff --git a/src/patch.cpp b/src/patch.cpp index c2693a3a..a469a93e 100644 --- a/src/patch.cpp +++ b/src/patch.cpp @@ -273,9 +273,7 @@ void PatchManager::loadAutosave() { // TODO Load template without causing infinite recursion return; } - DEFER({ - std::fclose(file); - }); + DEFER({std::fclose(file);}); json_error_t error; json_t* rootJ = json_loadf(file, 0, &error); diff --git a/src/settings.cpp b/src/settings.cpp index b3325d13..f3b4352b 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -260,9 +260,7 @@ void save(const std::string& path) { FILE* file = std::fopen(path.c_str(), "w"); if (!file) return; - DEFER({ - std::fclose(file); - }); + DEFER({std::fclose(file);}); json_dumpf(rootJ, file, JSON_INDENT(2) | JSON_REAL_PRECISION(9)); json_decref(rootJ); @@ -273,9 +271,7 @@ void load(const std::string& path) { FILE* file = std::fopen(path.c_str(), "r"); if (!file) return; - DEFER({ - std::fclose(file); - }); + DEFER({std::fclose(file);}); json_error_t error; json_t* rootJ = json_loadf(file, 0, &error);