diff --git a/include/patch.hpp b/include/patch.hpp index bfa1c93d..c723127f 100644 --- a/include/patch.hpp +++ b/include/patch.hpp @@ -13,6 +13,8 @@ struct PatchManager { int legacy; std::string warningLog; + PatchManager(); + ~PatchManager(); void init(std::string path); void reset(); void resetDialog(); diff --git a/include/plugin.hpp b/include/plugin.hpp index eb185037..f0cca6e4 100644 --- a/include/plugin.hpp +++ b/include/plugin.hpp @@ -26,7 +26,6 @@ bool isSlugValid(std::string slug); extern std::list plugins; -extern std::string token; extern bool isDownloading; extern float downloadProgress; extern std::string downloadName; diff --git a/include/settings.hpp b/include/settings.hpp index 3ef100e4..4816f2ea 100644 --- a/include/settings.hpp +++ b/include/settings.hpp @@ -1,26 +1,39 @@ #pragma once #include "common.hpp" +#include "math.hpp" +#include namespace rack { -namespace settings { -void save(std::string filename); -void load(std::string filename); +struct Settings { + std::string token; + math::Vec windowSize; + math::Vec windowPos; + float zoom = 1.0; + float cableOpacity = 0.5; + float cableTension = 0.5; + bool allowCursorLock = true; + float sampleRate = 44100.0; + int threadCount = 1; + bool paramTooltip = false; + bool cpuMeter = false; + bool lockModules = false; + bool checkVersion = true; + float frameRateLimit = 0.0; + bool frameRateSync = true; + bool skipLoadOnLaunch = false; + std::string patchPath; + json_t *toJson(); + void fromJson(json_t *rootJ); + void save(std::string filename); + void load(std::string filename); +}; -extern float zoom; -extern float cableOpacity; -extern float cableTension; -extern bool paramTooltip; -extern bool powerMeter; -extern bool lockModules; -extern bool checkVersion; -extern bool skipLoadOnLaunch; -extern float frameRateLimit; -extern bool frameRateSync; + +extern Settings settings; -} // namespace settings } // namespace rack diff --git a/include/window.hpp b/include/window.hpp index d0c05e95..139661c8 100644 --- a/include/window.hpp +++ b/include/window.hpp @@ -71,7 +71,6 @@ struct Window { This is not equal to gPixelRatio in general. */ float windowRatio = 1.f; - bool allowCursorLock = true; int frame = 0; /** The last known absolute mouse position in the window */ math::Vec mousePos; @@ -90,11 +89,6 @@ struct Window { Don't call this from a Key event. Simply use `e.mods` instead. */ int getMods(); - math::Vec getWindowSize(); - void setWindowSize(math::Vec size); - math::Vec getWindowPos(); - void setWindowPos(math::Vec pos); - bool isMaximized(); void setFullScreen(bool fullScreen); bool isFullScreen(); }; diff --git a/src/app/CableWidget.cpp b/src/app/CableWidget.cpp index f7ee94fd..5f4fd39c 100644 --- a/src/app/CableWidget.cpp +++ b/src/app/CableWidget.cpp @@ -207,8 +207,8 @@ void CableWidget::fromJson(json_t *rootJ, const std::map &mo } void CableWidget::draw(const widget::DrawContext &ctx) { - float opacity = settings::cableOpacity; - float tension = settings::cableTension; + float opacity = settings.cableOpacity; + float tension = settings.cableTension; float thickness = 5; if (isComplete()) { diff --git a/src/app/ModuleWidget.cpp b/src/app/ModuleWidget.cpp index 4c47f9fe..a3e0af85 100644 --- a/src/app/ModuleWidget.cpp +++ b/src/app/ModuleWidget.cpp @@ -145,7 +145,7 @@ void ModuleWidget::draw(const widget::DrawContext &ctx) { widget::Widget::draw(ctx); // Power meter - if (module && settings::powerMeter) { + if (module && settings.cpuMeter) { nvgBeginPath(ctx.vg); nvgRect(ctx.vg, 0, box.size.y - 20, @@ -285,7 +285,7 @@ void ModuleWidget::onDragEnd(const event::DragEnd &e) { } void ModuleWidget::onDragMove(const event::DragMove &e) { - if (!settings::lockModules) { + if (!settings.lockModules) { math::Rect newBox = box; newBox.pos = APP->scene->rackWidget->mousePos.minus(dragPos); APP->scene->rackWidget->requestModuleBoxNearest(this, newBox); diff --git a/src/app/ParamWidget.cpp b/src/app/ParamWidget.cpp index ade459f4..cde34c6e 100644 --- a/src/app/ParamWidget.cpp +++ b/src/app/ParamWidget.cpp @@ -158,7 +158,7 @@ void ParamWidget::onDoubleClick(const event::DoubleClick &e) { } void ParamWidget::onEnter(const event::Enter &e) { - if (settings::paramTooltip && !tooltip && paramQuantity) { + if (settings.paramTooltip && !tooltip && paramQuantity) { ParamTooltip *paramTooltip = new ParamTooltip; paramTooltip->paramWidget = this; APP->scene->addChild(paramTooltip); diff --git a/src/app/Scene.cpp b/src/app/Scene.cpp index 88f437c1..6cc84b66 100644 --- a/src/app/Scene.cpp +++ b/src/app/Scene.cpp @@ -59,12 +59,12 @@ void Scene::step() { int frame = APP->window->frame; if (frame > 0 && frame % (60 * 15) == 0) { APP->patch->save(asset::user("autosave.vcv")); - settings::save(asset::user("settings.json")); + settings.save(asset::user("settings.json")); } // Set zoom every few frames if (APP->window->frame % 10 == 0) - zoomWidget->setZoom(std::round(settings::zoom * 100) / 100); + zoomWidget->setZoom(std::round(settings.zoom * 100) / 100); // Request latest version from server if (!devMode && checkVersion && !checkedVersion) { diff --git a/src/app/Toolbar.cpp b/src/app/Toolbar.cpp index 90057958..921b1c90 100644 --- a/src/app/Toolbar.cpp +++ b/src/app/Toolbar.cpp @@ -180,10 +180,10 @@ struct EditButton : MenuButton { struct ZoomQuantity : ui::Quantity { void setValue(float value) override { - settings::zoom = math::clamp(value, getMinValue(), getMaxValue()); + settings.zoom = math::clamp(value, getMinValue(), getMaxValue()); } float getValue() override { - return settings::zoom; + return settings.zoom; } float getMinValue() override {return 0.25;} float getMaxValue() override {return 2.0;} @@ -197,10 +197,10 @@ struct ZoomQuantity : ui::Quantity { struct CableOpacityQuantity : ui::Quantity { void setValue(float value) override { - settings::cableOpacity = math::clamp(value, getMinValue(), getMaxValue()); + settings.cableOpacity = math::clamp(value, getMinValue(), getMaxValue()); } float getValue() override { - return settings::cableOpacity; + return settings.cableOpacity; } float getDefaultValue() override {return 0.5;} float getDisplayValue() override {return getValue() * 100;} @@ -213,10 +213,10 @@ struct CableOpacityQuantity : ui::Quantity { struct CableTensionQuantity : ui::Quantity { void setValue(float value) override { - settings::cableTension = math::clamp(value, getMinValue(), getMaxValue()); + settings.cableTension = math::clamp(value, getMinValue(), getMaxValue()); } float getValue() override { - return settings::cableTension; + return settings.cableTension; } float getDefaultValue() override {return 0.5;} std::string getLabel() override {return "Cable tension";} @@ -224,13 +224,13 @@ struct CableTensionQuantity : ui::Quantity { }; -struct PowerMeterItem : ui::MenuItem { - PowerMeterItem() { +struct CpuMeterItem : ui::MenuItem { + CpuMeterItem() { text = "CPU meter"; - rightText = CHECKMARK(settings::powerMeter); + rightText = CHECKMARK(settings.cpuMeter); } void onAction(const event::Action &e) override { - settings::powerMeter ^= true; + settings.cpuMeter ^= true; } }; @@ -238,10 +238,10 @@ struct PowerMeterItem : ui::MenuItem { struct ParamTooltipItem : ui::MenuItem { ParamTooltipItem() { text = "Parameter tooltips"; - rightText = CHECKMARK(settings::paramTooltip); + rightText = CHECKMARK(settings.paramTooltip); } void onAction(const event::Action &e) override { - settings::paramTooltip ^= true; + settings.paramTooltip ^= true; } }; @@ -249,10 +249,10 @@ struct ParamTooltipItem : ui::MenuItem { struct LockModulesItem : ui::MenuItem { LockModulesItem() { text = "Lock modules"; - rightText = CHECKMARK(settings::lockModules); + rightText = CHECKMARK(settings.lockModules); } void onAction(const event::Action &e) override { - settings::lockModules ^= true; + settings.lockModules ^= true; } }; @@ -369,7 +369,7 @@ struct SettingsButton : MenuButton { menu->box.size.x = box.size.x; menu->addChild(new ParamTooltipItem); - menu->addChild(new PowerMeterItem); + menu->addChild(new CpuMeterItem); menu->addChild(new LockModulesItem); menu->addChild(new SampleRateItem); menu->addChild(new ThreadCount); @@ -627,10 +627,10 @@ struct WebsiteItem : ui::MenuItem { struct CheckVersionItem : ui::MenuItem { CheckVersionItem() { text = "Check version on launch"; - rightText = CHECKMARK(settings::checkVersion); + rightText = CHECKMARK(settings.checkVersion); } void onAction(const event::Action &e) override { - settings::checkVersion ^= true; + settings.checkVersion ^= true; } }; diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index 8e4739fe..ff0d975e 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -155,16 +155,20 @@ struct Engine::Internal { Engine::Engine() { internal = new Internal; - float sampleRate = 44100.f; + float sampleRate = settings.sampleRate; internal->sampleRate = sampleRate; internal->sampleTime = 1 / sampleRate; internal->sampleRateRequested = sampleRate; + internal->threadCount = settings.threadCount; internal->engineBarrier.total = 1; internal->workerBarrier.total = 1; } Engine::~Engine() { + settings.sampleRate = internal->sampleRate; + settings.threadCount = internal->threadCount; + // Make sure there are no cables or modules in the rack on destruction. This suggests that a module failed to remove itself before the RackWidget was destroyed. assert(internal->cables.empty()); assert(internal->modules.empty()); @@ -173,6 +177,7 @@ Engine::~Engine() { } static void Engine_setWorkerCount(Engine *engine, int workerCount) { + assert(0 <= workerCount && workerCount <= 32); Engine::Internal *internal = engine->internal; // Stop all workers @@ -213,7 +218,7 @@ static void Engine_stepModules(Engine *engine, int id) { Module *module = internal->modules[i]; if (!module->bypass) { // Step module - if (settings::powerMeter) { + if (settings.cpuMeter) { auto startTime = std::chrono::high_resolution_clock::now(); module->step(); diff --git a/src/main.cpp b/src/main.cpp index 6d41a767..bc0620e3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -83,9 +83,9 @@ int main(int argc, char *argv[]) { INFO("Initialized environment"); // Initialize app + settings.load(asset::user("settings.json")); app::init(); APP->scene->devMode = devMode; - settings::load(asset::user("settings.json")); APP->patch->init(patchPath); INFO("Initialized app"); @@ -97,8 +97,8 @@ int main(int argc, char *argv[]) { // Destroy app APP->patch->save(asset::user("autosave.vcv")); - settings::save(asset::user("settings.json")); app::destroy(); + settings.save(asset::user("settings.json")); INFO("Cleaned up app"); // Destroy environment diff --git a/src/patch.cpp b/src/patch.cpp index b2816c1d..d1076d6c 100644 --- a/src/patch.cpp +++ b/src/patch.cpp @@ -16,6 +16,14 @@ namespace rack { static const char PATCH_FILTERS[] = "VCV Rack patch (.vcv):vcv"; +PatchManager::PatchManager() { + path = settings.patchPath; +} + +PatchManager::~PatchManager() { + settings.patchPath = path; +} + void PatchManager::init(std::string path) { if (!path.empty()) { // Load patch @@ -25,10 +33,10 @@ void PatchManager::init(std::string path) { } // 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; + 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; diff --git a/src/plugin.cpp b/src/plugin.cpp index 1cdc847c..e11f6e9a 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -6,6 +6,7 @@ #include "app.hpp" #include "app/common.hpp" #include "plugin/callbacks.hpp" +#include "settings.hpp" #include #include @@ -184,7 +185,7 @@ static bool syncPlugin(std::string slug, json_t *manifestJ, bool dryRun) { if (dryRun) { downloadUrl += "/available"; } - downloadUrl += "?token=" + network::encodeUrl(token); + downloadUrl += "?token=" + network::encodeUrl(settings.token); downloadUrl += "&slug=" + network::encodeUrl(slug); downloadUrl += "&version=" + network::encodeUrl(latestVersion); downloadUrl += "&arch=" + network::encodeUrl(arch); @@ -393,7 +394,7 @@ void logIn(std::string email, std::string password) { json_t *tokenJ = json_object_get(resJ, "token"); if (tokenJ) { const char *tokenStr = json_string_value(tokenJ); - token = tokenStr; + settings.token = tokenStr; loginStatus = ""; } } @@ -402,11 +403,11 @@ void logIn(std::string email, std::string password) { } void logOut() { - token = ""; + settings.token = ""; } bool sync(bool dryRun) { - if (token.empty()) + if (settings.token.empty()) return false; bool available = false; @@ -422,7 +423,7 @@ bool sync(bool dryRun) { // Get user's plugins list json_t *pluginsReqJ = json_object(); - json_object_set(pluginsReqJ, "token", json_string(token.c_str())); + json_object_set(pluginsReqJ, "token", json_string(settings.token.c_str())); std::string pluginsUrl = app::API_URL; pluginsUrl += "/plugins"; json_t *pluginsResJ = network::requestJson(network::METHOD_GET, pluginsUrl, pluginsReqJ); @@ -493,7 +494,7 @@ void cancelDownload() { } bool isLoggedIn() { - return token != ""; + return settings.token != ""; } Plugin *getPlugin(std::string pluginSlug) { @@ -534,7 +535,6 @@ bool isSlugValid(std::string slug) { std::list plugins; -std::string token; bool isDownloading = false; float downloadProgress = 0.f; std::string downloadName; diff --git a/src/settings.cpp b/src/settings.cpp index 0de45f74..d37cc0c4 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -10,181 +10,137 @@ namespace rack { -namespace settings { -static json_t *settingsToJson() { - // root +json_t *Settings::toJson() { json_t *rootJ = json_object(); - // token - json_t *tokenJ = json_string(plugin::token.c_str()); - json_object_set_new(rootJ, "token", tokenJ); + json_object_set_new(rootJ, "token", json_string(token.c_str())); - if (!APP->window->isMaximized()) { - // windowSize - math::Vec windowSize = APP->window->getWindowSize(); - json_t *windowSizeJ = json_pack("[f, f]", windowSize.x, windowSize.y); - json_object_set_new(rootJ, "windowSize", windowSizeJ); + json_t *windowSizeJ = json_pack("[f, f]", windowSize.x, windowSize.y); + json_object_set_new(rootJ, "windowSize", windowSizeJ); - // windowPos - math::Vec windowPos = APP->window->getWindowPos(); - json_t *windowPosJ = json_pack("[f, f]", windowPos.x, windowPos.y); - json_object_set_new(rootJ, "windowPos", windowPosJ); - } - - // cableOpacity - json_t *cableOpacityJ = json_real(cableOpacity); - json_object_set_new(rootJ, "cableOpacity", cableOpacityJ); + json_t *windowPosJ = json_pack("[f, f]", windowPos.x, windowPos.y); + json_object_set_new(rootJ, "windowPos", windowPosJ); - // cableTension - json_t *cableTensionJ = json_real(cableTension); - json_object_set_new(rootJ, "cableTension", cableTensionJ); + json_object_set_new(rootJ, "zoom", json_real(zoom)); - // zoom - json_t *zoomJ = json_real(zoom); - json_object_set_new(rootJ, "zoom", zoomJ); + json_object_set_new(rootJ, "cableOpacity", json_real(cableOpacity)); - // allowCursorLock - json_t *allowCursorLockJ = json_boolean(APP->window->allowCursorLock); - json_object_set_new(rootJ, "allowCursorLock", allowCursorLockJ); + json_object_set_new(rootJ, "cableTension", json_real(cableTension)); - // sampleRate - json_t *sampleRateJ = json_real(APP->engine->getSampleRate()); - json_object_set_new(rootJ, "sampleRate", sampleRateJ); + json_object_set_new(rootJ, "allowCursorLock", json_boolean(allowCursorLock)); - // patchPath - json_t *patchPathJ = json_string(APP->patch->path.c_str()); - json_object_set_new(rootJ, "patchPath", patchPathJ); + json_object_set_new(rootJ, "sampleRate", json_real(sampleRate)); - // skipLoadOnLaunch - if (skipLoadOnLaunch) { - json_object_set_new(rootJ, "skipLoadOnLaunch", json_true()); - } + json_object_set_new(rootJ, "threadCount", json_integer(threadCount)); - // moduleBrowser - json_object_set_new(rootJ, "moduleBrowser", app::moduleBrowserToJson()); + json_object_set_new(rootJ, "paramTooltip", json_boolean(paramTooltip)); - // powerMeter - json_object_set_new(rootJ, "powerMeter", json_boolean(powerMeter)); + json_object_set_new(rootJ, "cpuMeter", json_boolean(cpuMeter)); - // threadCount - json_object_set_new(rootJ, "threadCount", json_integer(APP->engine->getThreadCount())); + json_object_set_new(rootJ, "lockModules", json_boolean(lockModules)); - // checkVersion json_object_set_new(rootJ, "checkVersion", json_boolean(checkVersion)); - // paramTooltip - json_object_set_new(rootJ, "paramTooltip", json_boolean(paramTooltip)); - - // frameRateLimit json_object_set_new(rootJ, "frameRateLimit", json_real(frameRateLimit)); - // frameRateSync json_object_set_new(rootJ, "frameRateSync", json_boolean(frameRateSync)); + if (skipLoadOnLaunch) { + json_object_set_new(rootJ, "skipLoadOnLaunch", json_true()); + } + + json_object_set_new(rootJ, "patchPath", json_string(patchPath.c_str())); + + json_object_set_new(rootJ, "moduleBrowser", app::moduleBrowserToJson()); + return rootJ; } -static void settingsFromJson(json_t *rootJ) { - // token +void Settings::fromJson(json_t *rootJ) { json_t *tokenJ = json_object_get(rootJ, "token"); if (tokenJ) - plugin::token = json_string_value(tokenJ); + token = json_string_value(tokenJ); - // windowSize json_t *windowSizeJ = json_object_get(rootJ, "windowSize"); if (windowSizeJ) { - double width, height; - json_unpack(windowSizeJ, "[F, F]", &width, &height); - APP->window->setWindowSize(math::Vec(width, height)); + double x, y; + json_unpack(windowSizeJ, "[F, F]", &x, &y); + windowSize = math::Vec(x, y); } - // windowPos json_t *windowPosJ = json_object_get(rootJ, "windowPos"); if (windowPosJ) { double x, y; json_unpack(windowPosJ, "[F, F]", &x, &y); - APP->window->setWindowPos(math::Vec(x, y)); + windowPos = math::Vec(x, y); } - // cableOpacity + json_t *zoomJ = json_object_get(rootJ, "zoom"); + if (zoomJ) + zoom = json_number_value(zoomJ); + json_t *cableOpacityJ = json_object_get(rootJ, "cableOpacity"); if (cableOpacityJ) cableOpacity = json_number_value(cableOpacityJ); - // tension json_t *tensionJ = json_object_get(rootJ, "cableTension"); if (tensionJ) cableTension = json_number_value(tensionJ); - // zoom - json_t *zoomJ = json_object_get(rootJ, "zoom"); - if (zoomJ) - zoom = json_number_value(zoomJ); - - // allowCursorLock json_t *allowCursorLockJ = json_object_get(rootJ, "allowCursorLock"); if (allowCursorLockJ) - APP->window->allowCursorLock = json_is_true(allowCursorLockJ); + allowCursorLock = json_is_true(allowCursorLockJ); - // sampleRate json_t *sampleRateJ = json_object_get(rootJ, "sampleRate"); - if (sampleRateJ) { - float sampleRate = json_number_value(sampleRateJ); - APP->engine->setSampleRate(sampleRate); - } - - // patchPath - json_t *patchPathJ = json_object_get(rootJ, "patchPath"); - if (patchPathJ) - APP->patch->path = json_string_value(patchPathJ); + if (sampleRateJ) + sampleRate = json_number_value(sampleRateJ); - // skipLoadOnLaunch - json_t *skipLoadOnLaunchJ = json_object_get(rootJ, "skipLoadOnLaunch"); - if (skipLoadOnLaunchJ) - skipLoadOnLaunch = json_boolean_value(skipLoadOnLaunchJ); + json_t *threadCountJ = json_object_get(rootJ, "threadCount"); + if (threadCountJ) + threadCount = json_integer_value(threadCountJ); - // moduleBrowser - json_t *moduleBrowserJ = json_object_get(rootJ, "moduleBrowser"); - if (moduleBrowserJ) - app::moduleBrowserFromJson(moduleBrowserJ); + json_t *paramTooltipJ = json_object_get(rootJ, "paramTooltip"); + if (paramTooltipJ) + paramTooltip = json_boolean_value(paramTooltipJ); - // powerMeter - json_t *powerMeterJ = json_object_get(rootJ, "powerMeter"); - if (powerMeterJ) - powerMeter = json_boolean_value(powerMeterJ); + json_t *cpuMeterJ = json_object_get(rootJ, "cpuMeter"); + if (cpuMeterJ) + cpuMeter = json_boolean_value(cpuMeterJ); - // threadCount - json_t *threadCountJ = json_object_get(rootJ, "threadCount"); - if (threadCountJ) - APP->engine->setThreadCount(json_integer_value(threadCountJ)); + json_t *lockModulesJ = json_object_get(rootJ, "lockModules"); + if (lockModulesJ) + lockModules = json_boolean_value(lockModulesJ); - // checkVersion json_t *checkVersionJ = json_object_get(rootJ, "checkVersion"); if (checkVersionJ) checkVersion = json_boolean_value(checkVersionJ); - // paramTooltip - json_t *paramTooltipJ = json_object_get(rootJ, "paramTooltip"); - if (paramTooltipJ) - paramTooltip = json_boolean_value(paramTooltipJ); - - // frameRateLimit json_t *frameRateLimitJ = json_object_get(rootJ, "frameRateLimit"); if (frameRateLimitJ) frameRateLimit = json_number_value(frameRateLimitJ); - // frameRateSync json_t *frameRateSyncJ = json_object_get(rootJ, "frameRateSync"); if (frameRateSyncJ) frameRateSync = json_boolean_value(frameRateSyncJ); -} + json_t *skipLoadOnLaunchJ = json_object_get(rootJ, "skipLoadOnLaunch"); + if (skipLoadOnLaunchJ) + skipLoadOnLaunch = json_boolean_value(skipLoadOnLaunchJ); + + json_t *patchPathJ = json_object_get(rootJ, "patchPath"); + if (patchPathJ) + patchPath = json_string_value(patchPathJ); + + json_t *moduleBrowserJ = json_object_get(rootJ, "moduleBrowser"); + if (moduleBrowserJ) + app::moduleBrowserFromJson(moduleBrowserJ); +} -void save(std::string filename) { +void Settings::save(std::string filename) { INFO("Saving settings %s", filename.c_str()); - json_t *rootJ = settingsToJson(); + json_t *rootJ = toJson(); if (rootJ) { FILE *file = fopen(filename.c_str(), "w"); if (!file) @@ -196,7 +152,7 @@ void save(std::string filename) { } } -void load(std::string filename) { +void Settings::load(std::string filename) { INFO("Loading settings %s", filename.c_str()); FILE *file = fopen(filename.c_str(), "r"); if (!file) @@ -205,7 +161,7 @@ void load(std::string filename) { json_error_t error; json_t *rootJ = json_loadf(file, 0, &error); if (rootJ) { - settingsFromJson(rootJ); + fromJson(rootJ); json_decref(rootJ); } else { @@ -216,17 +172,7 @@ void load(std::string filename) { } -float zoom = 1.0; -float cableOpacity = 0.5; -float cableTension = 0.5; -bool paramTooltip = false; -bool powerMeter = false; -bool lockModules = false; -bool checkVersion = true; -bool skipLoadOnLaunch = false; -float frameRateLimit = 0.0; -bool frameRateSync = true; +Settings settings; -} // namespace settings } // namespace rack diff --git a/src/window.cpp b/src/window.cpp index 207689fd..e6eca447 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -12,7 +12,7 @@ #include #include -#ifdef ARCH_MAC +#if defined ARCH_MAC // For CGAssociateMouseAndMouseCursorPosition #include #endif @@ -109,7 +109,7 @@ static void windowSizeCallback(GLFWwindow *win, int width, int height) { static void mouseButtonCallback(GLFWwindow *win, int button, int action, int mods) { Window *window = (Window*) glfwGetWindowUserPointer(win); -#ifdef ARCH_MAC +#if defined ARCH_MAC // Remap Ctrl-left click to right click on Mac if (button == GLFW_MOUSE_BUTTON_LEFT) { if (mods & GLFW_MOD_CONTROL) { @@ -130,7 +130,7 @@ static void cursorPosCallback(GLFWwindow *win, double xpos, double ypos) { int cursorMode = glfwGetInputMode(win, GLFW_CURSOR); (void) cursorMode; -#ifdef ARCH_MAC +#if defined ARCH_MAC // Workaround for Mac. We can't use GLFW_CURSOR_DISABLED because it's buggy, so implement it on our own. // This is not an ideal implementation. For example, if the user drags off the screen, the new mouse position will be clamped. if (cursorMode == GLFW_CURSOR_HIDDEN) { @@ -223,7 +223,7 @@ Window::Window() { glfwMakeContextCurrent(win); // Enable v-sync - glfwSwapInterval(settings::frameRateSync ? 1 : 0); + glfwSwapInterval(settings.frameRateSync ? 1 : 0); glfwSetWindowSizeCallback(win, windowSizeCallback); glfwSetMouseButtonCallback(win, mouseButtonCallback); @@ -253,6 +253,14 @@ Window::Window() { glfwSetWindowSizeLimits(win, 800, 600, GLFW_DONT_CARE, GLFW_DONT_CARE); + if (settings.windowSize.isZero()) { + glfwMaximizeWindow(win); + } + else { + glfwSetWindowSize(win, settings.windowSize.x, settings.windowSize.y); + glfwSetWindowPos(win, settings.windowPos.x, settings.windowPos.y); + } + // Set up NanoVG int nvgFlags = NVG_ANTIALIAS; #if defined NANOVG_GL2 @@ -275,6 +283,19 @@ Window::Window() { } Window::~Window() { + if (glfwGetWindowAttrib(win, GLFW_MAXIMIZED)) { + settings.windowSize = math::Vec(); + settings.windowPos = math::Vec(); + } + else { + int winWidth, winHeight; + glfwGetWindowSize(win, &winWidth, &winHeight); + int winX, winY; + glfwGetWindowPos(win, &winX, &winY); + settings.windowSize = math::Vec(winWidth, winHeight); + settings.windowPos = math::Vec(winX, winY); + } + #if defined NANOVG_GL2 nvgDeleteGL2(vg); #elif defined NANOVG_GL3 @@ -375,9 +396,9 @@ void Window::run() { // Limit frame rate double endTime = glfwGetTime(); - if (settings::frameRateLimit > 0.0) { + if (settings.frameRateLimit > 0.0) { double frameDuration = endTime - startTime; - double waitDuration = 1.0 / settings::frameRateLimit - frameDuration; + double waitDuration = 1.0 / settings.frameRateLimit - frameDuration; if (waitDuration > 0.0) { std::this_thread::sleep_for(std::chrono::duration(waitDuration)); } @@ -394,8 +415,8 @@ void Window::close() { } void Window::cursorLock() { - if (allowCursorLock) { -#ifdef ARCH_MAC + if (settings.allowCursorLock) { +#if defined ARCH_MAC glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); #else glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_DISABLED); @@ -404,7 +425,7 @@ void Window::cursorLock() { } void Window::cursorUnlock() { - if (allowCursorLock) { + if (settings.allowCursorLock) { glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_NORMAL); } } @@ -422,34 +443,6 @@ int Window::getMods() { return mods; } -math::Vec Window::getWindowSize() { - int width, height; - glfwGetWindowSize(win, &width, &height); - return math::Vec(width, height); -} - -void Window::setWindowSize(math::Vec size) { - int width = size.x; - int height = size.y; - glfwSetWindowSize(win, width, height); -} - -math::Vec Window::getWindowPos() { - int x, y; - glfwGetWindowPos(win, &x, &y); - return math::Vec(x, y); -} - -void Window::setWindowPos(math::Vec pos) { - int x = pos.x; - int y = pos.y; - glfwSetWindowPos(win, x, y); -} - -bool Window::isMaximized() { - return glfwGetWindowAttrib(win, GLFW_MAXIMIZED); -} - void Window::setFullScreen(bool fullScreen) { if (isFullScreen()) { glfwSetWindowMonitor(win, NULL, internal->lastWindowX, internal->lastWindowY, internal->lastWindowWidth, internal->lastWindowHeight, GLFW_DONT_CARE);