diff options
author | David Robillard <d@drobilla.net> | 2016-10-02 21:00:16 -0400 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2016-10-02 23:01:13 -0400 |
commit | 97d25d127249ebe8558c019a968fe43303bea3f6 (patch) | |
tree | dab8f68ee3b8091778c912408a13b001f7525ff4 | |
parent | a6c193970cd7944a4ff364ae9b3abf02a9e3034f (diff) | |
download | ingen-97d25d127249ebe8558c019a968fe43303bea3f6.tar.gz ingen-97d25d127249ebe8558c019a968fe43303bea3f6.tar.bz2 ingen-97d25d127249ebe8558c019a968fe43303bea3f6.zip |
Fix saving and loading subgraphs
-rw-r--r-- | src/Parser.cpp | 104 | ||||
-rw-r--r-- | src/Resource.cpp | 7 | ||||
-rw-r--r-- | src/Serialiser.cpp | 7 | ||||
-rw-r--r-- | src/gui/GraphCanvas.cpp | 2 | ||||
-rw-r--r-- | src/server/PortImpl.cpp | 4 |
5 files changed, 68 insertions, 56 deletions
diff --git a/src/Parser.cpp b/src/Parser.cpp index 5f9ae6e1..61495c9f 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -279,35 +279,32 @@ parse_block(Ingen::World* world, Sord::URI(*world->rdf_world(), uris.ingen_prototype) }; - std::string type_uri; - for (const Sord::URI& prototype : prototype_predicates) { - for (Sord::Iter p = model.find(subject, prototype, Sord::Node()); !p.end(); ++p) { - const std::string prot_uri = relative_uri( - base_uri, p.get_object().to_string(), false); - if (serd_uri_string_has_scheme((const uint8_t*)prot_uri.c_str())) { - /* Ignore prototypes that are relative to this bundle, they are - blocks (probably from copy and paste), but we want files or - LV2 plugins here. */ - type_uri = prot_uri; - break; - } + // Get prototype + Sord::Node prototype; + for (const Sord::URI& pred : prototype_predicates) { + prototype = model.get(subject, pred, Sord::Node()); + if (prototype.is_valid()) { + break; } } - if (type_uri.empty()) { + if (!prototype.is_valid()) { world->log().error( fmt("Block %1% (%2%) missing mandatory lv2:prototype\n") % subject.to_string() % path); return boost::optional<Raul::Path>(); } - if (!serd_uri_string_has_scheme((const uint8_t*)type_uri.c_str())) { + const uint8_t* type_uri = (const uint8_t*)prototype.to_string().c_str(); + if (!serd_uri_string_has_scheme(type_uri) || + !strncmp((const char*)type_uri, "file:", 5)) { + // Prototype is a file, subgraph SerdURI base_uri_parts; serd_uri_parse((const uint8_t*)base_uri.c_str(), &base_uri_parts); SerdURI ignored; SerdNode sub_uri = serd_node_new_uri_from_string( - (const uint8_t*)type_uri.c_str(), + type_uri, &base_uri_parts, &ignored); @@ -328,9 +325,10 @@ parse_block(Ingen::World* world, path.parent(), Raul::Symbol(path.symbol())); parse_graph(world, target, model, base_uri, - subject, Resource::Graph::DEFAULT, + subject, Resource::Graph::EXTERNAL, path.parent(), Raul::Symbol(path.symbol())); } else { + // Prototype is non-file URI, plugin Resource::Properties props = get_properties( world, model, subject, Resource::Graph::DEFAULT); props.insert(make_pair(uris.rdf_type, @@ -385,6 +383,41 @@ parse_graph(Ingen::World* world, Resource::Properties props = get_properties(world, model, subject_node, ctx); target->put(Node::path_to_uri(graph_path), props, ctx); + // For each port on this graph + typedef std::map<uint32_t, PortRecord> PortRecords; + PortRecords ports; + for (Sord::Iter p = model.find(graph, lv2_port, nil); !p.end(); ++p) { + Sord::Node port = p.get_object(); + + // Get all properties + uint32_t index = 0; + boost::optional<PortRecord> port_record = get_port( + world, model, port, ctx, graph_path, &index); + if (!port_record) { + world->log().error(fmt("Invalid port %1%\n") % port); + return boost::optional<Raul::Path>(); + } + + // Store port information in ports map + if (ports.find(index) == ports.end()) { + ports[index] = *port_record; + } else { + world->log().error(fmt("Ignored port %1% with duplicate index %2%\n") + % port % index); + } + } + + // Create ports in order by index + for (const auto& p : ports) { + target->put(Node::path_to_uri(p.second.first), + p.second.second, + ctx); + } + + if (ctx != Resource::Graph::INTERNAL) { + return graph_path; // Not parsing graph internals, finished now + } + // For each block in this graph for (Sord::Iter n = model.find(subject_node, ingen_block, nil); !n.end(); ++n) { Sord::Node node = n.get_object(); @@ -399,9 +432,16 @@ parse_graph(Ingen::World* world, for (Sord::Iter p = model.find(node, lv2_port, nil); !p.end(); ++p) { Sord::Node port = p.get_object(); + Resource::Graph subctx = Resource::Graph::DEFAULT; + if (!model.find(node, + Sord::URI(*world->rdf_world(), uris.rdf_type), + Sord::URI(*world->rdf_world(), uris.ingen_Graph)).end()) { + subctx = Resource::Graph::EXTERNAL; + } + // Get all properties boost::optional<PortRecord> port_record = get_port( - world, model, port, ctx, block_path, NULL); + world, model, port, subctx, block_path, NULL); if (!port_record) { world->log().error(fmt("Invalid port %1%\n") % port); return boost::optional<Raul::Path>(); @@ -409,36 +449,12 @@ parse_graph(Ingen::World* world, // Create port and/or set all port properties target->put(Node::path_to_uri(port_record->first), - port_record->second); + port_record->second, + subctx); } } - // For each port on this graph - typedef std::map<uint32_t, PortRecord> PortRecords; - PortRecords ports; - for (Sord::Iter p = model.find(graph, lv2_port, nil); !p.end(); ++p) { - Sord::Node port = p.get_object(); - - // Get all properties - uint32_t index = 0; - boost::optional<PortRecord> port_record = get_port( - world, model, port, ctx, graph_path, &index); - if (!port_record) { - world->log().error(fmt("Invalid port %1%\n") % port); - return boost::optional<Raul::Path>(); - } - - // Store port information in ports map - ports[index] = *port_record; - } - - // Create ports in order by index - for (const auto& p : ports) { - target->put(Node::path_to_uri(p.second.first), - p.second.second, - ctx); - } - + // Now that all ports and blocks exist, create arcs inside graph parse_arcs(world, target, model, base_uri, subject_node, graph_path); return graph_path; diff --git a/src/Resource.cpp b/src/Resource.cpp index eef5e063..f1cb12a1 100644 --- a/src/Resource.cpp +++ b/src/Resource.cpp @@ -211,14 +211,9 @@ Resource::remove_properties(const Properties& props) Resource::Properties Resource::properties(Resource::Graph ctx) const { - if (ctx == Resource::Graph::DEFAULT) { - return properties(); - } - Properties props; for (const auto& p : _properties) { - if (p.second.context() == Resource::Graph::DEFAULT - || p.second.context() == ctx) { + if (p.second.context() == ctx) { props.insert(make_pair(p.first, p.second)); } } diff --git a/src/Serialiser.cpp b/src/Serialiser.cpp index b0d760dc..37bd20c0 100644 --- a/src/Serialiser.cpp +++ b/src/Serialiser.cpp @@ -445,13 +445,13 @@ Serialiser::Impl::serialise_block(SPtr<const Node> block, Sord::URI(_model->world(), uris.lv2_prototype), class_id); - const Node::Properties props = block->properties(Resource::Graph::EXTERNAL); + const Node::Properties props = block->properties(); serialise_properties(block_id, props); for (uint32_t i = 0; i < block->num_ports(); ++i) { Node* const p = block->port(i); const Sord::Node port_id = path_rdf_node(p->path()); - serialise_port(p, Resource::Graph::EXTERNAL, port_id); + serialise_port(p, Resource::Graph::DEFAULT, port_id); _model->add_statement(block_id, Sord::URI(_model->world(), uris.lv2_port), port_id); @@ -472,7 +472,7 @@ Serialiser::Impl::serialise_port(const Node* port, _model->add_statement(port_id, Sord::URI(world, uris.lv2_symbol), Sord::Literal(world, port->path().symbol())); - } else { + } else if (context == Resource::Graph::EXTERNAL) { // Never write lv2:index for plugin instances (not persistent/stable) props.erase(uris.lv2_index); } @@ -483,6 +483,7 @@ Serialiser::Impl::serialise_port(const Node* port, { const Atom& val = port->get_property(uris.ingen_value); if (val.is_valid()) { + props.erase(uris.lv2_default); props.insert(make_pair(uris.lv2_default, val)); } else { _world.log().warn("Control input has no value, lv2:default omitted.\n"); diff --git a/src/gui/GraphCanvas.cpp b/src/gui/GraphCanvas.cpp index 54a7b341..7053b495 100644 --- a/src/gui/GraphCanvas.cpp +++ b/src/gui/GraphCanvas.cpp @@ -789,7 +789,7 @@ GraphCanvas::menu_add_port(const string& sym_base, const string& name_base, const URIs& uris = _app.uris(); - Resource::Properties props = get_initial_data(); + Resource::Properties props = get_initial_data(Resource::Graph::INTERNAL); props.insert(make_pair(uris.rdf_type, _app.forge().make_urid(type))); if (type == uris.atom_AtomPort) { props.insert(make_pair(uris.atom_bufferType, diff --git a/src/server/PortImpl.cpp b/src/server/PortImpl.cpp index 26fdd6cb..f09cfd6e 100644 --- a/src/server/PortImpl.cpp +++ b/src/server/PortImpl.cpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2015 David Robillard <http://drobilla.net/> + Copyright 2007-2016 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 @@ -84,7 +84,7 @@ PortImpl::PortImpl(BufferFactory& bufs, set_type(type, buffer_type); - set_property(uris.lv2_index, bufs.forge().make((int32_t)index)); + set_property(uris.lv2_index, bufs.forge().make((int32_t)index), Resource::Graph::INTERNAL); if (has_value()) { set_property(uris.ingen_value, value); } |