modepull/1639/head
| @@ -5,10 +5,6 @@ FLAGS += \ | |||||
| -Iinclude \ | -Iinclude \ | ||||
| -Idep/include -Idep/lib/libzip/include | -Idep/include -Idep/lib/libzip/include | ||||
| ifdef RELEASE | |||||
| FLAGS += -DRELEASE | |||||
| endif | |||||
| include arch.mk | include arch.mk | ||||
| STRIP ?= strip | STRIP ?= strip | ||||
| @@ -58,22 +54,25 @@ dep: | |||||
| $(MAKE) -C dep | $(MAKE) -C dep | ||||
| run: $(TARGET) | run: $(TARGET) | ||||
| ./$< -d | |||||
| runr: $(TARGET) | |||||
| ./$< | ./$< | ||||
| debug: $(TARGET) | debug: $(TARGET) | ||||
| ifdef ARCH_MAC | ifdef ARCH_MAC | ||||
| lldb -ex run ./$< | |||||
| lldb -ex run ./$< -d | |||||
| endif | endif | ||||
| ifdef ARCH_WIN | ifdef ARCH_WIN | ||||
| gdb -ex run ./$< | |||||
| gdb -ex run ./$< -d | |||||
| endif | endif | ||||
| ifdef ARCH_LIN | ifdef ARCH_LIN | ||||
| gdb -ex run ./$< | |||||
| gdb -ex run ./$< -d | |||||
| endif | endif | ||||
| perf: $(TARGET) | perf: $(TARGET) | ||||
| ifdef ARCH_LIN | ifdef ARCH_LIN | ||||
| perf record --call-graph dwarf ./$< | |||||
| perf record --call-graph dwarf ./$< -d | |||||
| endif | endif | ||||
| clean: | clean: | ||||
| @@ -88,9 +87,6 @@ endif | |||||
| # This target is not intended for public use | # This target is not intended for public use | ||||
| dist: all | dist: all | ||||
| ifndef RELEASE | |||||
| exit 1 # Must enable RELEASE for dist target | |||||
| endif | |||||
| rm -rf dist | rm -rf dist | ||||
| # Rack distribution | # Rack distribution | ||||
| $(MAKE) -C plugins/Fundamental dist | $(MAKE) -C plugins/Fundamental dist | ||||
| @@ -7,6 +7,7 @@ | |||||
| namespace rack { | namespace rack { | ||||
| void assetInit(bool devMode); | |||||
| /** Returns the path of a global resource. Should only read files from this location. */ | /** Returns the path of a global resource. Should only read files from this location. */ | ||||
| std::string assetGlobal(std::string filename); | std::string assetGlobal(std::string filename); | ||||
| /** Returns the path of a local resource. Can read and write files to this location. */ | /** Returns the path of a local resource. Can read and write files to this location. */ | ||||
| @@ -95,7 +95,7 @@ struct Model { | |||||
| }; | }; | ||||
| void pluginInit(); | |||||
| void pluginInit(bool devMode); | |||||
| void pluginDestroy(); | void pluginDestroy(); | ||||
| void pluginLogIn(std::string email, std::string password); | void pluginLogIn(std::string email, std::string password); | ||||
| void pluginLogOut(); | void pluginLogOut(); | ||||
| @@ -175,7 +175,7 @@ enum LoggerLevel { | |||||
| FATAL_LEVEL | FATAL_LEVEL | ||||
| }; | }; | ||||
| void loggerInit(); | |||||
| void loggerInit(bool devMode); | |||||
| void loggerDestroy(); | void loggerDestroy(); | ||||
| /** Do not use this function directly. Use the macros below. */ | /** Do not use this function directly. Use the macros below. */ | ||||
| void loggerLog(LoggerLevel level, const char *file, int line, const char *format, ...); | void loggerLog(LoggerLevel level, const char *file, int line, const char *format, ...); | ||||
| @@ -209,10 +209,11 @@ Toolbar::Toolbar() { | |||||
| layout->addChild(cpuUsageButton); | layout->addChild(cpuUsageButton); | ||||
| */ | */ | ||||
| #if defined(RELEASE) | |||||
| Widget *pluginManager = new PluginManagerWidget(); | |||||
| layout->addChild(pluginManager); | |||||
| #endif | |||||
| // Kind of hacky, but display the PluginManagerWidget only if the local directory is not the development directory | |||||
| if (assetLocal("") != "./") { | |||||
| Widget *pluginManager = new PluginManagerWidget(); | |||||
| layout->addChild(pluginManager); | |||||
| } | |||||
| } | } | ||||
| void Toolbar::draw(NVGcontext *vg) { | void Toolbar::draw(NVGcontext *vg) { | ||||
| @@ -3,6 +3,8 @@ | |||||
| namespace rack { | namespace rack { | ||||
| bool gDev = false; | |||||
| std::string gApplicationName = "VCV Rack"; | std::string gApplicationName = "VCV Rack"; | ||||
| std::string gApplicationVersion = TOSTRING(VERSION); | std::string gApplicationVersion = TOSTRING(VERSION); | ||||
| std::string gApiHost = "https://api.vcvrack.com"; | std::string gApiHost = "https://api.vcvrack.com"; | ||||
| @@ -1,93 +1,94 @@ | |||||
| #include "asset.hpp" | #include "asset.hpp" | ||||
| #include "util/common.hpp" | #include "util/common.hpp" | ||||
| #include <sys/stat.h> // for mkdir | |||||
| #include "osdialog.h" | #include "osdialog.h" | ||||
| #if ARCH_MAC | #if ARCH_MAC | ||||
| #include <CoreFoundation/CoreFoundation.h> | |||||
| #include <pwd.h> | |||||
| #include <CoreFoundation/CoreFoundation.h> | |||||
| #include <pwd.h> | |||||
| #endif | #endif | ||||
| #if ARCH_WIN | #if ARCH_WIN | ||||
| #include <Windows.h> | |||||
| #include <Shlobj.h> | |||||
| #include <Shlwapi.h> | |||||
| #include <Windows.h> | |||||
| #include <Shlobj.h> | |||||
| #include <Shlwapi.h> | |||||
| #endif | #endif | ||||
| #if ARCH_LIN | #if ARCH_LIN | ||||
| #include <unistd.h> | |||||
| #include <sys/types.h> | |||||
| #include <pwd.h> | |||||
| #include <unistd.h> | |||||
| #include <sys/types.h> | |||||
| #include <pwd.h> | |||||
| #endif | #endif | ||||
| namespace rack { | namespace rack { | ||||
| std::string assetGlobal(std::string filename) { | |||||
| std::string dir; | |||||
| #if RELEASE | |||||
| static std::string globalDir; | |||||
| static std::string localDir; | |||||
| void assetInit(bool devMode) { | |||||
| if (devMode) { | |||||
| // Use current working directory if running in development mode | |||||
| globalDir = "."; | |||||
| localDir = "."; | |||||
| return; | |||||
| } | |||||
| #if ARCH_MAC | #if ARCH_MAC | ||||
| CFBundleRef bundle = CFBundleGetMainBundle(); | CFBundleRef bundle = CFBundleGetMainBundle(); | ||||
| assert(bundle); | assert(bundle); | ||||
| CFURLRef resourcesUrl = CFBundleCopyResourcesDirectoryURL(bundle); | CFURLRef resourcesUrl = CFBundleCopyResourcesDirectoryURL(bundle); | ||||
| char buf[PATH_MAX]; | char buf[PATH_MAX]; | ||||
| Boolean success = CFURLGetFileSystemRepresentation(resourcesUrl, TRUE, (UInt8 *)buf, sizeof(buf)); | |||||
| Boolean success = CFURLGetFileSystemRepresentation(resourcesUrl, TRUE, (UInt8*) buf, sizeof(buf)); | |||||
| assert(success); | assert(success); | ||||
| CFRelease(resourcesUrl); | CFRelease(resourcesUrl); | ||||
| dir = buf; | |||||
| globalDir = buf; | |||||
| // Get home directory | |||||
| struct passwd *pw = getpwuid(getuid()); | |||||
| assert(pw); | |||||
| localDir = pw->pw_dir; | |||||
| localDir += "/Documents/Rack"; | |||||
| #endif | #endif | ||||
| #if ARCH_WIN | #if ARCH_WIN | ||||
| char buf[MAX_PATH]; | char buf[MAX_PATH]; | ||||
| DWORD length = GetModuleFileName(NULL, buf, sizeof(buf)); | DWORD length = GetModuleFileName(NULL, buf, sizeof(buf)); | ||||
| assert(length > 0); | assert(length > 0); | ||||
| PathRemoveFileSpec(buf); | PathRemoveFileSpec(buf); | ||||
| dir = buf; | |||||
| #endif | |||||
| #if ARCH_LIN | |||||
| // TODO For now, users should launch Rack from their terminal in the global directory | |||||
| dir = "."; | |||||
| #endif | |||||
| #else // RELEASE | |||||
| dir = "."; | |||||
| #endif // RELEASE | |||||
| return dir + "/" + filename; | |||||
| } | |||||
| globalDir = buf; | |||||
| std::string assetLocal(std::string filename) { | |||||
| std::string dir; | |||||
| #if RELEASE | |||||
| #if ARCH_MAC | |||||
| // Get home directory | |||||
| struct passwd *pw = getpwuid(getuid()); | |||||
| assert(pw); | |||||
| dir = pw->pw_dir; | |||||
| dir += "/Documents/Rack"; | |||||
| #endif | |||||
| #if ARCH_WIN | |||||
| // Get "My Documents" folder | // Get "My Documents" folder | ||||
| char buf[MAX_PATH]; | char buf[MAX_PATH]; | ||||
| HRESULT result = SHGetFolderPath(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, buf); | HRESULT result = SHGetFolderPath(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, buf); | ||||
| assert(result == S_OK); | assert(result == S_OK); | ||||
| dir = buf; | |||||
| dir += "/Rack"; | |||||
| localDir = buf; | |||||
| localDir += "/Rack"; | |||||
| #endif | #endif | ||||
| #if ARCH_LIN | #if ARCH_LIN | ||||
| // TODO For now, users should launch Rack from their terminal in the global directory | |||||
| globalDir = "."; | |||||
| // Get home directory | |||||
| const char *home = getenv("HOME"); | const char *home = getenv("HOME"); | ||||
| if (!home) { | if (!home) { | ||||
| struct passwd *pw = getpwuid(getuid()); | struct passwd *pw = getpwuid(getuid()); | ||||
| assert(pw); | assert(pw); | ||||
| home = pw->pw_dir; | home = pw->pw_dir; | ||||
| } | } | ||||
| dir = home; | |||||
| dir += "/.Rack"; | |||||
| localDir = home; | |||||
| localDir += "/.Rack"; | |||||
| #endif | #endif | ||||
| systemCreateDirectory(dir); | |||||
| #else // RELEASE | |||||
| dir = "."; | |||||
| #endif // RELEASE | |||||
| return dir + "/" + filename; | |||||
| } | |||||
| std::string assetGlobal(std::string filename) { | |||||
| return globalDir + "/" + filename; | |||||
| } | |||||
| std::string assetLocal(std::string filename) { | |||||
| return localDir + "/" + filename; | |||||
| } | } | ||||
| @@ -20,23 +20,38 @@ using namespace rack; | |||||
| int main(int argc, char* argv[]) { | int main(int argc, char* argv[]) { | ||||
| randomInit(); | |||||
| loggerInit(); | |||||
| bool devMode = false; | |||||
| std::string patchFile; | |||||
| // Parse command line arguments | // Parse command line arguments | ||||
| std::string patchFile; | |||||
| if (argc >= 2) { | |||||
| patchFile = argv[1]; | |||||
| int c; | |||||
| opterr = 0; | |||||
| while ((c = getopt(argc, argv, "d")) != -1) { | |||||
| switch (c) { | |||||
| case 'd': { | |||||
| devMode = true; | |||||
| } break; | |||||
| default: break; | |||||
| } | |||||
| } | |||||
| if (optind < argc) { | |||||
| patchFile = argv[optind]; | |||||
| } | } | ||||
| info("Rack %s", gApplicationVersion.c_str()); | |||||
| // Initialize environment | |||||
| randomInit(); | |||||
| assetInit(devMode); | |||||
| loggerInit(devMode); | |||||
| // Log directories | |||||
| // Log environment | |||||
| info("Rack %s", gApplicationVersion.c_str()); | |||||
| if (devMode) | |||||
| info("Development mode"); | |||||
| info("Global directory: %s", assetGlobal("").c_str()); | info("Global directory: %s", assetGlobal("").c_str()); | ||||
| info("Local directory: %s", assetLocal("").c_str()); | info("Local directory: %s", assetLocal("").c_str()); | ||||
| // Initialize namespaces | |||||
| pluginInit(); | |||||
| // Initialize app | |||||
| pluginInit(devMode); | |||||
| engineInit(); | engineInit(); | ||||
| rtmidiInit(); | rtmidiInit(); | ||||
| bridgeInit(); | bridgeInit(); | ||||
| @@ -321,7 +321,7 @@ static void extractPackages(std::string path) { | |||||
| // public API | // public API | ||||
| //////////////////// | //////////////////// | ||||
| void pluginInit() { | |||||
| void pluginInit(bool devMode) { | |||||
| tagsInit(); | tagsInit(); | ||||
| // Load core | // Load core | ||||
| @@ -334,15 +334,15 @@ void pluginInit() { | |||||
| std::string localPlugins = assetLocal("plugins"); | std::string localPlugins = assetLocal("plugins"); | ||||
| mkdir(localPlugins.c_str(), 0755); | mkdir(localPlugins.c_str(), 0755); | ||||
| #if RELEASE | |||||
| // Copy Fundamental package to plugins directory if folder does not exist | |||||
| std::string fundamentalSrc = assetGlobal("Fundamental.zip"); | |||||
| std::string fundamentalDest = assetLocal("plugins/Fundamental.zip"); | |||||
| std::string fundamentalDir = assetLocal("plugins/Fundamental"); | |||||
| if (!systemIsDirectory(fundamentalDir) && !systemIsFile(fundamentalDest)) { | |||||
| systemCopy(fundamentalSrc, fundamentalDest); | |||||
| if (!devMode) { | |||||
| // Copy Fundamental package to plugins directory if folder does not exist | |||||
| std::string fundamentalSrc = assetGlobal("Fundamental.zip"); | |||||
| std::string fundamentalDest = assetLocal("plugins/Fundamental.zip"); | |||||
| std::string fundamentalDir = assetLocal("plugins/Fundamental"); | |||||
| if (systemIsFile(fundamentalSrc) && !systemIsFile(fundamentalDest) && !systemIsDirectory(fundamentalDir)) { | |||||
| systemCopy(fundamentalSrc, fundamentalDest); | |||||
| } | |||||
| } | } | ||||
| #endif | |||||
| // Extract packages and load plugins | // Extract packages and load plugins | ||||
| extractPackages(localPlugins); | extractPackages(localPlugins); | ||||
| @@ -6,22 +6,25 @@ | |||||
| namespace rack { | namespace rack { | ||||
| static FILE *logFile = stderr; | |||||
| static FILE *logFile = NULL; | |||||
| static std::chrono::high_resolution_clock::time_point startTime; | static std::chrono::high_resolution_clock::time_point startTime; | ||||
| void loggerInit() { | |||||
| void loggerInit(bool devMode) { | |||||
| startTime = std::chrono::high_resolution_clock::now(); | startTime = std::chrono::high_resolution_clock::now(); | ||||
| #ifdef RELEASE | |||||
| std::string logFilename = assetLocal("log.txt"); | |||||
| logFile = fopen(logFilename.c_str(), "w"); | |||||
| #endif | |||||
| if (devMode) { | |||||
| logFile = stderr; | |||||
| } | |||||
| else { | |||||
| std::string logFilename = assetLocal("log.txt"); | |||||
| logFile = fopen(logFilename.c_str(), "w"); | |||||
| } | |||||
| } | } | ||||
| void loggerDestroy() { | void loggerDestroy() { | ||||
| #ifdef RELEASE | |||||
| fclose(logFile); | |||||
| #endif | |||||
| if (logFile != stderr) { | |||||
| fclose(logFile); | |||||
| } | |||||
| } | } | ||||
| static const char* const loggerText[] = { | static const char* const loggerText[] = { | ||||