modetags/v0.6.1
@@ -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[] = { | ||||