From 5ecd4d401e50eb3f86461eb48e41a01c1d40da55 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 3 Apr 2015 06:11:55 +0000 Subject: Fix loading graphs with explicit/non-file URIs. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@5650 a436a847-0d15-0410-975c-d299462d15a1 --- src/Parser.cpp | 91 +++++++++++++++++++++++++++++++++++++++--------- src/ingen/ingen.cpp | 3 +- src/server/ingen_lv2.cpp | 43 +++++++---------------- 3 files changed, 88 insertions(+), 49 deletions(-) (limited to 'src') 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 RDFNodes; +using namespace std; namespace Ingen { +std::set +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 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 symbol, boost::optional 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 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()) { 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 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( - new LV2Graph(graph_uri, (const char*)file_path))); - free(file_path); - } + for (const auto& r : resources) { + graphs.push_back(SPtr(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; -- cgit v1.2.1