summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2016-10-02 21:00:16 -0400
committerDavid Robillard <d@drobilla.net>2016-10-02 23:01:13 -0400
commit97d25d127249ebe8558c019a968fe43303bea3f6 (patch)
treedab8f68ee3b8091778c912408a13b001f7525ff4
parenta6c193970cd7944a4ff364ae9b3abf02a9e3034f (diff)
downloadingen-97d25d127249ebe8558c019a968fe43303bea3f6.tar.gz
ingen-97d25d127249ebe8558c019a968fe43303bea3f6.tar.bz2
ingen-97d25d127249ebe8558c019a968fe43303bea3f6.zip
Fix saving and loading subgraphs
-rw-r--r--src/Parser.cpp104
-rw-r--r--src/Resource.cpp7
-rw-r--r--src/Serialiser.cpp7
-rw-r--r--src/gui/GraphCanvas.cpp2
-rw-r--r--src/server/PortImpl.cpp4
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);
}