summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-05-12 03:31:57 +0000
committerDavid Robillard <d@drobilla.net>2012-05-12 03:31:57 +0000
commit8211b45bffe20e8a271396b7568609a84b7cf0ec (patch)
tree8f2b9557977c0b7a681cb8fc2209c554213c1e66 /src
parent271b3f9d7f376cbbaef202ef6f898e5f9bb4c324 (diff)
downloadingen-8211b45bffe20e8a271396b7568609a84b7cf0ec.tar.gz
ingen-8211b45bffe20e8a271396b7568609a84b7cf0ec.tar.bz2
ingen-8211b45bffe20e8a271396b7568609a84b7cf0ec.zip
Get copy and paste working again.
Client side and text based is probably not the idea way to go about implementing this, but it more or less works and is certainly better than nothing for now. Copy paste of patch ports, and pasting into any path other than the root still isn't working currently. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@4367 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src')
-rw-r--r--src/client/ClientStore.cpp6
-rw-r--r--src/gui/PatchCanvas.cpp69
-rw-r--r--src/serialisation/Parser.cpp129
-rw-r--r--src/serialisation/Serialiser.cpp12
-rw-r--r--src/shared/URIs.cpp1
5 files changed, 125 insertions, 92 deletions
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")