aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2018-01-21 00:41:34 +0100
committerDavid Robillard <d@drobilla.net>2018-01-21 00:56:50 +0100
commita99b72e4adbc4c28fadc08d29299d99405f72db9 (patch)
treefb21f2cea8f5db1dc187cdbdd01f43e73bbddfff /src
parent329f498d901f9be9c0c820749850f5277a17df5d (diff)
downloadingen-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.cpp41
-rw-r--r--src/FilePath.cpp242
-rw-r--r--src/Parser.cpp56
-rw-r--r--src/Serialiser.cpp77
-rw-r--r--src/URI.cpp8
-rw-r--r--src/World.cpp18
-rw-r--r--src/gui/LoadGraphWindow.cpp8
-rw-r--r--src/gui/ThreadedLoader.cpp21
-rw-r--r--src/gui/ThreadedLoader.hpp9
-rw-r--r--src/runtime_paths.cpp92
-rw-r--r--src/server/LV2Block.cpp25
-rw-r--r--src/server/LV2Block.hpp4
-rw-r--r--src/server/events/CreateBlock.cpp3
-rw-r--r--src/server/events/Delta.cpp14
-rw-r--r--src/wscript1
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',