Browse Source

When loading a patch or autosave, if modules are unavailable, prompt user to close Rack and view them on the VCV Library.

tags/v2.5.0
Andrew Belt 1 year ago
parent
commit
bb8f70c04e
3 changed files with 73 additions and 24 deletions
  1. +6
    -4
      include/patch.hpp
  2. +0
    -2
      src/engine/Engine.cpp
  3. +67
    -18
      src/patch.cpp

+ 6
- 4
include/patch.hpp View File

@@ -22,8 +22,6 @@ struct Manager {
std::string templatePath;
/** Path to factory template patch */
std::string factoryTemplatePath;
/** Append to this while loading/saving a patch to display messages to the user after success. */
std::string warningLog;

PRIVATE Manager();
PRIVATE ~Manager();
@@ -44,10 +42,11 @@ struct Manager {
Returns whether the patch was loaded successfully.
*/
void load(std::string path);
/** Loads the template patch. */
/** Loads the template patch file. */
void loadTemplate();
void loadTemplateDialog();
bool hasAutosave();
/** Loads the patch from the autosave folder. */
void loadAutosave();
/** Loads a patch, sets the current path, and updates the recent patches. */
void loadAction(std::string path);
@@ -61,7 +60,10 @@ struct Manager {

json_t* toJson();
void fromJson(json_t* rootJ);
void log(std::string msg);
/** Checks if the JSON patch object contains modules not found in the loaded plugins, and launches a dialog box asking the user to cancel loading.
Returns whether the user requests to cancel loading the patch.
*/
bool checkUnavailableModulesJson(json_t* rootJ);
};




+ 0
- 2
src/engine/Engine.cpp View File

@@ -1211,7 +1211,6 @@ void Engine::fromJson(json_t* rootJ) {
}
catch (Exception& e) {
WARN("Cannot load model: %s", e.what());
APP->patch->log(e.what());
continue;
}

@@ -1230,7 +1229,6 @@ void Engine::fromJson(json_t* rootJ) {
}
catch (Exception& e) {
WARN("Cannot load module: %s", e.what());
APP->patch->log(e.what());
delete module;
continue;
}


+ 67
- 18
src/patch.cpp View File

@@ -13,6 +13,7 @@
#include <app/RackWidget.hpp>
#include <history.hpp>
#include <settings.hpp>
#include <plugin.hpp>


namespace rack {
@@ -22,7 +23,14 @@ namespace patch {
static const char PATCH_FILTERS[] = "VCV Rack patch (.vcv):vcv";


struct Manager::Internal {
bool disableAutosaveOnClose = false;
};


Manager::Manager() {
internal = new Internal;

autosavePath = asset::user("autosave");

// Use a different temporary autosave dir when safe mode is enabled, to avoid altering normal autosave.
@@ -43,13 +51,17 @@ Manager::~Manager() {
return;
}

// Dispatch onSave to all Modules so they save their patch storage, etc.
APP->engine->prepareSave();
// Save autosave if not headless
if (!settings::headless) {
APP->patch->saveAutosave();
if (!internal->disableAutosaveOnClose) {
// Dispatch onSave to all Modules so they save their patch storage, etc.
APP->engine->prepareSave();
// Save autosave if not headless
if (!settings::headless) {
APP->patch->saveAutosave();
}
cleanAutosave();
}
cleanAutosave();

delete internal;
}


@@ -348,6 +360,9 @@ void Manager::loadAutosave() {
throw Exception("Failed to load patch. JSON parsing error at %s %d:%d %s", error.source, error.line, error.column, error.text);
DEFER({json_decref(rootJ);});

if (checkUnavailableModulesJson(rootJ))
return;

fromJson(rootJ);
}

@@ -475,7 +490,6 @@ json_t* Manager::toJson() {

void Manager::fromJson(json_t* rootJ) {
clear();
warningLog = "";

// version
std::string version;
@@ -521,23 +535,58 @@ void Manager::fromJson(json_t* rootJ) {
}
}
catch (Exception& e) {
warningLog += "\n";
warningLog += e.what();
WARN("Cannot load patch: %s", e.what());
}
// At this point, ModuleWidgets and CableWidgets should own all Modules and Cables.
// TODO Assert this

// Display a message if we have something to say.
if (warningLog != "") {
osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK, warningLog.c_str());
}
warningLog = "";
}


void Manager::log(std::string msg) {
warningLog += msg;
warningLog += "\n";
bool Manager::checkUnavailableModulesJson(json_t* rootJ) {
std::set<std::string> pluginModuleSlugs;

json_t* modulesJ = json_object_get(rootJ, "modules");
if (!modulesJ)
return false;
size_t moduleIndex;
json_t* moduleJ;
json_array_foreach(modulesJ, moduleIndex, moduleJ) {
// Get model
try {
plugin::modelFromJson(moduleJ);
}
catch (Exception& e) {
// Get plugin and module slugs
json_t* pluginSlugJ = json_object_get(moduleJ, "plugin");
if (!pluginSlugJ)
continue;
std::string pluginSlug = json_string_value(pluginSlugJ);

json_t* modelSlugJ = json_object_get(moduleJ, "model");
if (!modelSlugJ)
continue;
std::string modelSlug = json_string_value(modelSlugJ);

// Add to list
pluginModuleSlugs.insert(pluginSlug + "/" + modelSlug);
}
}

if (!pluginModuleSlugs.empty()) {
std::string msg = "This patch includes modules that are not installed. Close Rack and show missing modules on the VCV Library?";
if (osdialog_message(OSDIALOG_WARNING, OSDIALOG_YES_NO, msg.c_str())) {
std::string url = "https://library.vcvrack.com/?modules=";
url += string::join(pluginModuleSlugs, ",");
system::openBrowser(url);
// Close Rack
APP->window->close();
// Don't save autosave when closing
// Possible bug: The autosave internal could still occur before the window closes
internal->disableAutosaveOnClose = true;
return true;
}
}
return false;
}




Loading…
Cancel
Save