@@ -13,6 +13,7 @@ | |||||
// Include some of the C++ stdlib for convenience | // Include some of the C++ stdlib for convenience | ||||
#include <string> | #include <string> | ||||
#include <stdexcept> | |||||
namespace rack { | namespace rack { | ||||
@@ -136,4 +137,10 @@ DeferWrapper<F> deferWrapper(F f) { | |||||
#define DEFER(code) auto CONCAT(_defer_, __COUNTER__) = rack::deferWrapper([&]() code) | #define DEFER(code) auto CONCAT(_defer_, __COUNTER__) = rack::deferWrapper([&]() code) | ||||
/** Reports a string to the user */ | |||||
struct UserException : std::runtime_error { | |||||
UserException(const std::string &msg) : std::runtime_error(msg) {} | |||||
}; | |||||
} // namespace rack | } // namespace rack |
@@ -82,7 +82,6 @@ int main(int argc, char *argv[]) { | |||||
patchPath = argv[optind]; | patchPath = argv[optind]; | ||||
} | } | ||||
// Initialize environment | |||||
asset::init(); | asset::init(); | ||||
logger::init(); | logger::init(); | ||||
@@ -106,6 +105,19 @@ int main(int argc, char *argv[]) { | |||||
INFO("System directory: %s", asset::systemDir.c_str()); | INFO("System directory: %s", asset::systemDir.c_str()); | ||||
INFO("User directory: %s", asset::userDir.c_str()); | INFO("User directory: %s", asset::userDir.c_str()); | ||||
// Load settings | |||||
try { | |||||
settings::load(asset::user("settings.json")); | |||||
} | |||||
catch (UserException &e) { | |||||
std::string msg = e.what(); | |||||
msg += "\n\nReset settings to default?"; | |||||
if (!osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK_CANCEL, msg.c_str())) { | |||||
exit(1); | |||||
} | |||||
} | |||||
// Check existence of the system res/ directory | |||||
std::string resDir = asset::system("res"); | std::string resDir = asset::system("res"); | ||||
if (!system::isDirectory(resDir)) { | if (!system::isDirectory(resDir)) { | ||||
std::string message = string::f("Rack's resource directory \"%s\" does not exist. Make sure Rack is correctly installed and launched.", resDir.c_str()); | std::string message = string::f("Rack's resource directory \"%s\" does not exist. Make sure Rack is correctly installed and launched.", resDir.c_str()); | ||||
@@ -128,7 +140,6 @@ int main(int argc, char *argv[]) { | |||||
// Initialize app | // Initialize app | ||||
INFO("Initializing app"); | INFO("Initializing app"); | ||||
settings::load(asset::user("settings.json")); | |||||
appInit(); | appInit(); | ||||
const char *openedFilename = glfwGetOpenedFilename(); | const char *openedFilename = glfwGetOpenedFilename(); | ||||
@@ -230,34 +230,36 @@ void fromJson(json_t *rootJ) { | |||||
void save(const std::string &path) { | void save(const std::string &path) { | ||||
INFO("Saving settings %s", path.c_str()); | INFO("Saving settings %s", path.c_str()); | ||||
json_t *rootJ = toJson(); | json_t *rootJ = toJson(); | ||||
if (rootJ) { | |||||
FILE *file = std::fopen(path.c_str(), "w"); | |||||
if (!file) | |||||
return; | |||||
json_dumpf(rootJ, file, JSON_INDENT(2) | JSON_REAL_PRECISION(9)); | |||||
json_decref(rootJ); | |||||
std::fclose(file); | |||||
} | |||||
if (!rootJ) | |||||
return; | |||||
FILE *file = fopen(path.c_str(), "w"); | |||||
if (!file) | |||||
return; | |||||
DEFER({ | |||||
fclose(file); | |||||
}); | |||||
json_dumpf(rootJ, file, JSON_INDENT(2) | JSON_REAL_PRECISION(9)); | |||||
json_decref(rootJ); | |||||
} | } | ||||
void load(const std::string &path) { | void load(const std::string &path) { | ||||
INFO("Loading settings %s", path.c_str()); | INFO("Loading settings %s", path.c_str()); | ||||
FILE *file = std::fopen(path.c_str(), "r"); | |||||
FILE *file = fopen(path.c_str(), "r"); | |||||
if (!file) | if (!file) | ||||
return; | |||||
throw UserException(string::f("Could not load settings file %s", path.c_str())); | |||||
DEFER({ | |||||
fclose(file); | |||||
}); | |||||
json_error_t error; | json_error_t error; | ||||
json_t *rootJ = json_loadf(file, 0, &error); | json_t *rootJ = json_loadf(file, 0, &error); | ||||
if (rootJ) { | |||||
fromJson(rootJ); | |||||
json_decref(rootJ); | |||||
} | |||||
else { | |||||
WARN("JSON parsing error at %s %d:%d %s", error.source, error.line, error.column, error.text); | |||||
} | |||||
if (!rootJ) | |||||
throw UserException(string::f("Settings file has invalid JSON at %d:%d %s", error.line, error.column, error.text)); | |||||
std::fclose(file); | |||||
fromJson(rootJ); | |||||
json_decref(rootJ); | |||||
} | } | ||||