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