diff options
-rw-r--r-- | bundles/ingen.lv2/ingen.ttl | 12 | ||||
-rw-r--r-- | ingen/shared/URIs.hpp | 1 | ||||
-rw-r--r-- | src/client/ClientStore.cpp | 6 | ||||
-rw-r--r-- | src/gui/PatchCanvas.cpp | 69 | ||||
-rw-r--r-- | src/serialisation/Parser.cpp | 129 | ||||
-rw-r--r-- | src/serialisation/Serialiser.cpp | 12 | ||||
-rw-r--r-- | src/shared/URIs.cpp | 1 |
7 files changed, 125 insertions, 105 deletions
diff --git a/bundles/ingen.lv2/ingen.ttl b/bundles/ingen.lv2/ingen.ttl index 95c26836..71124bb8 100644 --- a/bundles/ingen.lv2/ingen.ttl +++ b/bundles/ingen.lv2/ingen.ttl @@ -111,18 +111,6 @@ ingen:enabled rdfs:label "Enabled" ; rdfs:comment "Signifies the node is or should be running." . -ingen:Port - a owl:Class ; - rdfs:subClassOf ingen:Object ; - rdfs:label "Port" ; - rdfs:comment """ -A Port is an input or output on a Node. It is implicitly an instance of the -corresponding port on that Node's plugin (specified with ingen:prototype). -A Port MUST have a legal lv2:symbol in the exact way a Node must, see :Node -documentation for details. Ports inherit properties from the Port on their -parent's Plugin in the exact way Nodes inherit properties from their Plugin. -""" . - ingen:Edge a owl:Class ; rdfs:label "Edge" ; diff --git a/ingen/shared/URIs.hpp b/ingen/shared/URIs.hpp index 545a2bf0..0fd2cbdc 100644 --- a/ingen/shared/URIs.hpp +++ b/ingen/shared/URIs.hpp @@ -73,7 +73,6 @@ public: const Quark ingen_Internal; const Quark ingen_Node; const Quark ingen_Patch; - const Quark ingen_Port; const Quark ingen_activity; const Quark ingen_broadcast; const Quark ingen_canvasX; diff --git a/src/client/ClientStore.cpp b/src/client/ClientStore.cpp index a78653e5..75acef63 100644 --- a/src/client/ClientStore.cpp +++ b/src/client/ClientStore.cpp @@ -459,9 +459,11 @@ ClientStore::attempt_connection(const Raul::Path& tail_path, patch->add_edge(cm); return true; + } else { + LOG(Raul::warn) << "Failed to connect " << tail_path + << " => " << head_path << std::endl; + return false; } - - return false; } void diff --git a/src/gui/PatchCanvas.cpp b/src/gui/PatchCanvas.cpp index 3562a007..640051cb 100644 --- a/src/gui/PatchCanvas.cpp +++ b/src/gui/PatchCanvas.cpp @@ -637,42 +637,56 @@ PatchCanvas::destroy_selection() for_each_selected_edge(destroy_edge, &_app); } -void -PatchCanvas::copy_selection() +static void +serialise_node(GanvNode* node, void* data) { - std::cerr << "FIXME: copy" << std::endl; - #if 0 - static const char* base_uri = ""; - Serialiser serialiser(*_app.world(), _app.store()); - serialiser.start_to_string(_patch->path(), base_uri); + Serialisation::Serialiser* serialiser = (Serialisation::Serialiser*)data; + if (!GANV_IS_MODULE(node)) { + return; + } - FOREACH_ITEM(m, selected_items()) { - NodeModule* module = dynamic_cast<NodeModule*>(*m); - if (module) { - serialiser.serialise(module->node()); - } else { - PatchPortModule* port_module = dynamic_cast<PatchPortModule*>(*m); - if (port_module) - serialiser.serialise(port_module->port()); + Ganv::Module* module = Glib::wrap(GANV_MODULE(node)); + NodeModule* node_module = dynamic_cast<NodeModule*>(module); + + if (node_module) { + serialiser->serialise(node_module->node()); + } else { + PatchPortModule* port_module = dynamic_cast<PatchPortModule*>(module); + if (port_module) { + serialiser->serialise(port_module->port()); } } +} - for (SelectedEdges::const_iterator c = selected_edges().begin(); - c != selected_edges().end(); ++c) { - Edge* const edge = dynamic_cast<Edge*>(*c); - if (edge) { - const Sord::URI subject(*_app.world()->rdf_world(), - base_uri); - serialiser.serialise_edge(subject, edge->model()); - } +static void +serialise_edge(GanvEdge* edge, void* data) +{ + Serialisation::Serialiser* serialiser = (Serialisation::Serialiser*)data; + if (!GANV_IS_EDGE(edge)) { + return; + } + + GUI::Edge* gedge = dynamic_cast<GUI::Edge*>(Glib::wrap(GANV_EDGE(edge))); + if (gedge) { + serialiser->serialise_edge(Sord::Node(), gedge->model()); } +} + +void +PatchCanvas::copy_selection() +{ + static const char* base_uri = "http://drobilla.net/ns/ingen/selection/"; + Serialisation::Serialiser serialiser(*_app.world()); + serialiser.start_to_string(_patch->path(), base_uri); + + for_each_selected_node(serialise_node, &serialiser); + for_each_selected_edge(serialise_edge, &serialiser); - string result = serialiser.finish(); + const std::string result = serialiser.finish(); _paste_count = 0; Glib::RefPtr<Gtk::Clipboard> clipboard = Gtk::Clipboard::get(); clipboard->set_text(result); - #endif } void @@ -702,7 +716,7 @@ PatchCanvas::paste() uris.ingen_Patch)); props.insert(make_pair(uris.ingen_polyphony, _app.forge().make(int32_t(_patch->internal_poly())))); - clipboard.put(Path(), props); + clipboard.put(Path("/"), props); size_t first_slash; while (to_create != "/" && !to_create.empty() && (first_slash = to_create.find("/")) != string::npos) { @@ -723,7 +737,8 @@ PatchCanvas::paste() } ClashAvoider avoider(*_app.store().get(), clipboard, &clipboard); - parser->parse_string(_app.world(), &avoider, str, "", + static const char* base_uri = "http://drobilla.net/ns/ingen/selection/"; + parser->parse_string(_app.world(), &avoider, str, base_uri, parent, symbol); for (Store::iterator i = clipboard.begin(); i != clipboard.end(); ++i) { diff --git a/src/serialisation/Parser.cpp b/src/serialisation/Parser.cpp index df17d7ff..2c56dc1e 100644 --- a/src/serialisation/Parser.cpp +++ b/src/serialisation/Parser.cpp @@ -177,6 +177,7 @@ parse( Interface* target, Sord::Model& model, Glib::ustring document_uri, + Sord::Node& subject, boost::optional<Raul::Path> parent = boost::optional<Raul::Path>(), boost::optional<Raul::Symbol> symbol = boost::optional<Raul::Symbol>(), boost::optional<Resource::Properties> data = boost::optional<Resource::Properties>()); @@ -397,49 +398,57 @@ parse_patch(Ingen::Shared::World* world, } static bool -parse_edges(Ingen::Shared::World* world, - Ingen::Interface* target, - Sord::Model& model, - const Sord::Node& subject, - const Raul::Path& parent) +parse_edge(Ingen::Shared::World* world, + Ingen::Interface* target, + Sord::Model& model, + const Sord::Node& subject, + const Raul::Path& parent) { - Sord::URI ingen_edge(*world->rdf_world(), NS_INGEN "edge"); Sord::URI ingen_tail(*world->rdf_world(), NS_INGEN "tail"); Sord::URI ingen_head(*world->rdf_world(), NS_INGEN "head"); + Sord::Iter t = model.find(subject, ingen_tail, nil); + Sord::Iter h = model.find(subject, ingen_head, nil); + const Glib::ustring& base_uri = model.base_uri().to_string(); - RDFNodes connections; - for (Sord::Iter i = model.find(subject, ingen_edge, nil); !i.end(); ++i) { - connections.insert(i.get_object()); + if (t.end()) { + LOG(error) << "Edge has no tail" << endl; + return false; + } else if (h.end()) { + LOG(error) << "Edge has no head" << endl; + return false; } - for (RDFNodes::const_iterator i = connections.begin(); i != connections.end(); ++i) { - Sord::Iter t = model.find(*i, ingen_tail, nil); - Sord::Iter h = model.find(*i, ingen_head, nil); + const Path tail_path( + parent.child(relative_uri(base_uri, t.get_object().to_string(), false))); + const Path head_path( + parent.child(relative_uri(base_uri, h.get_object().to_string(), false))); - if (t.end()) { - LOG(error) << "Edge has no tail" << endl; - return false; - } else if (h.end()) { - LOG(error) << "Edge has no head" << endl; - return false; - } + if (!(++t).end()) { + LOG(error) << "Edge has multiple tails" << endl; + return false; + } else if (!(++h).end()) { + LOG(error) << "Edge has multiple heads" << endl; + return false; + } - const Path tail_path( - parent.child(relative_uri(base_uri, t.get_object().to_string(), false))); - const Path head_path( - parent.child(relative_uri(base_uri, h.get_object().to_string(), false))); - - if (!(++t).end()) { - LOG(error) << "Edge has multiple tails" << endl; - return false; - } else if (!(++h).end()) { - LOG(error) << "Edge has multiple heads" << endl; - return false; - } + target->connect(tail_path, head_path); - target->connect(tail_path, head_path); + return true; +} + +static bool +parse_edges(Ingen::Shared::World* world, + Ingen::Interface* target, + Sord::Model& model, + const Sord::Node& subject, + const Raul::Path& parent) +{ + Sord::URI ingen_edge(*world->rdf_world(), NS_INGEN "edge"); + + for (Sord::Iter i = model.find(subject, ingen_edge, nil); !i.end(); ++i) { + parse_edge(world, target, model, i.get_object(), parent); } return true; @@ -469,24 +478,23 @@ parse(Ingen::Shared::World* world, Ingen::Interface* target, Sord::Model& model, Glib::ustring document_uri, + Sord::Node& subject, boost::optional<Raul::Path> parent, boost::optional<Raul::Symbol> symbol, boost::optional<GraphObject::Properties> data) { const Sord::URI patch_class (*world->rdf_world(), NS_INGEN "Patch"); const Sord::URI node_class (*world->rdf_world(), NS_INGEN "Node"); - const Sord::URI port_class (*world->rdf_world(), NS_INGEN "Port"); + const Sord::URI edge_class (*world->rdf_world(), NS_INGEN "Edge"); const Sord::URI internal_class(*world->rdf_world(), NS_INGEN "Internal"); const Sord::URI in_port_class (*world->rdf_world(), LV2_CORE__InputPort); const Sord::URI out_port_class(*world->rdf_world(), LV2_CORE__OutputPort); const Sord::URI lv2_class (*world->rdf_world(), LV2_CORE__Plugin); - const Sord::URI rdf_type (*world->rdf_world(), NS_RDF "type"); - - Sord::Node subject = model.base_uri(); + const Sord::URI rdf_type (*world->rdf_world(), NS_RDF "type"); - Raul::Path path("/"); - if (parent && symbol) { - path = parent->child(*symbol); + // Parse explicit subject patch + if (subject.is_valid()) { + return parse_patch(world, target, model, subject, parent, symbol, data); } // Get all subjects and their types (?subject a ?type) @@ -508,19 +516,23 @@ parse(Ingen::Shared::World* world, } // Parse and create each subject - boost::optional<Path> ret; for (Subjects::const_iterator i = subjects.begin(); i != subjects.end(); ++i) { - const Sord::Node& subject = i->first; - const std::set<Sord::Node>& types = i->second; + const Sord::Node& s = i->first; + const std::set<Sord::Node>& types = i->second; + boost::optional<Path> ret; + const Raul::Path path( + relative_uri( model.base_uri().to_string(), s.to_string(), true)); if (types.find(patch_class) != types.end()) { - ret = parse_patch(world, target, model, subject, parent, symbol, data); + ret = parse_patch(world, target, model, s, parent, symbol, data); } else if (types.find(node_class) != types.end()) { - ret = parse_node(world, target, model, - subject, path.child(subject.to_string()), - data); - } else if (types.find(port_class) != types.end()) { - parse_properties(world, target, model, subject, path, data); + ret = parse_node(world, target, model, s, path, data); + } else if (types.find(in_port_class) != types.end() || + types.find(out_port_class) != types.end()) { + parse_properties(world, target, model, s, path, data); ret = path; + } else if (types.find(edge_class) != types.end()) { + Path parent_path(parent ? parent.get() : Path("/")); + parse_edge(world, target, model, s, parent_path); } else { LOG(error) << "Subject has no known types" << endl; } @@ -533,11 +545,10 @@ parse(Ingen::Shared::World* world, LOG(error) << " :: " << *t << endl; assert((*t).is_uri()); } - return boost::optional<Path>(); } } - return path; + return boost::optional<Path>(); } Parser::Parser(Ingen::Shared::World& world) @@ -578,7 +589,7 @@ Parser::parse_file(Ingen::Shared::World* world, SerdEnv* env = serd_env_new(&base_node); // Load patch file into model - Sord::Model model(*world->rdf_world(), uri); + Sord::Model model(*world->rdf_world(), uri, SORD_SPO|SORD_PSO, false); model.load_file(env, SERD_TURTLE, uri); serd_env_free(env); @@ -589,8 +600,9 @@ Parser::parse_file(Ingen::Shared::World* world, if (symbol) LOG(Raul::info)(Raul::fmt("Symbol: %1%\n") % symbol->c_str()); + Sord::Node subject(*world->rdf_world(), Sord::Node::URI, uri); boost::optional<Path> parsed_path - = parse(world, target, model, path, parent, symbol, data); + = parse(world, target, model, path, subject, parent, symbol, data); if (parsed_path) { target->set_property(*parsed_path, "http://drobilla.net/ns/ingen#document", @@ -612,8 +624,10 @@ Parser::parse_string(Ingen::Shared::World* world, boost::optional<GraphObject::Properties> data) { // Load string into model - Sord::Model model(*world->rdf_world(), base_uri); - SerdEnv* env = serd_env_new(NULL); + Sord::Model model(*world->rdf_world(), base_uri, SORD_SPO|SORD_PSO, false); + const SerdNode base = serd_node_from_string( + SERD_URI, (const uint8_t*)base_uri.c_str()); + SerdEnv* env = serd_env_new(&base); model.load_string(env, SERD_TURTLE, str.c_str(), str.length(), base_uri); serd_env_free(env); @@ -622,11 +636,8 @@ Parser::parse_string(Ingen::Shared::World* world, info << " (base " << base_uri << ")"; info << endl; - bool ret = parse(world, target, model, base_uri, parent, symbol, data); - Sord::URI subject(*world->rdf_world(), base_uri); - parse_edges(world, target, model, subject, parent ? *parent : "/"); - - return ret; + Sord::Node subject; + return parse(world, target, model, base_uri, subject, parent, symbol, data); } } // namespace Serialisation diff --git a/src/serialisation/Serialiser.cpp b/src/serialisation/Serialiser.cpp index 6e126c42..6a674eb5 100644 --- a/src/serialisation/Serialiser.cpp +++ b/src/serialisation/Serialiser.cpp @@ -526,9 +526,15 @@ Serialiser::Impl::serialise_edge(const Sord::Node& parent, Sord::Curie(world, "ingen:head"), dst); - _model->add_statement(parent, - Sord::Curie(world, "ingen:edge"), - edge_id); + if (parent.is_valid()) { + _model->add_statement(parent, + Sord::Curie(world, "ingen:edge"), + edge_id); + } else { + _model->add_statement(edge_id, + Sord::Curie(world, "rdf:type"), + Sord::Curie(world, "ingen:Edge")); + } } static bool diff --git a/src/shared/URIs.cpp b/src/shared/URIs.cpp index 6cc32c0b..abb0a011 100644 --- a/src/shared/URIs.cpp +++ b/src/shared/URIs.cpp @@ -68,7 +68,6 @@ URIs::URIs(Shared::Forge& f, URIMap* map) , ingen_Internal (forge, map, NS_INGEN "Internal") , ingen_Node (forge, map, NS_INGEN "Node") , ingen_Patch (forge, map, NS_INGEN "Patch") - , ingen_Port (forge, map, NS_INGEN "Port") , ingen_activity (forge, map, NS_INGEN "activity") , ingen_broadcast (forge, map, NS_INGEN "broadcast") , ingen_canvasX (forge, map, NS_INGEN "canvasX") |