@@ -2,13 +2,11 @@ | |||||
/Rack.exe | /Rack.exe | ||||
/Rack.res | /Rack.res | ||||
/libRack.a | /libRack.a | ||||
/autosave.json | |||||
/settings.json | |||||
/dep | |||||
/plugins | /plugins | ||||
/build | /build | ||||
/dep | |||||
*.vcv | |||||
/dist | |||||
/patches | /patches | ||||
/design | |||||
.DS_Store | .DS_Store | ||||
/dist | |||||
/autosave.vcv | |||||
/settings.json |
@@ -13,13 +13,14 @@ struct PatchManager { | |||||
int legacy; | int legacy; | ||||
std::string warningLog; | std::string warningLog; | ||||
void init(std::string path); | |||||
void reset(); | void reset(); | ||||
void resetDialog(); | void resetDialog(); | ||||
void save(std::string path); | void save(std::string path); | ||||
void saveDialog(); | void saveDialog(); | ||||
void saveAsDialog(); | void saveAsDialog(); | ||||
void saveTemplateDialog(); | void saveTemplateDialog(); | ||||
void load(std::string path); | |||||
bool load(std::string path); | |||||
void loadDialog(); | void loadDialog(); | ||||
/** If `lastPath` is defined, ask the user to reload it */ | /** If `lastPath` is defined, ask the user to reload it */ | ||||
void revertDialog(); | void revertDialog(); | ||||
@@ -37,7 +37,7 @@ int main(int argc, char *argv[]) { | |||||
#endif | #endif | ||||
bool devMode = false; | bool devMode = false; | ||||
std::string patchFile; | |||||
std::string patchPath; | |||||
// Parse command line arguments | // Parse command line arguments | ||||
int c; | int c; | ||||
@@ -57,7 +57,7 @@ int main(int argc, char *argv[]) { | |||||
} | } | ||||
} | } | ||||
if (optind < argc) { | if (optind < argc) { | ||||
patchFile = argv[optind]; | |||||
patchPath = argv[optind]; | |||||
} | } | ||||
// Initialize environment | // Initialize environment | ||||
@@ -86,28 +86,8 @@ int main(int argc, char *argv[]) { | |||||
appInit(); | appInit(); | ||||
app()->scene->devMode = devMode; | app()->scene->devMode = devMode; | ||||
settings::load(asset::user("settings.json")); | settings::load(asset::user("settings.json")); | ||||
app()->patch->init(patchPath); | |||||
if (patchFile.empty()) { | |||||
// To prevent launch crashes, if Rack crashes between now and 15 seconds from now, the "skipAutosaveOnLaunch" property will remain in settings.json, so that in the next launch, the broken autosave will not be loaded. | |||||
bool oldSkipLoadOnLaunch = settings::skipLoadOnLaunch; | |||||
settings::skipLoadOnLaunch = true; | |||||
settings::save(asset::user("settings.json")); | |||||
settings::skipLoadOnLaunch = false; | |||||
if (oldSkipLoadOnLaunch && osdialog_message(OSDIALOG_INFO, OSDIALOG_YES_NO, "Rack has recovered from a crash, possibly caused by a faulty module in your patch. Clear your patch and start over?")) { | |||||
app()->patch->path = ""; | |||||
} | |||||
else { | |||||
// Load autosave | |||||
std::string oldLastPath = app()->patch->path; | |||||
app()->patch->load(asset::user("autosave.vcv")); | |||||
app()->patch->path = oldLastPath; | |||||
} | |||||
} | |||||
else { | |||||
// Load patch | |||||
app()->patch->load(patchFile); | |||||
app()->patch->path = patchFile; | |||||
} | |||||
INFO("Initialized app"); | INFO("Initialized app"); | ||||
app()->engine->start(); | app()->engine->start(); | ||||
@@ -5,6 +5,8 @@ | |||||
#include "app/Scene.hpp" | #include "app/Scene.hpp" | ||||
#include "app/RackWidget.hpp" | #include "app/RackWidget.hpp" | ||||
#include "history.hpp" | #include "history.hpp" | ||||
#include "settings.hpp" | |||||
#include "osdialog.h" | #include "osdialog.h" | ||||
@@ -14,6 +16,39 @@ namespace rack { | |||||
static const char PATCH_FILTERS[] = "VCV Rack patch (.vcv):vcv"; | static const char PATCH_FILTERS[] = "VCV Rack patch (.vcv):vcv"; | ||||
void PatchManager::init(std::string path) { | |||||
if (!path.empty()) { | |||||
// Load patch | |||||
load(path); | |||||
this->path = path; | |||||
return; | |||||
} | |||||
// To prevent launch crashes, if Rack crashes between now and 15 seconds from now, the "skipAutosaveOnLaunch" property will remain in settings.json, so that in the next launch, the broken autosave will not be loaded. | |||||
bool oldSkipLoadOnLaunch = settings::skipLoadOnLaunch; | |||||
settings::skipLoadOnLaunch = true; | |||||
settings::save(asset::user("settings.json")); | |||||
settings::skipLoadOnLaunch = false; | |||||
if (oldSkipLoadOnLaunch && osdialog_message(OSDIALOG_INFO, OSDIALOG_YES_NO, "Rack has recovered from a crash, possibly caused by a faulty module in your patch. Clear your patch and start over?")) { | |||||
this->path = ""; | |||||
return; | |||||
} | |||||
// Load autosave | |||||
if (load(asset::user("autosave.vcv"))) { | |||||
return; | |||||
} | |||||
this->path = ""; | |||||
if (load(asset::user("template.vcv"))) { | |||||
return; | |||||
} | |||||
if (load(asset::system("template.vcv"))) { | |||||
return; | |||||
} | |||||
} | |||||
void PatchManager::reset() { | void PatchManager::reset() { | ||||
app()->history->clear(); | app()->history->clear(); | ||||
app()->scene->rackWidget->clear(); | app()->scene->rackWidget->clear(); | ||||
@@ -102,12 +137,12 @@ void PatchManager::saveTemplateDialog() { | |||||
} | } | ||||
} | } | ||||
void PatchManager::load(std::string path) { | |||||
bool PatchManager::load(std::string path) { | |||||
INFO("Loading patch %s", path.c_str()); | INFO("Loading patch %s", path.c_str()); | ||||
FILE *file = std::fopen(path.c_str(), "r"); | FILE *file = std::fopen(path.c_str(), "r"); | ||||
if (!file) { | if (!file) { | ||||
// Exit silently | // Exit silently | ||||
return; | |||||
return false; | |||||
} | } | ||||
DEFER({ | DEFER({ | ||||
std::fclose(file); | std::fclose(file); | ||||
@@ -118,7 +153,7 @@ void PatchManager::load(std::string path) { | |||||
if (!rootJ) { | if (!rootJ) { | ||||
std::string message = string::f("JSON parsing error at %s %d:%d %s", error.source, error.line, error.column, error.text); | std::string message = string::f("JSON parsing error at %s %d:%d %s", error.source, error.line, error.column, error.text); | ||||
osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK, message.c_str()); | osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK, message.c_str()); | ||||
return; | |||||
return false; | |||||
} | } | ||||
DEFER({ | DEFER({ | ||||
json_decref(rootJ); | json_decref(rootJ); | ||||
@@ -128,6 +163,7 @@ void PatchManager::load(std::string path) { | |||||
app()->scene->rackWidget->clear(); | app()->scene->rackWidget->clear(); | ||||
app()->scene->scrollWidget->offset = math::Vec(0, 0); | app()->scene->scrollWidget->offset = math::Vec(0, 0); | ||||
fromJson(rootJ); | fromJson(rootJ); | ||||
return true; | |||||
} | } | ||||
void PatchManager::loadDialog() { | void PatchManager::loadDialog() { | ||||
@@ -0,0 +1,238 @@ | |||||
{ | |||||
"version": "1.dev", | |||||
"modules": [ | |||||
{ | |||||
"plugin": "Core", | |||||
"version": "1.dev", | |||||
"model": "AudioInterface", | |||||
"params": [], | |||||
"data": { | |||||
}, | |||||
"id": 1, | |||||
"pos": [ | |||||
47, | |||||
0 | |||||
] | |||||
}, | |||||
{ | |||||
"plugin": "Fundamental", | |||||
"version": "1.0.0", | |||||
"model": "VCMixer", | |||||
"params": [ | |||||
{ | |||||
"value": 1.0 | |||||
}, | |||||
{ | |||||
"value": 1.0 | |||||
}, | |||||
{ | |||||
"value": 1.0 | |||||
}, | |||||
{ | |||||
"value": 1.0 | |||||
}, | |||||
{ | |||||
"value": 1.0 | |||||
} | |||||
], | |||||
"id": 2, | |||||
"pos": [ | |||||
37, | |||||
0 | |||||
] | |||||
}, | |||||
{ | |||||
"plugin": "Fundamental", | |||||
"version": "1.0.0", | |||||
"model": "VCO", | |||||
"params": [ | |||||
{ | |||||
"value": 1.0 | |||||
}, | |||||
{ | |||||
"value": 1.0 | |||||
}, | |||||
{ | |||||
"value": 0.0 | |||||
}, | |||||
{ | |||||
"value": 0.0 | |||||
}, | |||||
{ | |||||
"value": 0.0 | |||||
}, | |||||
{ | |||||
"value": 0.5 | |||||
}, | |||||
{ | |||||
"value": 0.0 | |||||
} | |||||
], | |||||
"id": 3, | |||||
"pos": [ | |||||
8, | |||||
0 | |||||
] | |||||
}, | |||||
{ | |||||
"plugin": "Fundamental", | |||||
"version": "1.0.0", | |||||
"model": "VCF", | |||||
"params": [ | |||||
{ | |||||
"value": 0.262999862 | |||||
}, | |||||
{ | |||||
"value": 0.5 | |||||
}, | |||||
{ | |||||
"value": 0.236999944 | |||||
}, | |||||
{ | |||||
"value": 0.869999945 | |||||
}, | |||||
{ | |||||
"value": 0.0 | |||||
} | |||||
], | |||||
"id": 4, | |||||
"pos": [ | |||||
18, | |||||
0 | |||||
] | |||||
}, | |||||
{ | |||||
"plugin": "Core", | |||||
"version": "1.dev", | |||||
"model": "MIDIToCVInterface", | |||||
"params": [], | |||||
"data": { | |||||
"divisions": [ | |||||
24, | |||||
6 | |||||
] | |||||
}, | |||||
"id": 5, | |||||
"pos": [ | |||||
0, | |||||
0 | |||||
] | |||||
}, | |||||
{ | |||||
"plugin": "Fundamental", | |||||
"version": "1.0.0", | |||||
"model": "VCA-1", | |||||
"params": [ | |||||
{ | |||||
"value": 1.0 | |||||
}, | |||||
{ | |||||
"value": 1.0 | |||||
} | |||||
], | |||||
"id": 6, | |||||
"pos": [ | |||||
26, | |||||
0 | |||||
] | |||||
}, | |||||
{ | |||||
"plugin": "Fundamental", | |||||
"version": "1.0.0", | |||||
"model": "ADSR", | |||||
"params": [ | |||||
{ | |||||
"value": 0.356000006 | |||||
}, | |||||
{ | |||||
"value": 0.671000004 | |||||
}, | |||||
{ | |||||
"value": 0.358999938 | |||||
}, | |||||
{ | |||||
"value": 0.5 | |||||
} | |||||
], | |||||
"id": 7, | |||||
"pos": [ | |||||
29, | |||||
0 | |||||
] | |||||
} | |||||
], | |||||
"cables": [ | |||||
{ | |||||
"id": 1, | |||||
"outputModuleId": 5, | |||||
"outputId": 0, | |||||
"inputModuleId": 3, | |||||
"inputId": 0, | |||||
"color": "#c91847" | |||||
}, | |||||
{ | |||||
"id": 2, | |||||
"outputModuleId": 3, | |||||
"outputId": 2, | |||||
"inputModuleId": 4, | |||||
"inputId": 3, | |||||
"color": "#0c8e15" | |||||
}, | |||||
{ | |||||
"id": 3, | |||||
"outputModuleId": 4, | |||||
"outputId": 0, | |||||
"inputModuleId": 6, | |||||
"inputId": 1, | |||||
"color": "#0986ad" | |||||
}, | |||||
{ | |||||
"id": 4, | |||||
"outputModuleId": 6, | |||||
"outputId": 0, | |||||
"inputModuleId": 2, | |||||
"inputId": 1, | |||||
"color": "#c9b70e" | |||||
}, | |||||
{ | |||||
"id": 5, | |||||
"outputModuleId": 2, | |||||
"outputId": 0, | |||||
"inputModuleId": 1, | |||||
"inputId": 0, | |||||
"color": "#0986ad" | |||||
}, | |||||
{ | |||||
"id": 6, | |||||
"outputModuleId": 2, | |||||
"outputId": 0, | |||||
"inputModuleId": 1, | |||||
"inputId": 1, | |||||
"color": "#c9b70e" | |||||
}, | |||||
{ | |||||
"id": 7, | |||||
"outputModuleId": 7, | |||||
"outputId": 0, | |||||
"inputModuleId": 4, | |||||
"inputId": 0, | |||||
"color": "#c91847" | |||||
}, | |||||
{ | |||||
"id": 8, | |||||
"outputModuleId": 7, | |||||
"outputId": 0, | |||||
"inputModuleId": 6, | |||||
"inputId": 0, | |||||
"color": "#0c8e15" | |||||
}, | |||||
{ | |||||
"id": 9, | |||||
"outputModuleId": 5, | |||||
"outputId": 1, | |||||
"inputModuleId": 7, | |||||
"inputId": 4, | |||||
"color": "#c9b70e" | |||||
} | |||||
] | |||||
} |