Browse Source

Make Module always deserialize "id", "leftModuleId", and "rightModuleId". Due to this, make pasting and cloning modules delete these properties from the JSON before `fromJson()` is called.

tags/v2.0.0
Andrew Belt 4 years ago
parent
commit
f3c8262183
8 changed files with 65 additions and 77 deletions
  1. +1
    -1
      include/helpers.hpp
  2. +27
    -30
      src/app/ModuleWidget.cpp
  3. +17
    -15
      src/app/RackWidget.cpp
  4. +12
    -16
      src/engine/Module.cpp
  5. +1
    -3
      src/logger.cpp
  6. +4
    -3
      src/network.cpp
  7. +1
    -3
      src/patch.cpp
  8. +2
    -6
      src/settings.cpp

+ 1
- 1
include/helpers.hpp View File

@@ -26,7 +26,7 @@ plugin::Model* createModel(const std::string& slug) {
return m; return m;
} }
app::ModuleWidget* createModuleWidget(engine::Module* m) override { app::ModuleWidget* createModuleWidget(engine::Module* m) override {
TModule *tm = NULL;
TModule* tm = NULL;
if (m) { if (m) {
assert(m->model == this); assert(m->model == this);
tm = dynamic_cast<TModule*>(m); tm = dynamic_cast<TModule*>(m);


+ 27
- 30
src/app/ModuleWidget.cpp View File

@@ -611,8 +611,6 @@ PortWidget* ModuleWidget::getOutput(int portId) {


json_t* ModuleWidget::toJson() { json_t* ModuleWidget::toJson() {
json_t* moduleJ = APP->engine->moduleToJson(module); 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; return moduleJ;
} }


@@ -622,13 +620,9 @@ void ModuleWidget::fromJson(json_t* rootJ) {


void ModuleWidget::copyClipboard() { void ModuleWidget::copyClipboard() {
json_t* moduleJ = toJson(); json_t* moduleJ = toJson();
DEFER({
json_decref(moduleJ);
});
DEFER({json_decref(moduleJ);});
char* moduleJson = json_dumps(moduleJ, JSON_INDENT(2) | JSON_REAL_PRECISION(9)); char* moduleJson = json_dumps(moduleJ, JSON_INDENT(2) | JSON_REAL_PRECISION(9));
DEFER({
free(moduleJson);
});
DEFER({std::free(moduleJson);});
glfwSetClipboardString(APP->window->win, 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); WARN("JSON parsing error at %s %d:%d %s", error.source, error.line, error.column, error.text);
return; 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
history::ModuleChange* h = new 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"); FILE* file = std::fopen(filename.c_str(), "r");
if (!file) if (!file)
throw Exception(string::f("Could not load patch file %s", filename.c_str())); 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()); 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); json_t* moduleJ = json_loadf(file, 0, &error);
if (!moduleJ) 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)); 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); fromJson(moduleJ);
} }
@@ -729,7 +727,7 @@ void ModuleWidget::loadDialog() {
// No path selected // No path selected
return; return;
} }
DEFER({free(pathC);});
DEFER({std::free(pathC);});


try { try {
loadAction(pathC); loadAction(pathC);
@@ -744,17 +742,13 @@ void ModuleWidget::save(std::string filename) {


json_t* moduleJ = toJson(); json_t* moduleJ = toJson();
assert(moduleJ); 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) { if (!file) {
WARN("Could not write to patch file %s", filename.c_str()); 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)); json_dumpf(moduleJ, file, JSON_INDENT(2) | JSON_REAL_PRECISION(9));
} }
@@ -786,7 +780,7 @@ void ModuleWidget::saveDialog() {
// No path selected // No path selected
return; return;
} }
DEFER({free(pathC);});
DEFER({std::free(pathC);});


std::string path = pathC; std::string path = pathC;
if (system::getExtension(path) == "") if (system::getExtension(path) == "")
@@ -872,15 +866,18 @@ void ModuleWidget::cloneAction() {
// history::ComplexAction // history::ComplexAction
history::ComplexAction* h = new 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 serialization is the obvious way to do this
json_t* moduleJ = toJson(); 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. // This doesn't need a lock (via Engine::moduleFromJson()) because the Module is not added to the Engine yet.
clonedModule->fromJson(moduleJ); clonedModule->fromJson(moduleJ);
json_decref(moduleJ); json_decref(moduleJ);
// Reset ID so the Engine automatically assigns a new one
clonedModule->id = -1;
APP->engine->addModule(clonedModule); APP->engine->addModule(clonedModule);


// Clone ModuleWidget // Clone ModuleWidget


+ 17
- 15
src/app/RackWidget.cpp View File

@@ -22,8 +22,9 @@ namespace app {




/** Creates a new Module and ModuleWidget */ /** Creates a new Module and ModuleWidget */
ModuleWidget* moduleWidgetFromJson(json_t* moduleJ) {
static ModuleWidget* moduleWidgetFromJson(json_t* moduleJ) {
plugin::Model* model = plugin::modelFromJson(moduleJ); plugin::Model* model = plugin::modelFromJson(moduleJ);
assert(model);
engine::Module* module = model->createModule(); engine::Module* module = model->createModule();
assert(module); assert(module);
module->fromJson(moduleJ); module->fromJson(moduleJ);
@@ -287,10 +288,12 @@ void RackWidget::fromJson(json_t* rootJ) {
} }


CableWidget* cw = new CableWidget; 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->setCable(cable);
cw->fromJson(cableJ); 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); 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); WARN("JSON parsing error at %s %d:%d %s", error.source, error.line, error.column, error.text);
return; 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 { 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); addModuleAtMouse(mw);


// history::ModuleAdd // history::ModuleAdd


+ 12
- 16
src/engine/Module.cpp View File

@@ -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 // params
json_t* paramsJ = json_object_get(rootJ, "params"); json_t* paramsJ = json_object_get(rootJ, "params");
@@ -176,16 +173,15 @@ void Module::fromJson(json_t* rootJ) {
if (bypassedJ) if (bypassedJ)
internal->bypassed = json_boolean_value(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 // data
json_t* dataJ = json_object_get(rootJ, "data"); json_t* dataJ = json_object_get(rootJ, "data");


+ 1
- 3
src/logger.cpp View File

@@ -101,9 +101,7 @@ bool isTruncated() {
FILE* file = std::fopen(asset::logPath.c_str(), "r"); FILE* file = std::fopen(asset::logPath.c_str(), "r");
if (!file) if (!file)
return false; return false;
DEFER({
std::fclose(file);
});
DEFER({std::fclose(file);});


if (fileEndsWith(file, "END")) if (fileEndsWith(file, "END"))
return false; return false;


+ 4
- 3
src/network.cpp View File

@@ -4,6 +4,7 @@
#include <curl/curl.h> #include <curl/curl.h>


#include <network.hpp> #include <network.hpp>
#include <system.hpp>
#include <asset.hpp> #include <asset.hpp>




@@ -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) { bool requestDownload(const std::string& url, const std::string& filename, float* progress, const CookieMap& cookies) {
CURL* curl = createCurl(); CURL* curl = createCurl();


FILE* file = fopen(filename.c_str(), "wb");
FILE* file = std::fopen(filename.c_str(), "wb");
if (!file) if (!file)
return false; return false;


@@ -182,10 +183,10 @@ bool requestDownload(const std::string& url, const std::string& filename, float*
CURLcode res = curl_easy_perform(curl); CURLcode res = curl_easy_perform(curl);
curl_easy_cleanup(curl); curl_easy_cleanup(curl);


fclose(file);
std::fclose(file);


if (res != CURLE_OK) if (res != CURLE_OK)
remove(filename.c_str());
system::remove(filename);


return res == CURLE_OK; return res == CURLE_OK;
} }


+ 1
- 3
src/patch.cpp View File

@@ -273,9 +273,7 @@ void PatchManager::loadAutosave() {
// TODO Load template without causing infinite recursion // TODO Load template without causing infinite recursion
return; return;
} }
DEFER({
std::fclose(file);
});
DEFER({std::fclose(file);});


json_error_t error; json_error_t error;
json_t* rootJ = json_loadf(file, 0, &error); json_t* rootJ = json_loadf(file, 0, &error);


+ 2
- 6
src/settings.cpp View File

@@ -260,9 +260,7 @@ void save(const std::string& path) {
FILE* file = std::fopen(path.c_str(), "w"); FILE* file = std::fopen(path.c_str(), "w");
if (!file) if (!file)
return; return;
DEFER({
std::fclose(file);
});
DEFER({std::fclose(file);});


json_dumpf(rootJ, file, JSON_INDENT(2) | JSON_REAL_PRECISION(9)); json_dumpf(rootJ, file, JSON_INDENT(2) | JSON_REAL_PRECISION(9));
json_decref(rootJ); json_decref(rootJ);
@@ -273,9 +271,7 @@ void load(const std::string& path) {
FILE* file = std::fopen(path.c_str(), "r"); FILE* file = std::fopen(path.c_str(), "r");
if (!file) if (!file)
return; return;
DEFER({
std::fclose(file);
});
DEFER({std::fclose(file);});


json_error_t error; json_error_t error;
json_t* rootJ = json_loadf(file, 0, &error); json_t* rootJ = json_loadf(file, 0, &error);


Loading…
Cancel
Save