summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ingen/Parser.hpp23
-rw-r--r--src/Parser.cpp91
-rw-r--r--src/ingen/ingen.cpp3
-rw-r--r--src/server/ingen_lv2.cpp43
4 files changed, 110 insertions, 50 deletions
diff --git a/ingen/Parser.hpp b/ingen/Parser.hpp
index f5045848..59783459 100644
--- a/ingen/Parser.hpp
+++ b/ingen/Parser.hpp
@@ -18,7 +18,7 @@
#define INGEN_PARSER_HPP
#include <string>
-#include <list>
+#include <set>
#include <boost/optional.hpp>
@@ -26,6 +26,7 @@
#include "ingen/ingen.h"
#include "raul/Path.hpp"
#include "raul/URI.hpp"
+#include "sord/sordmm.hpp"
namespace Ingen {
@@ -45,6 +46,26 @@ public:
typedef Node::Properties Properties;
+ /** Record of a resource listed in a bundle manifest. */
+ struct ResourceRecord {
+ inline ResourceRecord(const std::string& u, const std::string& f)
+ : uri(u), filename(f)
+ {}
+
+ inline bool operator<(const ResourceRecord& r) const {
+ return uri < r.uri;
+ }
+
+ std::string uri; ///< URI of resource (e.g. a Graph)
+ std::string filename; ///< Path of describing file (seeAlso)
+ };
+
+ /** Find all resources of a given type listed in a manifest file. */
+ virtual std::set<ResourceRecord> find_resources(
+ Sord::World& world,
+ const std::string& manifest_uri,
+ const Raul::URI& type_uri);
+
virtual bool parse_file(
World* world,
Interface* target,
diff --git a/src/Parser.cpp b/src/Parser.cpp
index b0bf88e6..30de26ba 100644
--- a/src/Parser.cpp
+++ b/src/Parser.cpp
@@ -35,12 +35,46 @@
#include "sord/sordmm.hpp"
#include "sratom/sratom.h"
-using namespace std;
+#define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+#define NS_RDFS "http://www.w3.org/2000/01/rdf-schema#"
-typedef set<Sord::Node> RDFNodes;
+using namespace std;
namespace Ingen {
+std::set<Parser::ResourceRecord>
+Parser::find_resources(Sord::World& world,
+ const std::string& manifest_uri,
+ const Raul::URI& type_uri)
+{
+ const Sord::URI base (world, manifest_uri);
+ const Sord::URI type (world, type_uri);
+ const Sord::URI rdf_type (world, NS_RDF "type");
+ const Sord::URI rdfs_seeAlso(world, NS_RDFS "seeAlso");
+ const Sord::Node nil;
+
+ SerdEnv* env = serd_env_new(sord_node_to_serd_node(base.c_obj()));
+ Sord::Model model(world, manifest_uri);
+ model.load_file(env, SERD_TURTLE, manifest_uri);
+
+ std::set<ResourceRecord> resources;
+ for (Sord::Iter i = model.find(nil, rdf_type, type); !i.end(); ++i) {
+ const Sord::Node resource = i.get_subject();
+ const std::string resource_uri = resource.to_c_string();
+ std::string file_path = "";
+ Sord::Iter f = model.find(resource, rdfs_seeAlso, nil);
+ if (!f.end()) {
+ uint8_t* p = serd_file_uri_parse(f.get_object().to_u_string(), NULL);
+ file_path = (const char*)p;
+ free(p);
+ }
+ resources.insert(ResourceRecord(resource.to_string(), file_path));
+ }
+
+ serd_env_free(env);
+ return resources;
+}
+
static std::string
relative_uri(const std::string& base, const std::string& uri, bool leading_slash)
{
@@ -326,6 +360,8 @@ parse_graph(Ingen::World* world,
graph_path_str = parent->child(*a_symbol);
} else if (parent) {
graph_path_str = *parent;
+ } else {
+ graph_path_str = "/";
}
if (!Raul::Path::is_valid(graph_path_str)) {
@@ -570,35 +606,56 @@ Parser::parse_file(Ingen::World* world,
boost::optional<Raul::Symbol> symbol,
boost::optional<Node::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);
}
- if (Glib::file_test(file_path, Glib::FILE_TEST_IS_DIR)) {
- // This is a bundle, append "/name.ttl" to get graph file path
- file_path = Glib::build_filename(path, get_basename(path) + ".ttl");
- }
- std::string uri;
+ // 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);
+
+ std::string manifest_uri;
try {
- uri = Glib::filename_to_uri(file_path, "");
+ manifest_uri = Glib::filename_to_uri(manifest_path);
} catch (const Glib::ConvertError& e) {
- world->log().error(fmt("Path to URI conversion error: %1%\n")
- % e.what());
+ world->log().error(fmt("URI conversion error (%1%)\n") % e.what());
return false;
}
- 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);
+ // Find graphs in manifest
+ const std::set<ResourceRecord> resources = find_resources(
+ *world->rdf_world(),
+ Glib::filename_to_uri(manifest_path),
+ Raul::URI(INGEN__Graph));
- // Load graph file into model
- Sord::Model model(*world->rdf_world(), uri, SORD_SPO|SORD_PSO, false);
- model.load_file(env, SERD_TURTLE, uri);
+ if (resources.empty()) {
+ world->log().error(fmt("No graphs found in %1%\n") % path);
+ return false;
+ }
+
+ // Choose the first (only) graph (only one top-level graph per bundle)
+ const std::string& uri = (*resources.begin()).uri;
+ if ((file_path = (*resources.begin()).filename).empty()) {
+ // No seeAlso file, use "manifest" (probably the graph file itself)
+ file_path = manifest_path;
+ }
+ // 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);
+
+ // Load graph into model
+ Sord::Model model(*world->rdf_world(), uri, SORD_SPO|SORD_PSO, false);
+ model.load_file(env, SERD_TURTLE, file_uri);
serd_env_free(env);
- world->log().info(fmt("Parsing %1%\n") % file_path);
+ world->log().info(fmt("Loading %1% from %2%\n") % uri % file_path);
if (parent)
world->log().info(fmt("Parent: %1%\n") % parent->c_str());
if (symbol)
diff --git a/src/ingen/ingen.cpp b/src/ingen/ingen.cpp
index 1c6f8af6..53fda208 100644
--- a/src/ingen/ingen.cpp
+++ b/src/ingen/ingen.cpp
@@ -144,8 +144,7 @@ main(int argc, char** argv)
world->set_interface(engine_interface);
- // Load necessary modules before activating engine (and Jack driver)
-
+ // Load GUI if requested
if (conf.option("gui").get<int32_t>()) {
ingen_try(world->load_module("gui"),
"Unable to load GUI module");
diff --git a/src/server/ingen_lv2.cpp b/src/server/ingen_lv2.cpp
index 6aa7bfc4..9e4b76fa 100644
--- a/src/server/ingen_lv2.cpp
+++ b/src/server/ingen_lv2.cpp
@@ -59,12 +59,10 @@
namespace Ingen {
/** Record of a graph in this bundle. */
-struct LV2Graph {
- LV2Graph(const std::string& u, const std::string& f);
+struct LV2Graph : public Parser::ResourceRecord {
+ LV2Graph(const Parser::ResourceRecord& record);
- const std::string uri;
- const std::string filename;
- LV2_Descriptor descriptor;
+ LV2_Descriptor descriptor;
};
/** Ingen LV2 library. */
@@ -455,33 +453,19 @@ struct IngenPlugin {
static Lib::Graphs
find_graphs(const std::string& manifest_uri)
{
- Sord::World world;
- const Sord::URI base(world, manifest_uri);
- const Sord::Node nil;
- const Sord::URI ingen_Graph (world, INGEN__Graph);
- const Sord::URI rdf_type (world, NS_RDF "type");
- const Sord::URI rdfs_seeAlso(world, NS_RDFS "seeAlso");
+ Sord::World world;
+ Parser parser;
- SerdEnv* env = serd_env_new(sord_node_to_serd_node(base.c_obj()));
- Sord::Model model(world, manifest_uri);
- model.load_file(env, SERD_TURTLE, manifest_uri);
+ const std::set<Parser::ResourceRecord> resources = parser.find_resources(
+ world,
+ manifest_uri,
+ Raul::URI(INGEN__Graph));
Lib::Graphs graphs;
- for (Sord::Iter i = model.find(nil, rdf_type, ingen_Graph); !i.end(); ++i) {
- const Sord::Node graph = i.get_subject();
- Sord::Iter f = model.find(graph, rdfs_seeAlso, nil);
- const std::string graph_uri = graph.to_c_string();
- if (!f.end()) {
- const uint8_t* file_uri = f.get_object().to_u_string();
- uint8_t* file_path = serd_file_uri_parse(file_uri, NULL);
- graphs.push_back(
- SPtr<const LV2Graph>(
- new LV2Graph(graph_uri, (const char*)file_path)));
- free(file_path);
- }
+ for (const auto& r : resources) {
+ graphs.push_back(SPtr<const LV2Graph>(new LV2Graph(r)));
}
- serd_env_free(env);
return graphs;
}
@@ -805,9 +789,8 @@ ingen_extension_data(const char* uri)
return NULL;
}
-LV2Graph::LV2Graph(const std::string& u, const std::string& f)
- : uri(u)
- , filename(f)
+LV2Graph::LV2Graph(const Parser::ResourceRecord& record)
+ : Parser::ResourceRecord(record)
{
descriptor.URI = uri.c_str();
descriptor.instantiate = ingen_instantiate;