@@ -42,12 +42,12 @@ struct App { | |||||
history::State *history = NULL; | history::State *history = NULL; | ||||
PatchManager *patch = NULL; | PatchManager *patch = NULL; | ||||
void init(bool headless); | |||||
void init(); | |||||
~App(); | ~App(); | ||||
}; | }; | ||||
void appInit(bool headless); | |||||
void appInit(); | |||||
void appDestroy(); | void appDestroy(); | ||||
/** Returns the global App pointer */ | /** Returns the global App pointer */ | ||||
App *appGet(); | App *appGet(); | ||||
@@ -18,7 +18,6 @@ struct Scene : widget::OpaqueWidget { | |||||
widget::Widget *moduleBrowser; | widget::Widget *moduleBrowser; | ||||
// Version checking | // Version checking | ||||
bool devMode = false; | |||||
bool checkVersion = true; | bool checkVersion = true; | ||||
bool checkedVersion = false; | bool checkedVersion = false; | ||||
std::string latestVersion; | std::string latestVersion; | ||||
@@ -13,7 +13,7 @@ namespace plugin { | |||||
namespace asset { | namespace asset { | ||||
void init(bool devMode); | |||||
void init(); | |||||
/** Returns the path of a system resource. Should only read files from this location. */ | /** Returns the path of a system resource. Should only read files from this location. */ | ||||
std::string system(std::string filename); | std::string system(std::string filename); | ||||
/** Returns the path of a user resource. Can read and write files to this location. */ | /** Returns the path of a user resource. Can read and write files to this location. */ | ||||
@@ -27,7 +27,7 @@ enum Level { | |||||
FATAL_LEVEL | FATAL_LEVEL | ||||
}; | }; | ||||
void init(bool devMode); | |||||
void init(); | |||||
void destroy(); | void destroy(); | ||||
/** Do not use this function directly. Use the macros below. | /** Do not use this function directly. Use the macros below. | ||||
Thread-safe. | Thread-safe. | ||||
@@ -9,6 +9,11 @@ namespace rack { | |||||
struct Settings { | struct Settings { | ||||
/** Runtime state, not serialized. */ | |||||
bool devMode = false; | |||||
bool headless = false; | |||||
/** Persistent state, serialized to settings.json. */ | |||||
std::string token; | std::string token; | ||||
math::Vec windowSize; | math::Vec windowSize; | ||||
math::Vec windowPos; | math::Vec windowPos; | ||||
@@ -31,8 +36,8 @@ struct Settings { | |||||
json_t *toJson(); | json_t *toJson(); | ||||
void fromJson(json_t *rootJ); | void fromJson(json_t *rootJ); | ||||
void save(std::string filename); | |||||
void load(std::string filename); | |||||
void save(const std::string &path); | |||||
void load(const std::string &path); | |||||
}; | }; | ||||
@@ -5,14 +5,15 @@ | |||||
#include "engine/Engine.hpp" | #include "engine/Engine.hpp" | ||||
#include "app/Scene.hpp" | #include "app/Scene.hpp" | ||||
#include "history.hpp" | #include "history.hpp" | ||||
#include "settings.hpp" | |||||
namespace rack { | namespace rack { | ||||
void App::init(bool headless) { | |||||
void App::init() { | |||||
engine = new engine::Engine; | engine = new engine::Engine; | ||||
if (!headless) { | |||||
if (!settings.headless) { | |||||
event = new widget::EventState; | event = new widget::EventState; | ||||
history = new history::State; | history = new history::State; | ||||
window = new Window; | window = new Window; | ||||
@@ -41,10 +42,10 @@ App::~App() { | |||||
static App *appInstance = NULL; | static App *appInstance = NULL; | ||||
void appInit(bool headless) { | |||||
void appInit() { | |||||
assert(!appInstance); | assert(!appInstance); | ||||
appInstance = new App; | appInstance = new App; | ||||
appInstance->init(headless); | |||||
appInstance->init(); | |||||
} | } | ||||
void appDestroy() { | void appDestroy() { | ||||
@@ -47,7 +47,7 @@ void Scene::step() { | |||||
} | } | ||||
// Request latest version from server | // Request latest version from server | ||||
if (!devMode && checkVersion && !checkedVersion) { | |||||
if (!settings.devMode && checkVersion && !checkedVersion) { | |||||
std::thread t(&Scene::runCheckVersion, this); | std::thread t(&Scene::runCheckVersion, this); | ||||
t.detach(); | t.detach(); | ||||
checkedVersion = true; | checkedVersion = true; | ||||
@@ -1,5 +1,6 @@ | |||||
#include "asset.hpp" | #include "asset.hpp" | ||||
#include "system.hpp" | #include "system.hpp" | ||||
#include "settings.hpp" | |||||
#include "plugin/Plugin.hpp" | #include "plugin/Plugin.hpp" | ||||
#if defined ARCH_MAC | #if defined ARCH_MAC | ||||
@@ -24,10 +25,10 @@ namespace rack { | |||||
namespace asset { | namespace asset { | ||||
void init(bool devMode) { | |||||
void init() { | |||||
// Get system dir | // Get system dir | ||||
if (systemDir.empty()) { | if (systemDir.empty()) { | ||||
if (devMode) { | |||||
if (settings.devMode) { | |||||
systemDir = "."; | systemDir = "."; | ||||
} | } | ||||
else { | else { | ||||
@@ -57,7 +58,7 @@ void init(bool devMode) { | |||||
// Get user dir | // Get user dir | ||||
if (userDir.empty()) { | if (userDir.empty()) { | ||||
if (devMode) { | |||||
if (settings.devMode) { | |||||
userDir = "."; | userDir = "."; | ||||
} | } | ||||
else { | else { | ||||
@@ -1,5 +1,6 @@ | |||||
#include "common.hpp" | #include "common.hpp" | ||||
#include "asset.hpp" | #include "asset.hpp" | ||||
#include "settings.hpp" | |||||
#include <chrono> | #include <chrono> | ||||
#include <mutex> | #include <mutex> | ||||
@@ -13,9 +14,9 @@ static std::chrono::high_resolution_clock::time_point startTime; | |||||
static std::mutex logMutex; | static std::mutex logMutex; | ||||
void init(bool devMode) { | |||||
void init() { | |||||
startTime = std::chrono::high_resolution_clock::now(); | startTime = std::chrono::high_resolution_clock::now(); | ||||
if (devMode) { | |||||
if (settings.devMode) { | |||||
outputFile = stderr; | outputFile = stderr; | ||||
} | } | ||||
else { | else { | ||||
@@ -56,8 +56,6 @@ int main(int argc, char *argv[]) { | |||||
(void) instanceMutex; | (void) instanceMutex; | ||||
#endif | #endif | ||||
bool devMode = false; | |||||
bool headless = false; | |||||
std::string patchPath; | std::string patchPath; | ||||
// Parse command line arguments | // Parse command line arguments | ||||
@@ -66,10 +64,10 @@ int main(int argc, char *argv[]) { | |||||
while ((c = getopt(argc, argv, "ds:u:")) != -1) { | while ((c = getopt(argc, argv, "ds:u:")) != -1) { | ||||
switch (c) { | switch (c) { | ||||
case 'd': { | case 'd': { | ||||
devMode = true; | |||||
settings.devMode = true; | |||||
} break; | } break; | ||||
case 'h': { | case 'h': { | ||||
headless = true; | |||||
settings.headless = true; | |||||
} break; | } break; | ||||
case 's': { | case 's': { | ||||
asset::systemDir = optarg; | asset::systemDir = optarg; | ||||
@@ -85,13 +83,13 @@ int main(int argc, char *argv[]) { | |||||
} | } | ||||
// Initialize environment | // Initialize environment | ||||
asset::init(devMode); | |||||
logger::init(devMode); | |||||
asset::init(); | |||||
logger::init(); | |||||
// We can now install a signal handler and log the output | // We can now install a signal handler and log the output | ||||
// Mac has its own decent crash handler | // Mac has its own decent crash handler | ||||
#if 0 | #if 0 | ||||
if (!devMode) { | |||||
if (!settings.devMode) { | |||||
signal(SIGABRT, fatalSignalHandler); | signal(SIGABRT, fatalSignalHandler); | ||||
signal(SIGFPE, fatalSignalHandler); | signal(SIGFPE, fatalSignalHandler); | ||||
signal(SIGILL, fatalSignalHandler); | signal(SIGILL, fatalSignalHandler); | ||||
@@ -102,7 +100,7 @@ int main(int argc, char *argv[]) { | |||||
// Log environment | // Log environment | ||||
INFO("%s v%s", app::APP_NAME, app::APP_VERSION); | INFO("%s v%s", app::APP_NAME, app::APP_VERSION); | ||||
if (devMode) | |||||
if (settings.devMode) | |||||
INFO("Development mode"); | INFO("Development mode"); | ||||
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()); | ||||
@@ -115,7 +113,7 @@ int main(int argc, char *argv[]) { | |||||
keyboard::init(); | keyboard::init(); | ||||
gamepad::init(); | gamepad::init(); | ||||
plugin::init(); | plugin::init(); | ||||
if (!headless) { | |||||
if (!settings.headless) { | |||||
ui::init(); | ui::init(); | ||||
windowInit(); | windowInit(); | ||||
} | } | ||||
@@ -123,22 +121,21 @@ int main(int argc, char *argv[]) { | |||||
// Initialize app | // Initialize app | ||||
INFO("Initializing app"); | INFO("Initializing app"); | ||||
settings.load(asset::user("settings.json")); | settings.load(asset::user("settings.json")); | ||||
appInit(headless); | |||||
appInit(); | |||||
const char *openedFilename = glfwGetOpenedFilename(); | const char *openedFilename = glfwGetOpenedFilename(); | ||||
if (openedFilename) { | if (openedFilename) { | ||||
patchPath = openedFilename; | patchPath = openedFilename; | ||||
} | } | ||||
if (!headless) { | |||||
APP->scene->devMode = devMode; | |||||
if (!settings.headless) { | |||||
APP->patch->init(patchPath); | APP->patch->init(patchPath); | ||||
} | } | ||||
INFO("Starting engine"); | INFO("Starting engine"); | ||||
APP->engine->start(); | APP->engine->start(); | ||||
if (!headless) { | |||||
if (!settings.headless) { | |||||
INFO("Running window"); | INFO("Running window"); | ||||
APP->window->run(); | APP->window->run(); | ||||
INFO("Stopped window"); | INFO("Stopped window"); | ||||
@@ -151,7 +148,7 @@ int main(int argc, char *argv[]) { | |||||
APP->engine->stop(); | APP->engine->stop(); | ||||
// Destroy app | // Destroy app | ||||
if (!headless) { | |||||
if (!settings.headless) { | |||||
APP->patch->save(asset::user("autosave.vcv")); | APP->patch->save(asset::user("autosave.vcv")); | ||||
} | } | ||||
INFO("Destroying app"); | INFO("Destroying app"); | ||||
@@ -160,7 +157,7 @@ int main(int argc, char *argv[]) { | |||||
// Destroy environment | // Destroy environment | ||||
INFO("Destroying environment"); | INFO("Destroying environment"); | ||||
if (!headless) { | |||||
if (!settings.headless) { | |||||
windowDestroy(); | windowDestroy(); | ||||
ui::destroy(); | ui::destroy(); | ||||
} | } | ||||
@@ -356,20 +356,20 @@ void init() { | |||||
plugins.push_back(corePlugin); | plugins.push_back(corePlugin); | ||||
// Get user plugins directory | // Get user plugins directory | ||||
std::string userPlugins = asset::user("plugins"); | |||||
mkdir(userPlugins.c_str(), 0755); | |||||
std::string pluginsDir = asset::user("plugins"); | |||||
mkdir(pluginsDir.c_str(), 0755); | |||||
// Copy Fundamental package to plugins directory if folder does not exist | |||||
// Extract packages and load plugins | |||||
extractPackages(pluginsDir); | |||||
loadPlugins(pluginsDir); | |||||
// Copy Fundamental package to plugins directory if Fundamental is not loaded | |||||
std::string fundamentalSrc = asset::system("Fundamental.zip"); | std::string fundamentalSrc = asset::system("Fundamental.zip"); | ||||
std::string fundamentalDest = asset::user("plugins/Fundamental.zip"); | |||||
std::string fundamentalDir = asset::user("plugins/Fundamental"); | std::string fundamentalDir = asset::user("plugins/Fundamental"); | ||||
if (system::isFile(fundamentalSrc) && !system::isFile(fundamentalDest) && !system::isDirectory(fundamentalDir)) { | |||||
system::copyFile(fundamentalSrc, fundamentalDest); | |||||
if (!settings.devMode && !getPlugin("Fundamental") && system::isFile(fundamentalSrc)) { | |||||
extractZip(fundamentalSrc.c_str(), pluginsDir.c_str()); | |||||
loadPlugin(fundamentalDir); | |||||
} | } | ||||
// Extract packages and load plugins | |||||
extractPackages(userPlugins); | |||||
loadPlugins(userPlugins); | |||||
} | } | ||||
void destroy() { | void destroy() { | ||||
@@ -172,11 +172,11 @@ void Settings::fromJson(json_t *rootJ) { | |||||
} | } | ||||
} | } | ||||
void Settings::save(std::string filename) { | |||||
INFO("Saving settings %s", filename.c_str()); | |||||
void Settings::save(const std::string &path) { | |||||
INFO("Saving settings %s", path.c_str()); | |||||
json_t *rootJ = toJson(); | json_t *rootJ = toJson(); | ||||
if (rootJ) { | if (rootJ) { | ||||
FILE *file = std::fopen(filename.c_str(), "w"); | |||||
FILE *file = std::fopen(path.c_str(), "w"); | |||||
if (!file) | if (!file) | ||||
return; | return; | ||||
@@ -186,9 +186,9 @@ void Settings::save(std::string filename) { | |||||
} | } | ||||
} | } | ||||
void Settings::load(std::string filename) { | |||||
INFO("Loading settings %s", filename.c_str()); | |||||
FILE *file = std::fopen(filename.c_str(), "r"); | |||||
void Settings::load(const std::string &path) { | |||||
INFO("Loading settings %s", path.c_str()); | |||||
FILE *file = std::fopen(path.c_str(), "r"); | |||||
if (!file) | if (!file) | ||||
return; | return; | ||||