Browse Source

Add system::join(). Add asset::module().

tags/v2.0.0
Andrew Belt 4 years ago
parent
commit
8d908a0a55
13 changed files with 95 additions and 55 deletions
  1. +27
    -6
      include/asset.hpp
  2. +1
    -1
      include/plugin/Plugin.hpp
  3. +9
    -0
      include/system.hpp
  4. +2
    -2
      src/app/ModuleWidget.cpp
  5. +24
    -20
      src/asset.cpp
  6. +1
    -0
      src/engine/Module.cpp
  7. +3
    -3
      src/patch.cpp
  8. +4
    -4
      src/plugin.cpp
  9. +2
    -2
      src/plugin/Model.cpp
  10. +1
    -1
      src/plugin/Plugin.cpp
  11. +15
    -10
      src/system.cpp
  12. +1
    -1
      src/updater.cpp
  13. +5
    -5
      src/window.cpp

+ 27
- 6
include/asset.hpp View File

@@ -10,16 +10,37 @@ struct Plugin;
} // namespace plugin


namespace engine {
struct Module;
} // namespace engine


namespace asset {


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. */
std::string user(std::string filename);
/** Returns the path of a resource in the plugin's folder. Should only read files from this location. */
std::string plugin(plugin::Plugin* plugin, std::string filename);

/** Returns the path of a system asset. Should only read files from this location. */
std::string system(std::string filename = "");

/** Returns the path of a user asset. Can read and write files to this location. */
std::string user(std::string filename = "");

/** Returns the path of a asset in the plugin's folder.
Plugin assets should be read-only by plugins.
Examples:
asset::plugin(pluginInstance, "samples/00.wav") // "/path/to/Rack/user/folder/plugins/MyPlugin/samples/00.wav"
*/
std::string plugin(plugin::Plugin* plugin, std::string filename = "");

/** Returns the path to an asset in the module patch folder.
The module patch folder is *not* created automatically. Before creating files at these paths, call
system::createDirectories(asset::module(module))

Examples:
asset::module(module, "recordings/00.wav") // "/path/to/Rack/user/folder/autosave/modules/1234/recordings/00.wav"
*/
std::string module(engine::Module* module, const std::string& filename = "");


// Set these before calling init() to override the default paths


+ 1
- 1
include/plugin/Plugin.hpp View File

@@ -73,7 +73,7 @@ struct Plugin {

~Plugin();
void addModel(Model* model);
Model* getModel(std::string slug);
Model* getModel(const std::string& slug);
void fromJson(json_t* rootJ);
std::string getBrand();
};


+ 9
- 0
include/system.hpp View File

@@ -14,6 +14,15 @@ namespace system {

// Filesystem

/** Joins two paths with a directory separator.
If `path2` is an empty string, returns `path1`.
*/
std::string join(const std::string& path1, const std::string& path2 = "");
/** Join an arbitrary number of paths, from left to right. */
template <typename... Paths>
std::string join(const std::string& path1, const std::string& path2, Paths... paths) {
return join(join(path1, path2), paths...);
}
/** Returns a list of all entries (directories, files, symbolic links, etc) in a directory.
`depth` is the number of directories to recurse. 0 depth does not recurse. -1 depth recurses infinitely.
*/


+ 2
- 2
src/app/ModuleWidget.cpp View File

@@ -674,7 +674,7 @@ void ModuleWidget::loadAction(std::string filename) {
}

void ModuleWidget::loadTemplate() {
std::string templatePath = model->getUserPresetDir() + "/" + "template.vcvm";
std::string templatePath = system::join(model->getUserPresetDir(), "template.vcvm");
try {
load(templatePath);
}
@@ -735,7 +735,7 @@ void ModuleWidget::saveTemplate() {
std::string presetDir = model->getUserPresetDir();
system::createDirectories(presetDir);

std::string templatePath = presetDir + "/" + "template.vcvm";
std::string templatePath = system::join(presetDir, "template.vcvm");
save(templatePath);
}



+ 24
- 20
src/asset.cpp View File

@@ -21,6 +21,7 @@
#include <settings.hpp>
#include <string.hpp>
#include <plugin/Plugin.hpp>
#include <engine/Module.hpp>
#include <app/common.hpp>


@@ -29,7 +30,7 @@ namespace asset {


static void initSystemDir() {
if (systemDir != "")
if (!systemDir.empty())
return;

if (settings::devMode) {
@@ -76,7 +77,7 @@ static void initSystemDir() {


static void initUserDir() {
if (userDir != "")
if (!userDir.empty())
return;

if (settings::devMode) {
@@ -89,15 +90,13 @@ static void initUserDir() {
wchar_t documentsBufW[MAX_PATH] = L".";
HRESULT result = SHGetFolderPathW(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, documentsBufW);
assert(result == S_OK);
userDir = string::U16toU8(documentsBufW);
userDir += "/Rack";
userDir = system::join(string::U16toU8(documentsBufW), "Rack");
#endif
#if defined ARCH_MAC
// Get home directory
struct passwd* pw = getpwuid(getuid());
assert(pw);
userDir = pw->pw_dir;
userDir += "/Documents/Rack";
userDir = system::join(pw->pw_dir, "Documents/Rack");
#endif
#if defined ARCH_LIN
// Get home directory
@@ -107,8 +106,7 @@ static void initUserDir() {
assert(pw);
homeBuf = pw->pw_dir;
}
userDir = homeBuf;
userDir += "/.Rack";
userDir = system::join(homeBuf, ".Rack");
#endif
}

@@ -120,34 +118,40 @@ void init() {

// Set paths
if (settings::devMode) {
pluginsPath = userDir + "/plugins";
settingsPath = userDir + "/settings.json";
autosavePath = userDir + "/autosave";
templatePath = userDir + "/template.vcv";
pluginsPath = system::join(userDir, "plugins");
settingsPath = system::join(userDir, "settings.json");
autosavePath = system::join(userDir, "autosave");
templatePath = system::join(userDir, "template.vcv");
}
else {
logPath = userDir + "/log.txt";
pluginsPath = userDir + "/plugins-v" + ABI_VERSION;
settingsPath = userDir + "/settings-v" + ABI_VERSION + ".json";
autosavePath = userDir + "/autosave-v" + ABI_VERSION;
templatePath = userDir + "/template-v" + ABI_VERSION + ".vcv";
logPath = system::join(userDir, "log.txt");
pluginsPath = system::join(userDir, "plugins-v" + ABI_VERSION);
settingsPath = system::join(userDir, "settings-v" + ABI_VERSION + ".json");
autosavePath = system::join(userDir, "autosave-v" + ABI_VERSION);
templatePath = system::join(userDir, "template-v" + ABI_VERSION + ".vcv");
}
}


std::string system(std::string filename) {
return systemDir + "/" + filename;
return system::join(systemDir, filename);
}


std::string user(std::string filename) {
return userDir + "/" + filename;
return system::join(userDir, filename);
}


std::string plugin(plugin::Plugin* plugin, std::string filename) {
assert(plugin);
return plugin->path + "/" + filename;
return system::join(plugin->path, filename);
}


std::string module(engine::Module* module, const std::string& filename) {
assert(module);
return system::join(autosavePath, "modules", std::to_string(module->id), filename);
}




+ 1
- 0
src/engine/Module.cpp View File

@@ -1,5 +1,6 @@
#include <engine/Module.hpp>
#include <plugin.hpp>
#include <asset.hpp>


namespace rack {


+ 3
- 3
src/patch.cpp View File

@@ -153,7 +153,7 @@ void PatchManager::saveAutosave() {

// Write to temporary path and then rename it to the correct path
system::createDirectories(asset::autosavePath);
std::string patchPath = asset::autosavePath + "/patch.json";
std::string patchPath = system::join(asset::autosavePath, "patch.json");
std::string tmpPath = patchPath + ".tmp";
FILE* file = std::fopen(tmpPath.c_str(), "w");
if (!file) {
@@ -189,7 +189,7 @@ void PatchManager::load(std::string path) {

if (isPatchLegacyPre2(path)) {
// Copy the .vcv file directly to "patch.json".
system::copy(path, asset::autosavePath + "/patch.json");
system::copy(path, system::join(asset::autosavePath, "patch.json"));
}
else {
// Extract the .vcv file as a .tar.zst archive.
@@ -237,7 +237,7 @@ void PatchManager::loadTemplateDialog() {

void PatchManager::loadAutosave() {
INFO("Loading autosave");
std::string patchPath = asset::autosavePath + "/patch.json";
std::string patchPath = system::join(asset::autosavePath, "patch.json");
FILE* file = std::fopen(patchPath.c_str(), "r");
if (!file) {
// Exit silently


+ 4
- 4
src/plugin.cpp View File

@@ -79,7 +79,7 @@ static InitCallback loadPluginCallback(Plugin* plugin) {
#elif ARCH_MAC
libraryExt = "dylib";
#endif
std::string libraryPath = plugin->path + "/plugin." + libraryExt;
std::string libraryPath = system::join(plugin->path, "plugin." + libraryExt);

// Check file existence
if (!system::isFile(libraryPath))
@@ -124,7 +124,7 @@ static Plugin* loadPlugin(std::string path) {
}

// Load plugin.json
std::string manifestFilename = (path == "") ? asset::system("Core.json") : (path + "/plugin.json");
std::string manifestFilename = (path == "") ? asset::system("Core.json") : system::join(path, "plugin.json");
FILE* file = std::fopen(manifestFilename.c_str(), "r");
if (!file)
throw Exception(string::f("Manifest file %s does not exist", manifestFilename.c_str()));
@@ -226,7 +226,7 @@ void init() {
#else
std::string fundamentalSrc = asset::system("Fundamental.zip");
#endif
std::string fundamentalDir = asset::pluginsPath + "/Fundamental";
std::string fundamentalDir = system::join(asset::pluginsPath, "Fundamental");
if (!settings::devMode && !getPlugin("Fundamental") && system::isFile(fundamentalSrc)) {
INFO("Extracting bundled Fundamental package");
system::unarchiveToFolder(fundamentalSrc.c_str(), asset::pluginsPath.c_str());
@@ -471,7 +471,7 @@ void syncUpdate(Update* update) {
INFO("Downloading plugin %s %s %s", update->pluginSlug.c_str(), update->version.c_str(), APP_ARCH.c_str());

// Download zip
std::string pluginDest = asset::pluginsPath + "/" + update->pluginSlug + ".zip";
std::string pluginDest = system::join(asset::pluginsPath, update->pluginSlug + ".zip");
if (!network::requestDownload(downloadUrl, pluginDest, &update->progress, cookies)) {
WARN("Plugin %s download was unsuccessful", update->pluginSlug.c_str());
return;


+ 2
- 2
src/plugin/Model.cpp View File

@@ -59,12 +59,12 @@ std::string Model::getFullName() {


std::string Model::getFactoryPresetDir() {
return asset::plugin(plugin, "presets/" + slug);
return asset::plugin(plugin, system::join("presets", slug));
}


std::string Model::getUserPresetDir() {
return asset::user("presets/" + plugin->slug + "/" + slug);
return asset::user(system::join("presets", plugin->slug, slug));
}




+ 1
- 1
src/plugin/Plugin.cpp View File

@@ -22,7 +22,7 @@ void Plugin::addModel(Model* model) {
models.push_back(model);
}

Model* Plugin::getModel(std::string slug) {
Model* Plugin::getModel(const std::string& slug) {
for (Model* model : models) {
if (model->slug == slug) {
return model;


+ 15
- 10
src/system.cpp View File

@@ -50,11 +50,16 @@ namespace rack {
namespace system {


std::string join(const std::string& path1, const std::string& path2) {
return (fs::u8path(path1) / fs::u8path(path2)).generic_u8string();
}


std::list<std::string> getEntries(const std::string& dirPath, int depth) {
try {
std::list<std::string> entries;
for (auto& entry : fs::directory_iterator(fs::u8path(dirPath))) {
std::string subEntry = entry.path().u8string();
std::string subEntry = entry.path().generic_u8string();
entries.push_back(subEntry);
// Recurse if depth > 0 (limited recursion) or depth < 0 (infinite recursion).
if (depth != 0) {
@@ -174,7 +179,7 @@ int removeRecursively(const std::string& path) {

std::string getWorkingDirectory() {
try {
return fs::current_path().u8string();
return fs::current_path().generic_u8string();
}
catch (fs::filesystem_error& e) {
throw Exception(e.what());
@@ -194,7 +199,7 @@ void setWorkingDirectory(const std::string& path) {

std::string getTempDir() {
try {
return fs::temp_directory_path().u8string();
return fs::temp_directory_path().generic_u8string();
}
catch (fs::filesystem_error& e) {
throw Exception(e.what());
@@ -204,7 +209,7 @@ std::string getTempDir() {

std::string getAbsolute(const std::string& path) {
try {
return fs::absolute(fs::u8path(path)).u8string();
return fs::absolute(fs::u8path(path)).generic_u8string();
}
catch (fs::filesystem_error& e) {
throw Exception(e.what());
@@ -214,7 +219,7 @@ std::string getAbsolute(const std::string& path) {

std::string getCanonical(const std::string& path) {
try {
return fs::canonical(fs::u8path(path)).u8string();
return fs::canonical(fs::u8path(path)).generic_u8string();
}
catch (fs::filesystem_error& e) {
throw Exception(e.what());
@@ -224,7 +229,7 @@ std::string getCanonical(const std::string& path) {

std::string getDirectory(const std::string& path) {
try {
return fs::u8path(path).parent_path().u8string();
return fs::u8path(path).parent_path().generic_u8string();
}
catch (fs::filesystem_error& e) {
throw Exception(e.what());
@@ -234,7 +239,7 @@ std::string getDirectory(const std::string& path) {

std::string getFilename(const std::string& path) {
try {
return fs::u8path(path).filename().u8string();
return fs::u8path(path).filename().generic_u8string();
}
catch (fs::filesystem_error& e) {
throw Exception(e.what());
@@ -244,7 +249,7 @@ std::string getFilename(const std::string& path) {

std::string getStem(const std::string& path) {
try {
return fs::u8path(path).stem().u8string();
return fs::u8path(path).stem().generic_u8string();
}
catch (fs::filesystem_error& e) {
throw Exception(e.what());
@@ -254,7 +259,7 @@ std::string getStem(const std::string& path) {

std::string getExtension(const std::string& path) {
try {
return fs::u8path(path).extension().u8string();
return fs::u8path(path).extension().generic_u8string();
}
catch (fs::filesystem_error& e) {
throw Exception(e.what());
@@ -410,7 +415,7 @@ void unarchiveToFolder(const std::string& archivePath, const std::string& folder
std::string entryPath = archive_entry_pathname(entry);
if (!fs::u8path(entryPath).is_relative())
throw Exception(string::f("unzipToFolder() does not support absolute paths: %s", entryPath.c_str()));
entryPath = fs::absolute(fs::u8path(entryPath), fs::u8path(folderPath)).u8string();
entryPath = fs::absolute(fs::u8path(entryPath), fs::u8path(folderPath)).generic_u8string();
#if defined ARCH_WIN
archive_entry_copy_pathname_w(entry, string::U8toU16(entryPath).c_str());
#else


+ 1
- 1
src/updater.cpp View File

@@ -76,7 +76,7 @@ void update() {
system::runProcessDetached(path);
#elif defined ARCH_MAC
std::string cmd;
// std::string appPath = asset::userDir + "/Rack.app";
// std::string appPath = system::join(asset::userDir, "Rack.app");
// cmd = "rm -rf '" + appPath + "'";
// std::system(cmd.c_str());
// // Unzip app using Apple's unzipper, since Rack's unzipper doesn't handle the metadata stuff correctly.


+ 5
- 5
src/window.cpp View File

@@ -434,10 +434,10 @@ void Window::screenshot(float zoom) {
std::string screenshotsDir = asset::user("screenshots");
system::createDirectory(screenshotsDir);
for (plugin::Plugin* p : plugin::plugins) {
std::string dir = screenshotsDir + "/" + p->slug;
std::string dir = system::join(screenshotsDir, p->slug);
system::createDirectory(dir);
for (plugin::Model* model : p->models) {
std::string filename = dir + "/" + model->slug + ".png";
std::string filename = system::join(dir, model->slug + ".png");
// Skip model if screenshot already exists
if (system::isFile(filename))
continue;
@@ -468,9 +468,9 @@ void Window::screenshot(float zoom) {
for (int y = 0; y < height / 2; y++) {
int flipY = height - y - 1;
uint8_t tmp[width * 4];
memcpy(tmp, &data[y * width * 4], width * 4);
memcpy(&data[y * width * 4], &data[flipY * width * 4], width * 4);
memcpy(&data[flipY * width * 4], tmp, width * 4);
std::memcpy(tmp, &data[y * width * 4], width * 4);
std::memcpy(&data[y * width * 4], &data[flipY * width * 4], width * 4);
std::memcpy(&data[flipY * width * 4], tmp, width * 4);
}

// Write pixels to PNG


Loading…
Cancel
Save