@@ -744,7 +744,12 @@ void ModuleWidget::pasteClipboardAction() { | |||||
h->moduleId = module->id; | h->moduleId = module->id; | ||||
h->oldModuleJ = toJson(); | h->oldModuleJ = toJson(); | ||||
fromJson(moduleJ); | |||||
try { | |||||
fromJson(moduleJ); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("%s", e.what()); | |||||
} | |||||
h->newModuleJ = toJson(); | h->newModuleJ = toJson(); | ||||
APP->history->push(h); | APP->history->push(h); | ||||
@@ -1006,7 +1011,12 @@ void ModuleWidget::cloneAction() { | |||||
// Clone Module | // Clone Module | ||||
engine::Module* clonedModule = model->createModule(); | 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); | |||||
try { | |||||
clonedModule->fromJson(moduleJ); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("%s", e.what()); | |||||
} | |||||
json_decref(moduleJ); | json_decref(moduleJ); | ||||
APP->engine->addModule(clonedModule); | APP->engine->addModule(clonedModule); | ||||
@@ -105,12 +105,12 @@ json_t* Module::toJson() { | |||||
// plugin | // plugin | ||||
json_object_set_new(rootJ, "plugin", json_string(model->plugin->slug.c_str())); | json_object_set_new(rootJ, "plugin", json_string(model->plugin->slug.c_str())); | ||||
// version | |||||
json_object_set_new(rootJ, "version", json_string(model->plugin->version.c_str())); | |||||
// model | // model | ||||
json_object_set_new(rootJ, "model", json_string(model->slug.c_str())); | json_object_set_new(rootJ, "model", json_string(model->slug.c_str())); | ||||
// version | |||||
json_object_set_new(rootJ, "version", json_string(model->plugin->version.c_str())); | |||||
// params | // params | ||||
json_t* paramsJ = paramsToJson(); | json_t* paramsJ = paramsToJson(); | ||||
if (paramsJ) | if (paramsJ) | ||||
@@ -139,35 +139,17 @@ json_t* Module::toJson() { | |||||
void Module::fromJson(json_t* rootJ) { | void Module::fromJson(json_t* rootJ) { | ||||
// Check if plugin and model are incorrect | |||||
json_t* pluginJ = json_object_get(rootJ, "plugin"); | |||||
std::string pluginSlug; | |||||
if (pluginJ) { | |||||
pluginSlug = json_string_value(pluginJ); | |||||
pluginSlug = plugin::normalizeSlug(pluginSlug); | |||||
if (pluginSlug != model->plugin->slug) { | |||||
WARN("Plugin %s does not match Module's plugin %s.", pluginSlug.c_str(), model->plugin->slug.c_str()); | |||||
return; | |||||
} | |||||
} | |||||
json_t* modelJ = json_object_get(rootJ, "model"); | |||||
std::string modelSlug; | |||||
if (modelJ) { | |||||
modelSlug = json_string_value(modelJ); | |||||
modelSlug = plugin::normalizeSlug(modelSlug); | |||||
if (modelSlug != model->slug) { | |||||
WARN("Model %s does not match Module's model %s.", modelSlug.c_str(), model->slug.c_str()); | |||||
return; | |||||
} | |||||
} | |||||
plugin::Model* model = plugin::modelFromJson(rootJ); | |||||
assert(model); | |||||
if (model != this->model) | |||||
throw Exception("Model %s %s does not match Module's model %s %s.", model->plugin->slug.c_str(), model->slug.c_str(), this->model->plugin->slug.c_str(), this->model->slug.c_str()); | |||||
// Check plugin version | // Check plugin version | ||||
json_t* versionJ = json_object_get(rootJ, "version"); | json_t* versionJ = json_object_get(rootJ, "version"); | ||||
if (versionJ) { | if (versionJ) { | ||||
std::string version = json_string_value(versionJ); | std::string version = json_string_value(versionJ); | ||||
if (version != model->plugin->version) { | |||||
INFO("Patch created with %s v%s, currently using v%s.", pluginSlug.c_str(), version.c_str(), model->plugin->version.c_str()); | |||||
if (version != this->model->plugin->version) { | |||||
INFO("Patch created with %s v%s, currently using v%s.", this->model->plugin->slug.c_str(), version.c_str(), this->model->plugin->version.c_str()); | |||||
} | } | ||||
} | } | ||||
@@ -243,13 +225,14 @@ void Module::paramsFromJson(json_t* rootJ) { | |||||
if (paramId >= paramQuantities.size()) | if (paramId >= paramQuantities.size()) | ||||
continue; | continue; | ||||
ParamQuantity* pq = paramQuantities[paramId]; | |||||
// Check that the Param is bounded | // Check that the Param is bounded | ||||
if (!paramQuantities[paramId]->isBounded()) | |||||
if (!pq->isBounded()) | |||||
continue; | continue; | ||||
json_t* valueJ = json_object_get(paramJ, "value"); | json_t* valueJ = json_object_get(paramJ, "value"); | ||||
if (valueJ) | if (valueJ) | ||||
paramQuantities[paramId]->setValue(json_number_value(valueJ)); | |||||
pq->setValue(json_number_value(valueJ)); | |||||
} | } | ||||
} | } | ||||
@@ -63,7 +63,12 @@ void ModuleAdd::undo() { | |||||
void ModuleAdd::redo() { | void ModuleAdd::redo() { | ||||
engine::Module* module = model->createModule(); | engine::Module* module = model->createModule(); | ||||
module->id = moduleId; | module->id = moduleId; | ||||
module->fromJson(moduleJ); | |||||
try { | |||||
module->fromJson(moduleJ); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("%s", e.what()); | |||||
} | |||||
APP->engine->addModule(module); | APP->engine->addModule(module); | ||||
app::ModuleWidget* mw = model->createModuleWidget(module); | app::ModuleWidget* mw = model->createModuleWidget(module); | ||||
@@ -460,9 +460,15 @@ void PatchManager::fromJson(json_t* rootJ) { | |||||
if (!unsavedJ) | if (!unsavedJ) | ||||
APP->history->setSaved(); | APP->history->setSaved(); | ||||
APP->engine->fromJson(rootJ); | |||||
if (APP->scene) { | |||||
APP->scene->rack->fromJson(rootJ); | |||||
try { | |||||
APP->engine->fromJson(rootJ); | |||||
if (APP->scene) { | |||||
APP->scene->rack->fromJson(rootJ); | |||||
} | |||||
} | |||||
catch (Exception& e) { | |||||
warningLog += "\n"; | |||||
warningLog += e.what(); | |||||
} | } | ||||
// At this point, ModuleWidgets and CableWidgets should own all Modules and Cables. | // At this point, ModuleWidgets and CableWidgets should own all Modules and Cables. | ||||
// TODO Assert this | // TODO Assert this | ||||
@@ -1,6 +1,7 @@ | |||||
#include <thread> | #include <thread> | ||||
#include <map> | #include <map> | ||||
#include <stdexcept> | #include <stdexcept> | ||||
#include <tuple> | |||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
@@ -250,24 +251,53 @@ void destroy() { | |||||
} | } | ||||
// To request fallback slugs to be added to this list, open a GitHub issue. | |||||
static const std::map<std::string, std::string> pluginSlugFallbacks = { | |||||
// {"", ""}, | |||||
}; | |||||
Plugin* getPlugin(const std::string& pluginSlug) { | Plugin* getPlugin(const std::string& pluginSlug) { | ||||
if (pluginSlug.empty()) | |||||
return NULL; | |||||
for (Plugin* plugin : plugins) { | for (Plugin* plugin : plugins) { | ||||
if (plugin->slug == pluginSlug) { | if (plugin->slug == pluginSlug) { | ||||
return plugin; | return plugin; | ||||
} | } | ||||
} | } | ||||
// Use fallback plugin slug | |||||
auto it = pluginSlugFallbacks.find(pluginSlug); | |||||
if (it != pluginSlugFallbacks.end()) { | |||||
return getPlugin(it->second); | |||||
} | |||||
return NULL; | return NULL; | ||||
} | } | ||||
// To request fallback slugs to be added to this list, open a GitHub issue. | |||||
using PluginModuleSlug = std::tuple<std::string, std::string>; | |||||
static const std::map<PluginModuleSlug, PluginModuleSlug> moduleSlugFallbacks = { | |||||
{{"AudibleInstrumentsPreview", "Plaits"}, {"AudibleInstruments", "Plaits"}}, | |||||
{{"AudibleInstrumentsPreview", "Marbles"}, {"AudibleInstruments", "Marbles"}}, | |||||
// {{"", ""}, {"", ""}}, | |||||
}; | |||||
Model* getModel(const std::string& pluginSlug, const std::string& modelSlug) { | Model* getModel(const std::string& pluginSlug, const std::string& modelSlug) { | ||||
Plugin* plugin = getPlugin(pluginSlug); | |||||
if (!plugin) | |||||
if (pluginSlug.empty() || modelSlug.empty()) | |||||
return NULL; | return NULL; | ||||
Model* model = plugin->getModel(modelSlug); | |||||
if (!model) | |||||
return NULL; | |||||
return model; | |||||
Plugin* plugin = getPlugin(pluginSlug); | |||||
if (plugin) { | |||||
Model* model = plugin->getModel(modelSlug); | |||||
if (model) | |||||
return model; | |||||
} | |||||
// Use fallback (module slug, plugin slug) | |||||
auto it = moduleSlugFallbacks.find(std::make_tuple(pluginSlug, modelSlug)); | |||||
if (it != moduleSlugFallbacks.end()) { | |||||
return getModel(std::get<0>(it->second), std::get<1>(it->second)); | |||||
} | |||||
return NULL; | |||||
} | } | ||||