diff options
-rw-r--r-- | ingen/Parser.hpp | 23 | ||||
-rw-r--r-- | src/Parser.cpp | 91 | ||||
-rw-r--r-- | src/ingen/ingen.cpp | 3 | ||||
-rw-r--r-- | src/server/ingen_lv2.cpp | 43 |
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; |