diff options
-rw-r--r-- | ingen/runtime_paths.hpp | 8 | ||||
-rw-r--r-- | src/runtime_paths.cpp | 86 |
2 files changed, 78 insertions, 16 deletions
diff --git a/ingen/runtime_paths.hpp b/ingen/runtime_paths.hpp index 2575efa1..fb697b14 100644 --- a/ingen/runtime_paths.hpp +++ b/ingen/runtime_paths.hpp @@ -30,12 +30,20 @@ extern const char search_path_separator; INGEN_API void set_bundle_path(const char* path); INGEN_API void set_bundle_path_from_code(void* function); +INGEN_API FilePath +find_in_search_path(const std::string& name, + const std::vector<FilePath>& search_path); + INGEN_API FilePath bundle_file_path(const std::string& name); INGEN_API FilePath data_file_path(const std::string& name); INGEN_API FilePath ingen_module_path(const std::string& name, FilePath dir={}); INGEN_API FilePath user_config_dir(); +INGEN_API FilePath user_data_dir(); INGEN_API std::vector<FilePath> system_config_dirs(); +INGEN_API std::vector<FilePath> system_data_dirs(); +INGEN_API std::vector<FilePath> config_dirs(); +INGEN_API std::vector<FilePath> data_dirs(); } // namespace ingen diff --git a/src/runtime_paths.cpp b/src/runtime_paths.cpp index 6e42381f..471e2ba2 100644 --- a/src/runtime_paths.cpp +++ b/src/runtime_paths.cpp @@ -17,6 +17,7 @@ #include "ingen/runtime_paths.hpp" #include "ingen/FilePath.hpp" +#include "ingen/filesystem.hpp" #include "ingen_config.h" #include <algorithm> @@ -43,6 +44,22 @@ static const char* const library_prefix = "lib"; static const char* const library_suffix = ".so"; #endif +static std::vector<FilePath> +parse_search_path(const char* search_path, std::vector<FilePath> defaults) +{ + if (!search_path) { + return std::move(defaults); + } + + std::vector<FilePath> paths; + std::istringstream ss{search_path}; + std::string entry; + while (std::getline(ss, entry, search_path_separator)) { + paths.emplace_back(entry); + } + return paths; +} + /** Must be called once at startup, and passed a pointer to a function * that lives in the 'top level' of the bundle (e.g. the executable). * Passing a function defined in a module etc. will not work! @@ -69,6 +86,20 @@ set_bundle_path(const char* path) bundle_path = FilePath(path); } +FilePath +find_in_search_path(const std::string& name, + const std::vector<FilePath>& search_path) +{ + for (const auto& dir : search_path) { + FilePath path = dir / name; + if (filesystem::exists(path)) { + return path; + } + } + + return FilePath{}; +} + /** Return the absolute path of a file in an Ingen LV2 bundle */ FilePath @@ -85,7 +116,7 @@ data_file_path(const std::string& name) #ifdef BUNDLE return bundle_path / INGEN_DATA_DIR / name; #else - return FilePath(INGEN_DATA_DIR) / name; + return find_in_search_path(name, data_dirs()); #endif } @@ -110,34 +141,57 @@ ingen_module_path(const std::string& name, FilePath dir) FilePath user_config_dir() { - const char* const xdg_config_home = getenv("XDG_CONFIG_HOME"); - const char* const home = getenv("HOME"); - - if (xdg_config_home) { + if (const char* xdg_config_home = getenv("XDG_CONFIG_HOME")) { return FilePath(xdg_config_home); - } else if (home) { + } else if (const char* home = getenv("HOME")) { return FilePath(home) / ".config"; } + return FilePath(); +} +FilePath +user_data_dir() +{ + if (const char* xdg_data_home = getenv("XDG_DATA_HOME")) { + return FilePath(xdg_data_home); + } else if (const char* home = getenv("HOME")) { + return FilePath(home) / ".local/share"; + } return FilePath(); } std::vector<FilePath> system_config_dirs() { - const char* const xdg_config_dirs = getenv("XDG_CONFIG_DIRS"); + return parse_search_path(getenv("XDG_CONFIG_DIRS"), {"/etc/xdg"}); +} - std::vector<FilePath> paths; - if (xdg_config_dirs) { - std::istringstream ss(xdg_config_dirs); - std::string entry; - while (std::getline(ss, entry, search_path_separator)) { - paths.emplace_back(entry); - } - } else { - paths.emplace_back("/etc/xdg"); +std::vector<FilePath> +config_dirs() +{ + std::vector<FilePath> paths = system_config_dirs(); + const FilePath user_dir = user_config_dir(); + if (!user_dir.empty()) { + paths.insert(paths.begin(), user_dir); } + return paths; +} + +std::vector<FilePath> +system_data_dirs() +{ + return parse_search_path(getenv("XDG_DATA_DIRS"), + {"/usr/local/share", "/usr/share"}); +} +std::vector<FilePath> +data_dirs() +{ + std::vector<FilePath> paths = system_data_dirs(); + const FilePath user_dir = user_data_dir(); + if (!user_dir.empty()) { + paths.insert(paths.begin(), user_dir); + } return paths; } |