| @@ -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; | |||
| } | |||