diff options
author | David Robillard <d@drobilla.net> | 2018-01-21 00:41:34 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2018-01-21 00:56:50 +0100 |
commit | a99b72e4adbc4c28fadc08d29299d99405f72db9 (patch) | |
tree | fb21f2cea8f5db1dc187cdbdd01f43e73bbddfff /src | |
parent | 329f498d901f9be9c0c820749850f5277a17df5d (diff) | |
download | ingen-a99b72e4adbc4c28fadc08d29299d99405f72db9.tar.gz ingen-a99b72e4adbc4c28fadc08d29299d99405f72db9.tar.bz2 ingen-a99b72e4adbc4c28fadc08d29299d99405f72db9.zip |
Add FilePath class and remove use of glib path utilities
Diffstat (limited to 'src')
-rw-r--r-- | src/Configuration.cpp | 41 | ||||
-rw-r--r-- | src/FilePath.cpp | 242 | ||||
-rw-r--r-- | src/Parser.cpp | 56 | ||||
-rw-r--r-- | src/Serialiser.cpp | 77 | ||||
-rw-r--r-- | src/URI.cpp | 8 | ||||
-rw-r--r-- | src/World.cpp | 18 | ||||
-rw-r--r-- | src/gui/LoadGraphWindow.cpp | 8 | ||||
-rw-r--r-- | src/gui/ThreadedLoader.cpp | 21 | ||||
-rw-r--r-- | src/gui/ThreadedLoader.hpp | 9 | ||||
-rw-r--r-- | src/runtime_paths.cpp | 92 | ||||
-rw-r--r-- | src/server/LV2Block.cpp | 25 | ||||
-rw-r--r-- | src/server/LV2Block.hpp | 4 | ||||
-rw-r--r-- | src/server/events/CreateBlock.cpp | 3 | ||||
-rw-r--r-- | src/server/events/Delta.cpp | 14 | ||||
-rw-r--r-- | src/wscript | 1 |
15 files changed, 436 insertions, 183 deletions
diff --git a/src/Configuration.cpp b/src/Configuration.cpp index bdbf07bc..ec9cbf0f 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -20,14 +20,13 @@ #include <iostream> #include <thread> -#include <glibmm/fileutils.h> -#include <glibmm/miscutils.h> - #include "ingen/Configuration.hpp" #include "ingen/Forge.hpp" #include "ingen/Log.hpp" #include "ingen/URIMap.hpp" +#include "ingen/filesystem.hpp" #include "ingen/ingen.h" +#include "ingen/runtime_paths.hpp" #include "sord/sordmm.hpp" #include "sratom/sratom.h" @@ -226,9 +225,9 @@ Configuration::parse(int argc, char** argv) throw (Configuration::OptionError) } bool -Configuration::load(const std::string& path) +Configuration::load(const FilePath& path) { - if (!Glib::file_test(path, Glib::FILE_TEST_EXISTS)) { + if (!filesystem::exists(path)) { return false; } @@ -261,23 +260,22 @@ Configuration::load(const std::string& path) return true; } -std::string +FilePath Configuration::save(URIMap& uri_map, const std::string& app, - const std::string& filename, + const FilePath& filename, unsigned scopes) throw (FileError) { // Save to file if it is absolute, otherwise save to user config dir - std::string path = filename; - if (!Glib::path_is_absolute(path)) { - path = Glib::build_filename( - Glib::build_filename(Glib::get_user_config_dir(), app), filename); + FilePath path = filename; + if (!path.is_absolute()) { + path = FilePath(user_config_dir()) / app / filename; } // Create parent directories if necessary - const std::string dir = Glib::path_get_dirname(path); - if (g_mkdir_with_parents(dir.c_str(), 0755) < 0) { + const FilePath dir = path.parent_path(); + if (!filesystem::create_directories(dir)) { throw FileError((fmt("Error creating directory %1% (%2%)") % dir % strerror(errno)).str()); } @@ -343,23 +341,20 @@ Configuration::save(URIMap& uri_map, return path; } -std::list<std::string> -Configuration::load_default(const std::string& app, - const std::string& filename) +std::list<FilePath> +Configuration::load_default(const std::string& app, const FilePath& filename) { - std::list<std::string> loaded; + std::list<FilePath> loaded; - const std::vector<std::string> dirs = Glib::get_system_config_dirs(); - for (auto d : dirs) { - const std::string path = Glib::build_filename( - Glib::build_filename(d, app), filename); + const std::vector<FilePath> dirs = system_config_dirs(); + for (const auto& d : dirs) { + const FilePath path = d / app / filename; if (load(path)) { loaded.push_back(path); } } - const std::string path = Glib::build_filename( - Glib::build_filename(Glib::get_user_config_dir(), app), filename); + const FilePath path = user_config_dir() / app / filename; if (load(path)) { loaded.push_back(path); } diff --git a/src/FilePath.cpp b/src/FilePath.cpp new file mode 100644 index 00000000..557fabc9 --- /dev/null +++ b/src/FilePath.cpp @@ -0,0 +1,242 @@ +/* + This file is part of Ingen. + Copyright 2018 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "ingen/FilePath.hpp" + +namespace Ingen { + +template <typename Char> +static bool +is_sep(const Char chr) +{ +#ifdef USE_WINDOWS_FILE_PATHS + return chr == L'/' || chr == preferred_separator; +#else + return chr == '/'; +#endif +} + +FilePath& +FilePath::operator=(FilePath&& path) noexcept +{ + _str = std::move(path._str); + path.clear(); + return *this; +} + +FilePath& +FilePath::operator=(string_type&& str) +{ + return *this = FilePath(std::move(str)); +} + +FilePath& +FilePath::operator/=(const FilePath& path) +{ + const FilePath::string_type str = path.string(); + if (!_str.empty() && !is_sep(_str.back()) && !str.empty() && + !is_sep(str.front())) { + _str += preferred_separator; + } + + _str += str; + return *this; +} + +FilePath& +FilePath::operator+=(const FilePath& path) +{ + return operator+=(path.native()); +} + +FilePath& +FilePath::operator+=(const string_type& str) +{ + _str += str; + return *this; +} + +FilePath& +FilePath::operator+=(const value_type* str) +{ + _str += str; + return *this; +} + +FilePath& +FilePath::operator+=(value_type chr) +{ + _str += chr; + return *this; +} + +FilePath& +FilePath::operator+=(boost::basic_string_view<value_type> sv) +{ + _str.append(sv.data(), sv.size()); + return *this; +} + +FilePath +FilePath::root_name() const +{ +#ifdef USE_WINDOWS_FILE_PATHS + if (_str.length() >= 2 && _str[0] >= 'A' && _str[0] <= 'Z' && + _str[1] == ':') { + return FilePath(_str.substr(0, 2)); + } +#endif + + return FilePath(); +} + +FilePath +FilePath::root_directory() const +{ +#ifdef USE_WINDOWS_FILE_PATHS + const auto name = root_name().string(); + return name.empty() ? Path() : Path(name + preferred_separator); +#endif + + return _str[0] == '/' ? FilePath("/") : FilePath(); +} + +FilePath +FilePath::root_path() const +{ +#ifdef USE_WINDOWS_FILE_PATHS + const auto name = root_name(); + return name.empty() ? FilePath() : name / root_directory(); +#endif + return root_directory(); +} + +FilePath +FilePath::relative_path() const +{ + const auto root = root_path(); + return root.empty() ? FilePath() + : FilePath(_str.substr(root.string().length())); +} + +FilePath +FilePath::parent_path() const +{ + if (empty() || *this == root_path()) { + return *this; + } + + const auto first_sep = find_first_sep(); + const auto last_sep = find_last_sep(); + return ((last_sep == std::string::npos || last_sep == first_sep) + ? root_path() + : FilePath(_str.substr(0, last_sep))); +} + +FilePath +FilePath::filename() const +{ + return ((empty() || *this == root_path()) + ? FilePath() + : FilePath(_str.substr(find_last_sep() + 1))); +} + +FilePath +FilePath::stem() const +{ + const auto name = filename(); + const auto dot = name.string().find('.'); + return ((dot == std::string::npos) ? name + : FilePath(name.string().substr(0, dot))); +} + +FilePath +FilePath::extension() const +{ + const auto name = filename().string(); + const auto dot = name.find('.'); + return ((dot == std::string::npos) ? FilePath() + : FilePath(name.substr(dot, dot))); +} + +bool +FilePath::is_absolute() const +{ +#ifdef USE_WINDOWS_FILE_PATHS + return !root_name().empty(); +#else + return !root_directory().empty(); +#endif +} + +std::size_t +FilePath::find_first_sep() const +{ + const auto i = std::find_if(_str.begin(), _str.end(), is_sep<value_type>); + return i == _str.end() ? std::string::npos : (i - _str.begin()); +} + +std::size_t +FilePath::find_last_sep() const +{ + const auto i = std::find_if(_str.rbegin(), _str.rend(), is_sep<value_type>); + return (i == _str.rend() ? std::string::npos + : (_str.length() - 1 - (i - _str.rbegin()))); +} + +bool +operator==(const FilePath& lhs, const FilePath& rhs) noexcept +{ + return lhs.string() == rhs.string(); +} + +bool +operator!=(const FilePath& lhs, const FilePath& rhs) noexcept +{ + return !(lhs == rhs); +} + +bool +operator<(const FilePath& lhs, const FilePath& rhs) noexcept +{ + return lhs.string().compare(rhs.string()) < 0; +} + +bool +operator<=(const FilePath& lhs, const FilePath& rhs) noexcept +{ + return !(rhs < lhs); +} + +bool +operator>(const FilePath& lhs, const FilePath& rhs) noexcept +{ + return rhs < lhs; +} + +bool +operator>=(const FilePath& lhs, const FilePath& rhs) noexcept +{ + return !(lhs < rhs); +} + +FilePath +operator/(const FilePath& lhs, const FilePath& rhs) +{ + return FilePath(lhs) /= rhs; +} + +} // namespace Ingen diff --git a/src/Parser.cpp b/src/Parser.cpp index e0ec0d35..27f7d753 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -19,10 +19,6 @@ #include <string> #include <utility> -#include <glibmm/convert.h> -#include <glibmm/fileutils.h> -#include <glibmm/miscutils.h> - #include "ingen/Atom.hpp" #include "ingen/AtomForgeSink.hpp" #include "ingen/Forge.hpp" @@ -32,6 +28,7 @@ #include "ingen/URIMap.hpp" #include "ingen/URIs.hpp" #include "ingen/World.hpp" +#include "ingen/filesystem.hpp" #include "ingen/paths.hpp" #include "lv2/lv2plug.in/ns/ext/atom/atom.h" #include "serd/serd.h" @@ -105,14 +102,6 @@ relative_uri(const std::string& base, const std::string& uri, bool leading_slash return ret; } -static std::string -get_basename(const std::string& uri) -{ - std::string ret = Glib::path_get_basename(uri); - ret = ret.substr(0, ret.find_last_of('.')); - return ret; -} - static bool skip_property(Ingen::URIs& uris, const Sord::Node& predicate) { @@ -418,9 +407,11 @@ parse_graph(Ingen::World* world, // For each block in this graph for (Sord::Iter n = model.find(subject, ingen_block, nil); !n.end(); ++n) { - Sord::Node node = n.get_object(); + Sord::Node node = n.get_object(); + URI node_uri = URI(node.to_string()); + assert(!node_uri.path().empty() && node_uri.path() != "/"); const Raul::Path block_path = graph_path.child( - Raul::Symbol(get_basename(node.to_string()))); + Raul::Symbol(FilePath(node_uri.path()).stem().string())); // Parse and create block parse_block(world, target, model, base_uri, node, block_path, @@ -630,30 +621,23 @@ parse(Ingen::World* world, bool Parser::parse_file(Ingen::World* world, Ingen::Interface* target, - const std::string& path, + const FilePath& path, boost::optional<Raul::Path> parent, boost::optional<Raul::Symbol> symbol, boost::optional<Properties> data) { // Get absolute file path - std::string file_path = path; - if (!Glib::path_is_absolute(file_path)) { - file_path = Glib::build_filename(Glib::get_current_dir(), file_path); + FilePath file_path = path; + if (!file_path.is_absolute()) { + file_path = filesystem::current_path() / file_path; } // Find file to use as manifest - const bool is_bundle = Glib::file_test(file_path, Glib::FILE_TEST_IS_DIR); - const std::string manifest_path = (is_bundle - ? Glib::build_filename(file_path, "manifest.ttl") - : file_path); - - URI manifest_uri; - try { - manifest_uri = URI(Glib::filename_to_uri(manifest_path)); - } catch (const Glib::ConvertError& e) { - world->log().error(fmt("URI conversion error (%1%)\n") % e.what()); - return false; - } + const bool is_bundle = filesystem::is_directory(file_path); + const FilePath manifest_path = + (is_bundle ? file_path / "manifest.ttl" : file_path); + + URI manifest_uri(manifest_path); // Find graphs in manifest const std::set<ResourceRecord> resources = find_resources( @@ -669,7 +653,7 @@ Parser::parse_file(Ingen::World* world, In this case, choose the one with the file URI. */ URI uri; for (const ResourceRecord& r : resources) { - if (r.uri == Glib::filename_to_uri(manifest_path)) { + if (r.uri == URI(manifest_path)) { uri = r.uri; file_path = r.filename; break; @@ -688,10 +672,10 @@ Parser::parse_file(Ingen::World* world, } // Initialise parsing environment - const std::string file_uri = Glib::filename_to_uri(file_path); - const uint8_t* uri_c_str = (const uint8_t*)uri.c_str(); - SerdNode base_node = serd_node_from_string(SERD_URI, uri_c_str); - SerdEnv* env = serd_env_new(&base_node); + const URI file_uri = URI(file_path); + const uint8_t* uri_c_str = (const uint8_t*)uri.c_str(); + SerdNode base_node = serd_node_from_string(SERD_URI, uri_c_str); + SerdEnv* env = serd_env_new(&base_node); // Load graph into model Sord::Model model(*world->rdf_world(), uri.string(), SORD_SPO|SORD_PSO, false); @@ -726,7 +710,7 @@ boost::optional<URI> Parser::parse_string(Ingen::World* world, Ingen::Interface* target, const std::string& str, - const std::string& base_uri, + const URI& base_uri, boost::optional<Raul::Path> parent, boost::optional<Raul::Symbol> symbol, boost::optional<Properties> data) diff --git a/src/Serialiser.cpp b/src/Serialiser.cpp index 2f976d53..86913aa4 100644 --- a/src/Serialiser.cpp +++ b/src/Serialiser.cpp @@ -22,14 +22,8 @@ #include <string> #include <utility> -#include <glib.h> -#include <glib/gstdio.h> -#include <glibmm/convert.h> -#include <glibmm/fileutils.h> -#include <glibmm/miscutils.h> -#include <glibmm/module.h> - #include "ingen/Arc.hpp" +#include "ingen/FilePath.hpp" #include "ingen/Forge.hpp" #include "ingen/Interface.hpp" #include "ingen/Log.hpp" @@ -41,6 +35,8 @@ #include "ingen/URIMap.hpp" #include "ingen/URIs.hpp" #include "ingen/World.hpp" +#include "ingen/filesystem.hpp" +#include "ingen/runtime_paths.hpp" #include "lv2/lv2plug.in/ns/ext/state/state.h" #include "lv2/lv2plug.in/ns/extensions/ui/ui.h" #include "raul/Path.hpp" @@ -65,7 +61,8 @@ struct Serialiser::Impl { enum class Mode { TO_FILE, TO_STRING }; - void start_to_file(const Raul::Path& root, const std::string& filename); + void start_to_file(const Raul::Path& root, + const FilePath& filename); std::set<const Resource*> serialise_graph(SPtr<const Node> graph, const Sord::Node& graph_id); @@ -85,10 +82,10 @@ struct Serialiser::Impl { Sord::Node path_rdf_node(const Raul::Path& path); - void write_manifest(const std::string& bundle_path, - SPtr<const Node> graph); + void write_manifest(const FilePath& bundle_path, + SPtr<const Node> graph); - void write_plugins(const std::string& bundle_path, + void write_plugins(const FilePath& bundle_path, const std::set<const Resource*> plugins); void serialise_arc(const Sord::Node& parent, @@ -116,11 +113,11 @@ Serialiser::~Serialiser() } void -Serialiser::Impl::write_manifest(const std::string& bundle_path, - SPtr<const Node> graph) +Serialiser::Impl::write_manifest(const FilePath& bundle_path, + SPtr<const Node> graph) { - const string manifest_path(Glib::build_filename(bundle_path, "manifest.ttl")); - const string binary_path(Glib::Module::build_path("", "ingen_lv2")); + const FilePath manifest_path(bundle_path / "manifest.ttl"); + const FilePath binary_path(ingen_module_path("lv2")); start_to_file(Raul::Path("/"), manifest_path); @@ -147,10 +144,10 @@ Serialiser::Impl::write_manifest(const std::string& bundle_path, } void -Serialiser::Impl::write_plugins(const std::string& bundle_path, +Serialiser::Impl::write_plugins(const FilePath& bundle_path, const std::set<const Resource*> plugins) { - const string plugins_path(Glib::build_filename(bundle_path, "plugins.ttl")); + const FilePath plugins_path(bundle_path / "plugins.ttl"); start_to_file(Raul::Path("/"), plugins_path); @@ -187,27 +184,22 @@ Serialiser::write_bundle(SPtr<const Node> graph, const URI& uri) void Serialiser::Impl::write_bundle(SPtr<const Node> graph, const URI& uri) { - std::string path = Glib::filename_from_uri(uri.string()); - if (Glib::file_test(path, Glib::FILE_TEST_EXISTS) - && !Glib::file_test(path, Glib::FILE_TEST_IS_DIR)) { - path = Glib::path_get_dirname(path); + FilePath path(uri.path()); + if (filesystem::exists(path) && !filesystem::is_directory(path)) { + path = path.parent_path(); } _world.log().info(fmt("Writing bundle %1%\n") % path); + filesystem::create_directories(path); - if (path.back() != '/') { - path.append("/"); - } - - g_mkdir_with_parents(path.c_str(), 0744); - - const string main_file = Glib::build_filename(path, "main.ttl"); + const FilePath main_file = path / "main.ttl"; const Raul::Path old_root_path = _root_path; start_to_file(graph->path(), main_file); std::set<const Resource*> plugins = serialise_graph( - graph, Sord::URI(_model->world(), main_file, _base_uri.string())); + graph, + Sord::URI(_model->world(), main_file.string(), _base_uri.string())); finish(); write_manifest(path, graph); @@ -221,20 +213,13 @@ Serialiser::Impl::write_bundle(SPtr<const Node> graph, const URI& uri) * This must be called before any serializing methods. */ void -Serialiser::Impl::start_to_file(const Raul::Path& root, const string& filename) +Serialiser::Impl::start_to_file(const Raul::Path& root, + const FilePath& filename) { - // Set Base URI - assert(filename.find(":") == string::npos || filename.substr(0, 5) == "file:"); - if (filename.find(":") == string::npos) { - _base_uri = URI("file://" + filename); - } else { - _base_uri = URI(filename); - } - - // Find graph basename to use as symbol / fallback name - _basename = Glib::path_get_basename(filename); + _base_uri = URI(filename); + _basename = filename.stem().string(); if (_basename == "main.ttl") { - _basename = Glib::path_get_basename(Glib::path_get_dirname(filename)); + _basename = filename.filename().parent_path().stem().string(); } _model = new Sord::Model(*_world.rdf_world(), _base_uri.string()); @@ -449,14 +434,14 @@ Serialiser::Impl::serialise_block(SPtr<const Node> block, serialise_properties(block_id, props); if (_base_uri.scheme() == "file") { - const std::string base = Glib::filename_from_uri(_base_uri.string()); - const std::string graph_dir = Glib::path_get_dirname(base); - const std::string state_dir = Glib::build_filename(graph_dir, block->symbol()); - const std::string state_file = Glib::build_filename(state_dir, "state.ttl"); + const FilePath base_path = _base_uri.file_path(); + const FilePath graph_dir = base_path.parent_path(); + const FilePath state_dir = graph_dir / block->symbol(); + const FilePath state_file = state_dir / "state.ttl"; if (block->save_state(state_dir)) { _model->add_statement(block_id, Sord::URI(_model->world(), uris.state_state), - Sord::URI(_model->world(), Glib::filename_to_uri(state_file))); + Sord::URI(_model->world(), URI(state_file))); } } diff --git a/src/URI.cpp b/src/URI.cpp index cc7dde46..a9c12223 100644 --- a/src/URI.cpp +++ b/src/URI.cpp @@ -16,6 +16,7 @@ #include <cassert> +#include "ingen/FilePath.hpp" #include "ingen/URI.hpp" namespace Ingen { @@ -47,6 +48,13 @@ URI::URI(const Sord::Node& node) assert(node.type() == Sord::Node::URI); } +URI::URI(const FilePath& path) + : _node(serd_node_new_file_uri((const uint8_t*)path.c_str(), + NULL, + &_uri, + true)) +{} + URI::URI(const URI& uri) : _node(serd_node_new_uri(&uri._uri, NULL, &_uri)) {} diff --git a/src/World.cpp b/src/World.cpp index 7834c3df..25e13873 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -17,8 +17,6 @@ #include <map> #include <string> -#include <glibmm/fileutils.h> -#include <glibmm/miscutils.h> #include <glibmm/module.h> #include "ingen/Configuration.hpp" @@ -34,6 +32,7 @@ #include "ingen/URIMap.hpp" #include "ingen/URIs.hpp" #include "ingen/World.hpp" +#include "ingen/filesystem.hpp" #include "ingen/ingen.h" #include "ingen/runtime_paths.hpp" #include "lilv/lilv.h" @@ -63,14 +62,13 @@ ingen_load_module(Log& log, const string& name) Glib::Module* module = nullptr; // Search INGEN_MODULE_PATH first - bool module_path_found; - string module_path = Glib::getenv("INGEN_MODULE_PATH", module_path_found); - if (module_path_found) { + const char* const module_path = getenv("INGEN_MODULE_PATH"); + if (module_path) { string dir; std::istringstream iss(module_path); - while (getline(iss, dir, G_SEARCHPATH_SEPARATOR)) { - string filename = Ingen::module_path(name, dir); - if (Glib::file_test(filename, Glib::FILE_TEST_EXISTS)) { + while (getline(iss, dir, search_path_separator)) { + FilePath filename = Ingen::ingen_module_path(name, FilePath(dir)); + if (filesystem::exists(filename)) { module = new Glib::Module(filename); if (*module) { return module; @@ -82,11 +80,11 @@ ingen_load_module(Log& log, const string& name) } // Try default directory if not found - module = new Glib::Module(Ingen::module_path(name)); + module = new Glib::Module(Ingen::ingen_module_path(name)); if (*module) { return module; - } else if (!module_path_found) { + } else if (!module_path) { log.error(fmt("Unable to find %1% (%2%)\n") % name % Glib::Module::get_last_error()); return nullptr; diff --git a/src/gui/LoadGraphWindow.cpp b/src/gui/LoadGraphWindow.cpp index 10ddf436..b02ca510 100644 --- a/src/gui/LoadGraphWindow.cpp +++ b/src/gui/LoadGraphWindow.cpp @@ -88,9 +88,9 @@ LoadGraphWindow::LoadGraphWindow(BaseObjectType* cobject, property_select_multiple() = true; // Add global examples directory to "shortcut folders" (bookmarks) - const std::string examples_dir = Ingen::data_file_path("graphs"); + const FilePath examples_dir = Ingen::data_file_path("graphs"); if (Glib::file_test(examples_dir, Glib::FILE_TEST_IS_DIR)) { - add_shortcut_folder(examples_dir); + add_shortcut_folder(examples_dir.string()); } } @@ -175,7 +175,7 @@ LoadGraphWindow::ok_clicked() } _app->loader()->load_graph( - true, get_filename(), parent, symbol, _initial_data); + true, FilePath(get_filename()), parent, symbol, _initial_data); } else { std::list<Glib::ustring> uri_list = get_filenames(); @@ -194,7 +194,7 @@ LoadGraphWindow::ok_clicked() symbol = avoid_symbol_clash(symbol); _app->loader()->load_graph( - false, u, _graph->path(), symbol, _initial_data); + false, FilePath(URI(u).path()), _graph->path(), symbol, _initial_data); } } diff --git a/src/gui/ThreadedLoader.cpp b/src/gui/ThreadedLoader.cpp index 891502f7..7a80fa6e 100644 --- a/src/gui/ThreadedLoader.cpp +++ b/src/gui/ThreadedLoader.cpp @@ -46,7 +46,9 @@ ThreadedLoader::~ThreadedLoader() { _exit_flag = true; _sem.post(); - _thread.join(); + if (_thread.joinable()) { + _thread.join(); + } } SPtr<Parser> @@ -59,23 +61,22 @@ void ThreadedLoader::run() { while (_sem.wait() && !_exit_flag) { - _mutex.lock(); + std::lock_guard<std::mutex> lock(_mutex); while (!_events.empty()) { _events.front()(); _events.pop_front(); } - _mutex.unlock(); } } void ThreadedLoader::load_graph(bool merge, - const Glib::ustring& document_uri, + const FilePath& file_path, optional<Raul::Path> engine_parent, optional<Raul::Symbol> engine_symbol, optional<Properties> engine_data) { - _mutex.lock(); + std::lock_guard<std::mutex> lock(_mutex); Glib::ustring engine_base = ""; if (engine_parent) { @@ -88,17 +89,16 @@ ThreadedLoader::load_graph(bool merge, _events.push_back(sigc::hide_return( sigc::bind(sigc::mem_fun(this, &ThreadedLoader::load_graph_event), - document_uri, + file_path, engine_parent, engine_symbol, engine_data))); - _mutex.unlock(); _sem.post(); } void -ThreadedLoader::load_graph_event(const Glib::ustring& document_uri, +ThreadedLoader::load_graph_event(const FilePath& file_path, optional<Raul::Path> engine_parent, optional<Raul::Symbol> engine_symbol, optional<Properties> engine_data) @@ -107,7 +107,7 @@ ThreadedLoader::load_graph_event(const Glib::ustring& document_uri, _app.world()->parser()->parse_file(_app.world(), _app.world()->interface().get(), - document_uri, + file_path, engine_parent, engine_symbol, engine_data); @@ -116,14 +116,13 @@ ThreadedLoader::load_graph_event(const Glib::ustring& document_uri, void ThreadedLoader::save_graph(SPtr<const Client::GraphModel> model, const URI& uri) { - _mutex.lock(); + std::lock_guard<std::mutex> lock(_mutex); _events.push_back(sigc::hide_return( sigc::bind(sigc::mem_fun(this, &ThreadedLoader::save_graph_event), model, uri))); - _mutex.unlock(); _sem.post(); } diff --git a/src/gui/ThreadedLoader.hpp b/src/gui/ThreadedLoader.hpp index 64968230..79ef6466 100644 --- a/src/gui/ThreadedLoader.hpp +++ b/src/gui/ThreadedLoader.hpp @@ -21,11 +21,12 @@ #include <cassert> #include <list> +#include <mutex> #include <string> #include <boost/optional.hpp> -#include <glibmm/thread.h> +#include "ingen/FilePath.hpp" #include "ingen/Interface.hpp" #include "ingen/Parser.hpp" #include "ingen/Serialiser.hpp" @@ -57,7 +58,7 @@ public: ~ThreadedLoader(); void load_graph(bool merge, - const Glib::ustring& document_uri, + const FilePath& file_path, boost::optional<Raul::Path> engine_parent, boost::optional<Raul::Symbol> engine_symbol, boost::optional<Properties> engine_data); @@ -67,7 +68,7 @@ public: SPtr<Parser> parser(); private: - void load_graph_event(const Glib::ustring& document_uri, + void load_graph_event(const FilePath& file_path, boost::optional<Raul::Path> engine_parent, boost::optional<Raul::Symbol> engine_symbol, boost::optional<Properties> engine_data); @@ -83,7 +84,7 @@ private: App& _app; Raul::Semaphore _sem; SPtr<Interface> _engine; - Glib::Mutex _mutex; + std::mutex _mutex; std::list<Closure> _events; bool _exit_flag; std::thread _thread; diff --git a/src/runtime_paths.cpp b/src/runtime_paths.cpp index bc3bf302..8dbe5c0c 100644 --- a/src/runtime_paths.cpp +++ b/src/runtime_paths.cpp @@ -16,20 +16,34 @@ #include <climits> #include <cstdlib> +#include <cstdlib> +#include <sstream> #include <string> #include <dlfcn.h> -#include <glibmm/module.h> -#include <glibmm/miscutils.h> - #include "ingen/runtime_paths.hpp" +#include "ingen/FilePath.hpp" #include "ingen_config.h" namespace Ingen { -static std::string bundle_path; +static FilePath bundle_path; + +#if defined(__APPLE__) +const char search_path_separator = ':'; +static const char* const library_prefix = "lib"; +static const char* const library_suffix = ".dylib"; +#elif defined(_WIN32) && !defined(__CYGWIN__) +const char search_path_separator = ';'; +static const char* const library_prefix = ""; +static const char* const library_suffix = ".dll"; +#else +const char search_path_separator = ':'; +static const char* const library_prefix = "lib"; +static const char* const library_suffix = ".so"; +#endif /** 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). @@ -48,59 +62,85 @@ set_bundle_path_from_code(void* function) const char* bin_loc = dli.dli_fname; #endif - std::string bundle = bin_loc; - bundle = bundle.substr(0, bundle.find_last_of(G_DIR_SEPARATOR)); - bundle_path = bundle; + bundle_path = FilePath(bin_loc).parent_path(); } void set_bundle_path(const char* path) { - bundle_path = path; + bundle_path = FilePath(path); } /** Return the absolute path of a file in an Ingen LV2 bundle */ -std::string +FilePath bundle_file_path(const std::string& name) { - return Glib::build_filename(bundle_path, name); + return bundle_path / name; } /** Return the absolute path of a 'resource' file. */ -std::string +FilePath data_file_path(const std::string& name) { #ifdef BUNDLE - return Glib::build_filename(bundle_path, Glib::build_path(INGEN_DATA_DIR, name)); + return bundle_path / INGEN_DATA_DIR / name; #else - return Glib::build_filename(INGEN_DATA_DIR, name); + return FilePath(INGEN_DATA_DIR) / name; #endif } /** Return the absolute path of a module (dynamically loaded shared library). */ -std::string -module_path(const std::string& name, std::string dir) +FilePath +ingen_module_path(const std::string& name, FilePath dir) { - std::string ret; - if (dir == "") { + FilePath ret; + if (dir.empty()) { #ifdef BUNDLE - dir = Glib::build_path(bundle_path, INGEN_MODULE_DIR); + dir = FilePath(bundle_path) / INGEN_MODULE_DIR; #else - dir = INGEN_MODULE_DIR; + dir = FilePath(INGEN_MODULE_DIR); #endif } - ret = Glib::Module::build_path(dir, std::string("ingen_") + name); + return dir / + (std::string(library_prefix) + "ingen_" + name + library_suffix); +} -#ifdef __APPLE__ - // MacPorts glib doesnt seem to do portable path building correctly... - if (ret.substr(ret.length() - 3) == ".so") - ret = ret.substr(0, ret.length() - 2).append("dylib"); -#endif - return ret; +FilePath +user_config_dir() +{ + const char* const xdg_config_home = getenv("XDG_CONFIG_HOME"); + const char* const home = getenv("HOME"); + + if (xdg_config_home) { + return FilePath(xdg_config_home); + } else if (home) { + return FilePath(home) / ".config"; + } + + return FilePath(); +} + +std::vector<FilePath> +system_config_dirs() +{ + const char* const xdg_config_dirs = getenv("XDG_CONFIG_DIRS"); + + 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"); + } + + return paths; } } // namespace Ingen diff --git a/src/server/LV2Block.cpp b/src/server/LV2Block.cpp index 53bed410..f4792f39 100644 --- a/src/server/LV2Block.cpp +++ b/src/server/LV2Block.cpp @@ -18,9 +18,6 @@ #include <cmath> #include <cstdint> -#include <glibmm/miscutils.h> -#include <glibmm/convert.h> - #include "lv2/lv2plug.in/ns/ext/morph/morph.h" #include "lv2/lv2plug.in/ns/ext/presets/presets.h" #include "lv2/lv2plug.in/ns/ext/options/options.h" @@ -30,7 +27,9 @@ #include "raul/Maid.hpp" #include "raul/Array.hpp" +#include "ingen/FilePath.hpp" #include "ingen/Log.hpp" +#include "ingen/URI.hpp" #include "ingen/URIMap.hpp" #include "ingen/URIs.hpp" #include "ingen/World.hpp" @@ -460,7 +459,7 @@ LV2Block::instantiate(BufferFactory& bufs, const LilvState* state) } bool -LV2Block::save_state(const std::string& dir) const +LV2Block::save_state(const FilePath& dir) const { World* world = _lv2_plugin->world(); LilvWorld* lworld = world->lilv_world(); @@ -623,11 +622,11 @@ LV2Block::load_preset(const URI& uri) } LilvState* -LV2Block::load_state(World* world, const std::string& path) +LV2Block::load_state(World* world, const FilePath& path) { - LilvWorld* lworld = world->lilv_world(); - const std::string uri = Glib::filename_to_uri(path); - LilvNode* subject = lilv_new_uri(lworld, uri.c_str()); + LilvWorld* lworld = world->lilv_world(); + const URI uri = URI(path); + LilvNode* subject = lilv_new_uri(lworld, uri.c_str()); LilvState* state = lilv_state_new_from_file( lworld, @@ -685,9 +684,9 @@ LV2Block::save_preset(const URI& uri, LV2_URID_Map* lmap = &world->uri_map().urid_map_feature()->urid_map; LV2_URID_Unmap* lunmap = &world->uri_map().urid_unmap_feature()->urid_unmap; - const std::string path = Glib::filename_from_uri(uri.string()); - const std::string dirname = Glib::path_get_dirname(path); - const std::string basename = Glib::path_get_basename(path); + const FilePath path = FilePath(uri.path()); + const FilePath dirname = path.parent_path(); + const FilePath basename = path.stem(); LilvState* state = lilv_state_new_from_instance( _lv2_plugin->lilv_plugin(), instance(0), lmap, @@ -715,8 +714,8 @@ LV2Block::save_preset(const URI& uri, preset.set_property(_uris.lv2_appliesTo, world->forge().make_urid(_lv2_plugin->uri())); - LilvNode* lbundle = lilv_new_uri( - lworld, Glib::filename_to_uri(dirname + "/").c_str()); + const std::string bundle_uri = URI(dirname).string() + '/'; + LilvNode* lbundle = lilv_new_uri(lworld, bundle_uri.c_str()); lilv_world_load_bundle(lworld, lbundle); lilv_node_free(lbundle); diff --git a/src/server/LV2Block.hpp b/src/server/LV2Block.hpp index eec852a2..f3a59550 100644 --- a/src/server/LV2Block.hpp +++ b/src/server/LV2Block.hpp @@ -51,7 +51,7 @@ public: bool instantiate(BufferFactory& bufs, const LilvState* state); LilvInstance* instance() { return instance(0); } - bool save_state(const std::string& dir) const; + bool save_state(const FilePath& dir) const; BlockImpl* duplicate(Engine& engine, const Raul::Symbol& symbol, @@ -80,7 +80,7 @@ public: BufferRef buf, SampleCount offset); - static LilvState* load_state(World* world, const std::string& path); + static LilvState* load_state(World* world, const FilePath& path); protected: struct Instance : public Raul::Noncopyable { diff --git a/src/server/events/CreateBlock.cpp b/src/server/events/CreateBlock.cpp index fc0c0f5e..d678bea3 100644 --- a/src/server/events/CreateBlock.cpp +++ b/src/server/events/CreateBlock.cpp @@ -119,7 +119,8 @@ CreateBlock::pre_process(PreProcessContext& ctx) LilvState* state = nullptr; auto s = _properties.find(uris.state_state); if (s != _properties.end() && s->second.type() == uris.forge.Path) { - state = LV2Block::load_state(_engine.world(), s->second.ptr<char>()); + state = LV2Block::load_state( + _engine.world(), FilePath(s->second.ptr<char>())); } // Instantiate plugin diff --git a/src/server/events/Delta.cpp b/src/server/events/Delta.cpp index 56cc22aa..b23ae884 100644 --- a/src/server/events/Delta.cpp +++ b/src/server/events/Delta.cpp @@ -17,8 +17,6 @@ #include <vector> #include <thread> -#include <glibmm/convert.h> - #include "ingen/Log.hpp" #include "ingen/Store.hpp" #include "ingen/URIs.hpp" @@ -366,15 +364,17 @@ Delta::pre_process(PreProcessContext& ctx) _status = Status::BAD_VALUE_TYPE; } } else if (key == uris.pset_preset) { - std::string uri_str; + URI uri; if (uris.forge.is_uri(value)) { - uri_str = uris.forge.str(value, false); + const std::string uri_str = uris.forge.str(value, false); + if (URI::is_valid(uri_str)) { + uri = URI(uri_str); + } } else if (value.type() == uris.forge.Path) { - uri_str = Glib::filename_to_uri(value.ptr<char>()); + uri = URI(FilePath(value.ptr<char>())); } - if (URI::is_valid(uri_str)) { - const URI uri(uri_str); + if (!uri.empty()) { op = SpecialType::PRESET; if ((_state = block->load_preset(uri))) { lilv_state_emit_port_values( diff --git a/src/wscript b/src/wscript index 5429ba26..82055ac9 100644 --- a/src/wscript +++ b/src/wscript @@ -8,6 +8,7 @@ def build(bld): 'ClashAvoider.cpp', 'ColorContext.cpp', 'Configuration.cpp', + 'FilePath.cpp', 'Forge.cpp', 'LV2Features.cpp', 'Log.cpp', |