From 60ad6a5e5786d912e92e4cf7484d11745f6ab559 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Sat, 8 May 2021 16:14:15 +0200 Subject: [PATCH] Eliminate the glib requirement for ui-less plugins --- plugins/CMakeLists.txt | 4 -- plugins/common/plugin/NativeHelpers.cpp | 96 ++++++++++++++++++++++--- plugins/common/plugin/NativeHelpers.h | 8 +++ plugins/common/plugin/SfizzSettings.cpp | 12 +--- 4 files changed, 96 insertions(+), 24 deletions(-) diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 77f13374..d88dcd71 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -41,10 +41,6 @@ elseif(APPLE) target_link_libraries(plugins-common PRIVATE "${APPLE_FOUNDATION_LIBRARY}") else() - find_package(PkgConfig REQUIRED) - pkg_check_modules(GLIB REQUIRED glib-2.0) - target_include_directories(plugins-common PRIVATE ${GLIB_INCLUDE_DIRS}) - target_link_libraries(plugins-common PRIVATE ${GLIB_LIBRARIES}) endif() if((SFIZZ_LV2 AND SFIZZ_LV2_UI) OR SFIZZ_VST OR SFIZZ_AU OR SFIZZ_VST2) diff --git a/plugins/common/plugin/NativeHelpers.cpp b/plugins/common/plugin/NativeHelpers.cpp index 3ada4d93..f6988de0 100644 --- a/plugins/common/plugin/NativeHelpers.cpp +++ b/plugins/common/plugin/NativeHelpers.cpp @@ -5,6 +5,9 @@ // If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz #include "NativeHelpers.h" +#include +#include +#include #include #include @@ -25,21 +28,94 @@ const fs::path& getUserDocumentsDirectory() #elif defined(__APPLE__) // implemented in NativeHelpers.mm #else -#include - const fs::path& getUserDocumentsDirectory() { static const fs::path directory = []() -> fs::path { - const gchar* path = g_get_user_special_dir(G_USER_DIRECTORY_DOCUMENTS); - if (path) - return fs::path(path); - else { - const char* home = getenv("HOME"); - if (home && home[0] == '/') - return fs::path(home) / "Documents"; - throw std::runtime_error("Cannot get the document directory."); + for (const XdgUserDirsEntry& ent : + parseXdgUserDirs(getXdgConfigHome() / "user-dirs.dirs")) { + if (ent.name == "XDG_DOCUMENTS_DIR") + return ent.value; } + return getUserHomeDirectory() / "Documents"; }(); return directory; } + +const fs::path& getUserHomeDirectory() +{ + static const fs::path directory = []() -> fs::path { + const char* home = getenv("HOME"); + if (home && home[0] == '/') + return fs::u8path(home); + else + throw std::runtime_error("Cannot get the home directory."); + }(); + return directory; +} + +const fs::path& getXdgConfigHome() +{ + static const fs::path directory = []() -> fs::path { + const char* config = getenv("XDG_CONFIG_HOME"); + if (config && config[0] == '/') + return fs::u8path(config); + else + return getUserHomeDirectory() / ".config"; + + }(); + return directory; +} + +std::vector parseXdgUserDirs(const fs::path& userDirsPath) +{ + // from user-dirs.dirs(5) + // This file contains lines of the form `XDG_NAME_DIR=VALUE` + // VALUE must be of the form "$HOME/Path" or "/Path". + // Lines beginning with a # character are ignored. + + std::vector ents; + const fs::path& home = getUserHomeDirectory(); + + fs::ifstream in(userDirsPath); + std::string lineBuf; + + lineBuf.reserve(256); + while (std::getline(in, lineBuf)) { + absl::string_view line(lineBuf); + + line = absl::StripLeadingAsciiWhitespace(line); + if (line.empty() || line.front() == '#') + continue; + + size_t pos = line.find('='); + if (pos == line.npos) + continue; + + XdgUserDirsEntry ent; + ent.name = std::string(line.substr(0, pos)); + + absl::string_view rawValue = line.substr(pos + 1); + + rawValue = absl::StripTrailingAsciiWhitespace(rawValue); + + if (rawValue.size() < 2 || rawValue.front() != '"' || rawValue.back() != '"') + continue; + + rawValue.remove_prefix(1); + rawValue.remove_suffix(1); + + if (!rawValue.empty() && rawValue.front() == '/') + ent.value = fs::u8path(rawValue.begin(), rawValue.end()); + else if (absl::StartsWith(rawValue, "$HOME")) { + absl::string_view part = rawValue.substr(5); + ent.value = home / fs::u8path(part.begin(), part.end()).relative_path(); + } + else + continue; + + ents.push_back(std::move(ent)); + } + + return ents; +} #endif diff --git a/plugins/common/plugin/NativeHelpers.h b/plugins/common/plugin/NativeHelpers.h index 766d01d7..22407662 100644 --- a/plugins/common/plugin/NativeHelpers.h +++ b/plugins/common/plugin/NativeHelpers.h @@ -6,5 +6,13 @@ #pragma once #include +#include const fs::path& getUserDocumentsDirectory(); + +#if !defined(_WIN32) && !defined(__APPLE__) +const fs::path& getUserHomeDirectory(); +const fs::path& getXdgConfigHome(); +struct XdgUserDirsEntry { std::string name; fs::path value; }; +std::vector parseXdgUserDirs(const fs::path& userDirsPath); +#endif diff --git a/plugins/common/plugin/SfizzSettings.cpp b/plugins/common/plugin/SfizzSettings.cpp index 10e987ab..6e1bf520 100644 --- a/plugins/common/plugin/SfizzSettings.cpp +++ b/plugins/common/plugin/SfizzSettings.cpp @@ -5,6 +5,7 @@ // If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz #include "SfizzSettings.h" +#include "NativeHelpers.h" #include #include @@ -112,16 +113,7 @@ bool SfizzSettings::store(const char* name, absl::string_view value) static const fs::path getSettingsPath() { - fs::path dirPath; - const char* env; - if ((env = getenv("XDG_CONFIG_HOME")) && env[0] == '/') - dirPath = fs::path(env); - else if ((env = getenv("HOME")) && env[0] == '/') - dirPath = fs::path(env) / ".config"; - else - return {}; - dirPath /= "SFZTools"; - dirPath /= "sfizz"; + const fs::path dirPath = getXdgConfigHome() / "SFZTools" / "sfizz"; std::error_code ec; fs::create_directories(dirPath, ec); if (ec)