modetags/v0.6.1
@@ -5,10 +5,6 @@ FLAGS += \ | |||
-Iinclude \ | |||
-Idep/include -Idep/lib/libzip/include | |||
ifdef RELEASE | |||
FLAGS += -DRELEASE | |||
endif | |||
include arch.mk | |||
STRIP ?= strip | |||
@@ -58,22 +54,25 @@ dep: | |||
$(MAKE) -C dep | |||
run: $(TARGET) | |||
./$< -d | |||
runr: $(TARGET) | |||
./$< | |||
debug: $(TARGET) | |||
ifdef ARCH_MAC | |||
lldb -ex run ./$< | |||
lldb -ex run ./$< -d | |||
endif | |||
ifdef ARCH_WIN | |||
gdb -ex run ./$< | |||
gdb -ex run ./$< -d | |||
endif | |||
ifdef ARCH_LIN | |||
gdb -ex run ./$< | |||
gdb -ex run ./$< -d | |||
endif | |||
perf: $(TARGET) | |||
ifdef ARCH_LIN | |||
perf record --call-graph dwarf ./$< | |||
perf record --call-graph dwarf ./$< -d | |||
endif | |||
clean: | |||
@@ -88,9 +87,6 @@ endif | |||
# This target is not intended for public use | |||
dist: all | |||
ifndef RELEASE | |||
exit 1 # Must enable RELEASE for dist target | |||
endif | |||
rm -rf dist | |||
# Rack distribution | |||
$(MAKE) -C plugins/Fundamental dist | |||
@@ -7,6 +7,7 @@ | |||
namespace rack { | |||
void assetInit(bool devMode); | |||
/** Returns the path of a global resource. Should only read files from this location. */ | |||
std::string assetGlobal(std::string filename); | |||
/** 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 pluginLogIn(std::string email, std::string password); | |||
void pluginLogOut(); | |||
@@ -175,7 +175,7 @@ enum LoggerLevel { | |||
FATAL_LEVEL | |||
}; | |||
void loggerInit(); | |||
void loggerInit(bool devMode); | |||
void loggerDestroy(); | |||
/** Do not use this function directly. Use the macros below. */ | |||
void loggerLog(LoggerLevel level, const char *file, int line, const char *format, ...); | |||
@@ -209,10 +209,11 @@ Toolbar::Toolbar() { | |||
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) { | |||
@@ -3,6 +3,8 @@ | |||
namespace rack { | |||
bool gDev = false; | |||
std::string gApplicationName = "VCV Rack"; | |||
std::string gApplicationVersion = TOSTRING(VERSION); | |||
std::string gApiHost = "https://api.vcvrack.com"; | |||
@@ -1,93 +1,94 @@ | |||
#include "asset.hpp" | |||
#include "util/common.hpp" | |||
#include <sys/stat.h> // for mkdir | |||
#include "osdialog.h" | |||
#if ARCH_MAC | |||
#include <CoreFoundation/CoreFoundation.h> | |||
#include <pwd.h> | |||
#include <CoreFoundation/CoreFoundation.h> | |||
#include <pwd.h> | |||
#endif | |||
#if ARCH_WIN | |||
#include <Windows.h> | |||
#include <Shlobj.h> | |||
#include <Shlwapi.h> | |||
#include <Windows.h> | |||
#include <Shlobj.h> | |||
#include <Shlwapi.h> | |||
#endif | |||
#if ARCH_LIN | |||
#include <unistd.h> | |||
#include <sys/types.h> | |||
#include <pwd.h> | |||
#include <unistd.h> | |||
#include <sys/types.h> | |||
#include <pwd.h> | |||
#endif | |||
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 | |||
CFBundleRef bundle = CFBundleGetMainBundle(); | |||
assert(bundle); | |||
CFURLRef resourcesUrl = CFBundleCopyResourcesDirectoryURL(bundle); | |||
char buf[PATH_MAX]; | |||
Boolean success = CFURLGetFileSystemRepresentation(resourcesUrl, TRUE, (UInt8 *)buf, sizeof(buf)); | |||
Boolean success = CFURLGetFileSystemRepresentation(resourcesUrl, TRUE, (UInt8*) buf, sizeof(buf)); | |||
assert(success); | |||
CFRelease(resourcesUrl); | |||
dir = buf; | |||
globalDir = buf; | |||
// Get home directory | |||
struct passwd *pw = getpwuid(getuid()); | |||
assert(pw); | |||
localDir = pw->pw_dir; | |||
localDir += "/Documents/Rack"; | |||
#endif | |||
#if ARCH_WIN | |||
char buf[MAX_PATH]; | |||
DWORD length = GetModuleFileName(NULL, buf, sizeof(buf)); | |||
assert(length > 0); | |||
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 | |||
char buf[MAX_PATH]; | |||
HRESULT result = SHGetFolderPath(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, buf); | |||
assert(result == S_OK); | |||
dir = buf; | |||
dir += "/Rack"; | |||
localDir = buf; | |||
localDir += "/Rack"; | |||
#endif | |||
#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"); | |||
if (!home) { | |||
struct passwd *pw = getpwuid(getuid()); | |||
assert(pw); | |||
home = pw->pw_dir; | |||
} | |||
dir = home; | |||
dir += "/.Rack"; | |||
localDir = home; | |||
localDir += "/.Rack"; | |||
#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[]) { | |||
randomInit(); | |||
loggerInit(); | |||
bool devMode = false; | |||
std::string patchFile; | |||
// 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("Local directory: %s", assetLocal("").c_str()); | |||
// Initialize namespaces | |||
pluginInit(); | |||
// Initialize app | |||
pluginInit(devMode); | |||
engineInit(); | |||
rtmidiInit(); | |||
bridgeInit(); | |||
@@ -321,7 +321,7 @@ static void extractPackages(std::string path) { | |||
// public API | |||
//////////////////// | |||
void pluginInit() { | |||
void pluginInit(bool devMode) { | |||
tagsInit(); | |||
// Load core | |||
@@ -334,15 +334,15 @@ void pluginInit() { | |||
std::string localPlugins = assetLocal("plugins"); | |||
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 | |||
extractPackages(localPlugins); | |||
@@ -6,22 +6,25 @@ | |||
namespace rack { | |||
static FILE *logFile = stderr; | |||
static FILE *logFile = NULL; | |||
static std::chrono::high_resolution_clock::time_point startTime; | |||
void loggerInit() { | |||
void loggerInit(bool devMode) { | |||
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() { | |||
#ifdef RELEASE | |||
fclose(logFile); | |||
#endif | |||
if (logFile != stderr) { | |||
fclose(logFile); | |||
} | |||
} | |||
static const char* const loggerText[] = { | |||