@@ -744,7 +744,12 @@ void ModuleWidget::pasteClipboardAction() { | |||
h->moduleId = module->id; | |||
h->oldModuleJ = toJson(); | |||
fromJson(moduleJ); | |||
try { | |||
fromJson(moduleJ); | |||
} | |||
catch (Exception& e) { | |||
WARN("%s", e.what()); | |||
} | |||
h->newModuleJ = toJson(); | |||
APP->history->push(h); | |||
@@ -1006,7 +1011,12 @@ void ModuleWidget::cloneAction() { | |||
// 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); | |||
try { | |||
clonedModule->fromJson(moduleJ); | |||
} | |||
catch (Exception& e) { | |||
WARN("%s", e.what()); | |||
} | |||
json_decref(moduleJ); | |||
APP->engine->addModule(clonedModule); | |||
@@ -105,12 +105,12 @@ json_t* Module::toJson() { | |||
// plugin | |||
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 | |||
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 | |||
json_t* paramsJ = paramsToJson(); | |||
if (paramsJ) | |||
@@ -139,35 +139,17 @@ json_t* Module::toJson() { | |||
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 | |||
json_t* versionJ = json_object_get(rootJ, "version"); | |||
if (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()) | |||
continue; | |||
ParamQuantity* pq = paramQuantities[paramId]; | |||
// Check that the Param is bounded | |||
if (!paramQuantities[paramId]->isBounded()) | |||
if (!pq->isBounded()) | |||
continue; | |||
json_t* valueJ = json_object_get(paramJ, "value"); | |||
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() { | |||
engine::Module* module = model->createModule(); | |||
module->id = moduleId; | |||
module->fromJson(moduleJ); | |||
try { | |||
module->fromJson(moduleJ); | |||
} | |||
catch (Exception& e) { | |||
WARN("%s", e.what()); | |||
} | |||
APP->engine->addModule(module); | |||
app::ModuleWidget* mw = model->createModuleWidget(module); | |||
@@ -460,9 +460,15 @@ void PatchManager::fromJson(json_t* rootJ) { | |||
if (!unsavedJ) | |||
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. | |||
// TODO Assert this | |||
@@ -1,6 +1,7 @@ | |||
#include <thread> | |||
#include <map> | |||
#include <stdexcept> | |||
#include <tuple> | |||
#include <sys/types.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) { | |||
if (pluginSlug.empty()) | |||
return NULL; | |||
for (Plugin* plugin : plugins) { | |||
if (plugin->slug == pluginSlug) { | |||
return plugin; | |||
} | |||
} | |||
// Use fallback plugin slug | |||
auto it = pluginSlugFallbacks.find(pluginSlug); | |||
if (it != pluginSlugFallbacks.end()) { | |||
return getPlugin(it->second); | |||
} | |||
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) { | |||
Plugin* plugin = getPlugin(pluginSlug); | |||
if (!plugin) | |||
if (pluginSlug.empty() || modelSlug.empty()) | |||
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; | |||
} | |||