summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2008-08-17 18:58:24 +0000
committerDavid Robillard <d@drobilla.net>2008-08-17 18:58:24 +0000
commit602e31074b30167baace71ccfff1f58a6b3f0626 (patch)
treeeb7b85c99532af48adfe6322e2b620ac31c62f76 /src
parent0e47cf5e7153a96875a64754291fad1cdbf26da7 (diff)
downloadingen-602e31074b30167baace71ccfff1f58a6b3f0626.tar.gz
ingen-602e31074b30167baace71ccfff1f58a6b3f0626.tar.bz2
ingen-602e31074b30167baace71ccfff1f58a6b3f0626.zip
More serialization work.
Preliminary copy/paste (nodes only) git-svn-id: http://svn.drobilla.net/lad/ingen@1418 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src')
-rw-r--r--src/common/interface/GraphObject.hpp2
-rw-r--r--src/libs/client/ClientStore.cpp97
-rw-r--r--src/libs/client/ClientStore.hpp45
-rw-r--r--src/libs/client/ObjectModel.cpp34
-rw-r--r--src/libs/client/ObjectModel.hpp4
-rw-r--r--src/libs/client/PortModel.hpp9
-rw-r--r--src/libs/engine/EngineStore.cpp14
-rw-r--r--src/libs/engine/GraphObjectImpl.hpp2
-rw-r--r--src/libs/engine/LV2Plugin.cpp17
-rw-r--r--src/libs/engine/LV2Plugin.hpp5
-rw-r--r--src/libs/gui/LoadPluginWindow.cpp8
-rw-r--r--src/libs/gui/LoadPluginWindow.hpp3
-rw-r--r--src/libs/gui/NodeModule.cpp18
-rw-r--r--src/libs/gui/PatchCanvas.cpp40
-rw-r--r--src/libs/gui/PatchCanvas.hpp1
-rw-r--r--src/libs/gui/PatchWindow.cpp21
-rw-r--r--src/libs/gui/PatchWindow.hpp2
-rw-r--r--src/libs/gui/ThreadedLoader.cpp24
-rw-r--r--src/libs/gui/ThreadedLoader.hpp6
-rw-r--r--src/libs/serialisation/Parser.cpp355
-rw-r--r--src/libs/serialisation/Parser.hpp28
-rw-r--r--src/libs/serialisation/Serialiser.cpp5
-rw-r--r--src/libs/shared/Builder.cpp88
-rw-r--r--src/libs/shared/Builder.hpp53
-rw-r--r--src/libs/shared/Makefile.am2
-rw-r--r--src/libs/shared/Store.cpp21
-rw-r--r--src/libs/shared/Store.hpp4
27 files changed, 658 insertions, 250 deletions
diff --git a/src/common/interface/GraphObject.hpp b/src/common/interface/GraphObject.hpp
index fa7be25a..c6fb5856 100644
--- a/src/common/interface/GraphObject.hpp
+++ b/src/common/interface/GraphObject.hpp
@@ -50,7 +50,9 @@ public:
virtual const Raul::Path path() const = 0;
virtual const Raul::Symbol symbol() const = 0;
virtual const Variables& variables() const = 0;
+ virtual Variables& variables() = 0;
virtual const Properties& properties() const = 0;
+ virtual Properties& properties() = 0;
virtual bool polyphonic() const = 0;
// FIXME: return WeakPtr, and stupid name
diff --git a/src/libs/client/ClientStore.cpp b/src/libs/client/ClientStore.cpp
index 969f3a8f..6c2c81ff 100644
--- a/src/libs/client/ClientStore.cpp
+++ b/src/libs/client/ClientStore.cpp
@@ -35,20 +35,27 @@ namespace Client {
ClientStore::ClientStore(SharedPtr<EngineInterface> engine, SharedPtr<SigClientInterface> emitter)
: _engine(engine)
, _emitter(emitter)
+ , _plugins(new Plugins())
{
- emitter->signal_object_destroyed.connect(sigc::mem_fun(this, &ClientStore::destruction_event));
- emitter->signal_object_renamed.connect(sigc::mem_fun(this, &ClientStore::rename_event));
- emitter->signal_new_plugin.connect(sigc::mem_fun(this, &ClientStore::new_plugin_event));
- emitter->signal_new_patch.connect(sigc::mem_fun(this, &ClientStore::new_patch_event));
- emitter->signal_new_node.connect(sigc::mem_fun(this, &ClientStore::new_node_event));
- emitter->signal_new_port.connect(sigc::mem_fun(this, &ClientStore::new_port_event));
- emitter->signal_patch_cleared.connect(sigc::mem_fun(this, &ClientStore::patch_cleared_event));
- emitter->signal_connection.connect(sigc::mem_fun(this, &ClientStore::connection_event));
- emitter->signal_disconnection.connect(sigc::mem_fun(this, &ClientStore::disconnection_event));
- emitter->signal_variable_change.connect(sigc::mem_fun(this, &ClientStore::variable_change_event));
- emitter->signal_property_change.connect(sigc::mem_fun(this, &ClientStore::property_change_event));
- emitter->signal_port_value.connect(sigc::mem_fun(this, &ClientStore::port_value_event));
- emitter->signal_port_activity.connect(sigc::mem_fun(this, &ClientStore::port_activity_event));
+ _handle_orphans = (engine && emitter);
+
+ if (!emitter)
+ return;
+
+ emitter->signal_object_destroyed.connect(sigc::mem_fun(this, &ClientStore::destruction));
+ emitter->signal_object_renamed.connect(sigc::mem_fun(this, &ClientStore::rename));
+ emitter->signal_new_plugin.connect(sigc::mem_fun(this, &ClientStore::new_plugin));
+ emitter->signal_new_patch.connect(sigc::mem_fun(this, &ClientStore::new_patch));
+ emitter->signal_new_node.connect(sigc::mem_fun(this, &ClientStore::new_node));
+ emitter->signal_new_port.connect(sigc::mem_fun(this, &ClientStore::new_port));
+ emitter->signal_patch_cleared.connect(sigc::mem_fun(this, &ClientStore::patch_cleared));
+ emitter->signal_connection.connect(sigc::mem_fun(this, &ClientStore::connect));
+ emitter->signal_disconnection.connect(sigc::mem_fun(this, &ClientStore::disconnect));
+ emitter->signal_variable_change.connect(sigc::mem_fun(this, &ClientStore::set_variable));
+ emitter->signal_property_change.connect(sigc::mem_fun(this, &ClientStore::set_property));
+ emitter->signal_port_value.connect(sigc::mem_fun(this, &ClientStore::set_port_value));
+ emitter->signal_voice_value.connect(sigc::mem_fun(this, &ClientStore::set_voice_value));
+ emitter->signal_port_activity.connect(sigc::mem_fun(this, &ClientStore::port_activity));
}
@@ -56,13 +63,15 @@ void
ClientStore::clear()
{
Store::clear();
- _plugins.clear();
+ _plugins->clear();
}
void
ClientStore::add_plugin_orphan(SharedPtr<NodeModel> node)
{
+ if (!_handle_orphans)
+ return;
cerr << "WARNING: Node " << node->path() << " received, but plugin "
<< node->plugin_uri() << " unknown." << endl;
@@ -84,6 +93,8 @@ ClientStore::add_plugin_orphan(SharedPtr<NodeModel> node)
void
ClientStore::resolve_plugin_orphans(SharedPtr<PluginModel> plugin)
{
+ if (!_handle_orphans)
+ return;
Raul::Table<string, list<SharedPtr<NodeModel> > >::iterator n
= _plugin_orphans.find(plugin->uri());
@@ -106,6 +117,8 @@ ClientStore::resolve_plugin_orphans(SharedPtr<PluginModel> plugin)
void
ClientStore::add_connection_orphan(std::pair<Path, Path> orphan)
{
+ if (!_handle_orphans)
+ return;
cerr << "WARNING: Orphan connection " << orphan.first
<< " -> " << orphan.second << " received." << endl;
@@ -116,6 +129,8 @@ ClientStore::add_connection_orphan(std::pair<Path, Path> orphan)
void
ClientStore::resolve_connection_orphans(SharedPtr<PortModel> port)
{
+ if (!_handle_orphans)
+ return;
assert(port->parent());
for (list< pair<Path, Path> >::iterator c = _connection_orphans.begin();
@@ -139,6 +154,8 @@ ClientStore::resolve_connection_orphans(SharedPtr<PortModel> port)
void
ClientStore::add_orphan(SharedPtr<ObjectModel> child)
{
+ if (!_handle_orphans)
+ return;
cerr << "WARNING: Orphan object " << child->path() << " received." << endl;
Raul::PathTable<list<SharedPtr<ObjectModel> > >::iterator children
@@ -159,6 +176,8 @@ ClientStore::add_orphan(SharedPtr<ObjectModel> child)
void
ClientStore::add_variable_orphan(const Path& subject_path, const string& predicate, const Atom& value)
{
+ if (!_handle_orphans)
+ return;
Raul::PathTable<list<std::pair<string, Atom> > >::iterator orphans
= _variable_orphans.find(subject_path);
@@ -177,6 +196,8 @@ ClientStore::add_variable_orphan(const Path& subject_path, const string& predica
void
ClientStore::resolve_variable_orphans(SharedPtr<ObjectModel> subject)
{
+ if (!_handle_orphans)
+ return;
Raul::PathTable<list<std::pair<string, Atom> > >::iterator v
= _variable_orphans.find(subject->path());
@@ -198,6 +219,8 @@ ClientStore::resolve_variable_orphans(SharedPtr<ObjectModel> subject)
void
ClientStore::resolve_orphans(SharedPtr<ObjectModel> parent)
{
+ if (!_handle_orphans)
+ return;
Raul::PathTable<list<SharedPtr<ObjectModel> > >::iterator c
= _orphans.find(parent->path());
@@ -222,6 +245,7 @@ ClientStore::add_object(SharedPtr<ObjectModel> object)
// one (with precedence to the new values).
iterator existing = find(object->path());
if (existing != end()) {
+ cout << "WARNING: Object " << object->path() << " already exists in store" << endl;
PtrCast<ObjectModel>(existing->second)->set(object);
} else {
@@ -307,8 +331,8 @@ SharedPtr<PluginModel>
ClientStore::plugin(const string& uri)
{
assert(uri.length() > 0);
- Plugins::iterator i = _plugins.find(uri);
- if (i == _plugins.end())
+ Plugins::iterator i = _plugins->find(uri);
+ if (i == _plugins->end())
return SharedPtr<PluginModel>();
else
return (*i).second;
@@ -335,9 +359,9 @@ ClientStore::add_plugin(SharedPtr<PluginModel> pm)
{
// FIXME: dupes? merge, like with objects?
- _plugins[pm->uri()] = pm;
+ (*_plugins)[pm->uri()] = pm;
signal_new_plugin(pm);
- //cerr << "Plugin: " << pm->uri() << ", # plugins: " << _plugins.size() << endl;
+ //cerr << "Plugin: " << pm->uri() << ", # plugins: " << _plugins->size() << endl;
}
@@ -345,7 +369,7 @@ ClientStore::add_plugin(SharedPtr<PluginModel> pm)
void
-ClientStore::destruction_event(const Path& path)
+ClientStore::destruction(const Path& path)
{
SharedPtr<ObjectModel> removed = remove_object(path);
@@ -356,7 +380,7 @@ ClientStore::destruction_event(const Path& path)
}
void
-ClientStore::rename_event(const Path& old_path, const Path& new_path)
+ClientStore::rename(const Path& old_path, const Path& new_path)
{
iterator parent = find(old_path);
if (parent == end()) {
@@ -398,7 +422,7 @@ ClientStore::rename_event(const Path& old_path, const Path& new_path)
}
void
-ClientStore::new_plugin_event(const string& uri, const string& type_uri, const string& symbol, const string& name)
+ClientStore::new_plugin(const string& uri, const string& type_uri, const string& symbol, const string& name)
{
SharedPtr<PluginModel> p(new PluginModel(uri, type_uri, symbol, name));
add_plugin(p);
@@ -407,7 +431,7 @@ ClientStore::new_plugin_event(const string& uri, const string& type_uri, const s
void
-ClientStore::new_patch_event(const Path& path, uint32_t poly)
+ClientStore::new_patch(const string& path, uint32_t poly)
{
SharedPtr<PatchModel> p(new PatchModel(path, poly));
add_object(p);
@@ -415,7 +439,7 @@ ClientStore::new_patch_event(const Path& path, uint32_t poly)
void
-ClientStore::new_node_event(const Path& path, const string& plugin_uri)
+ClientStore::new_node(const string& path, const string& plugin_uri)
{
SharedPtr<PluginModel> plug = plugin(plugin_uri);
if (!plug) {
@@ -429,7 +453,7 @@ ClientStore::new_node_event(const Path& path, const string& plugin_uri)
void
-ClientStore::new_port_event(const Path& path, uint32_t index, const string& type, bool is_output)
+ClientStore::new_port(const string& path, uint32_t index, const string& type, bool is_output)
{
PortModel::Direction pdir = is_output ? PortModel::OUTPUT : PortModel::INPUT;
@@ -441,7 +465,7 @@ ClientStore::new_port_event(const Path& path, uint32_t index, const string& type
void
-ClientStore::patch_cleared_event(const Path& path)
+ClientStore::patch_cleared(const Path& path)
{
iterator i = find(path);
if (i != end()) {
@@ -469,7 +493,7 @@ ClientStore::patch_cleared_event(const Path& path)
void
-ClientStore::variable_change_event(const Path& subject_path, const string& predicate, const Atom& value)
+ClientStore::set_variable(const string& subject_path, const string& predicate, const Atom& value)
{
SharedPtr<ObjectModel> subject = object(subject_path);
@@ -485,7 +509,7 @@ ClientStore::variable_change_event(const Path& subject_path, const string& predi
void
-ClientStore::property_change_event(const Path& subject_path, const string& predicate, const Atom& value)
+ClientStore::set_property(const string& subject_path, const string& predicate, const Atom& value)
{
SharedPtr<ObjectModel> subject = object(subject_path);
@@ -501,7 +525,7 @@ ClientStore::property_change_event(const Path& subject_path, const string& predi
void
-ClientStore::port_value_event(const Path& port_path, const Raul::Atom& value)
+ClientStore::set_port_value(const string& port_path, const Raul::Atom& value)
{
SharedPtr<PortModel> port = PtrCast<PortModel>(object(port_path));
if (port)
@@ -510,9 +534,20 @@ ClientStore::port_value_event(const Path& port_path, const Raul::Atom& value)
cerr << "ERROR: control change for nonexistant port " << port_path << endl;
}
+
+void
+ClientStore::set_voice_value(const string& port_path, uint32_t voice, const Raul::Atom& value)
+{
+ SharedPtr<PortModel> port = PtrCast<PortModel>(object(port_path));
+ if (port)
+ port->value(voice, value);
+ else
+ cerr << "ERROR: poly control change for nonexistant port " << port_path << endl;
+}
+
void
-ClientStore::port_activity_event(const Path& port_path)
+ClientStore::port_activity(const Path& port_path)
{
SharedPtr<PortModel> port = PtrCast<PortModel>(object(port_path));
if (port)
@@ -581,14 +616,14 @@ ClientStore::attempt_connection(const Path& src_port_path, const Path& dst_port_
void
-ClientStore::connection_event(const Path& src_port_path, const Path& dst_port_path)
+ClientStore::connect(const string& src_port_path, const string& dst_port_path)
{
attempt_connection(src_port_path, dst_port_path, true);
}
void
-ClientStore::disconnection_event(const Path& src_port_path, const Path& dst_port_path)
+ClientStore::disconnect(const string& src_port_path, const string& dst_port_path)
{
// Find the ports and create a ConnectionModel just to get at the parent path
// finding logic in ConnectionModel. So I'm lazy.
diff --git a/src/libs/client/ClientStore.hpp b/src/libs/client/ClientStore.hpp
index a750f875..4b4d9742 100644
--- a/src/libs/client/ClientStore.hpp
+++ b/src/libs/client/ClientStore.hpp
@@ -53,9 +53,10 @@ class ConnectionModel;
*
* \ingroup IngenClient
*/
-class ClientStore : public Shared::Store, public sigc::trackable { // FIXME: is trackable necessary?
+class ClientStore : public Shared::Store, public Shared::CommonInterface, public sigc::trackable {
public:
- ClientStore(SharedPtr<EngineInterface> engine, SharedPtr<SigClientInterface> emitter);
+ ClientStore(SharedPtr<EngineInterface> engine=SharedPtr<EngineInterface>(),
+ SharedPtr<SigClientInterface> emitter=SharedPtr<SigClientInterface>());
SharedPtr<PluginModel> plugin(const string& uri);
SharedPtr<ObjectModel> object(const Path& path);
@@ -63,7 +64,21 @@ public:
void clear();
typedef Raul::Table<string, SharedPtr<PluginModel> > Plugins;
- const Plugins& plugins() const { return _plugins; }
+ SharedPtr<const Plugins> plugins() const { return _plugins; }
+ SharedPtr<Plugins> plugins() { return _plugins; }
+ void set_plugins(SharedPtr<Plugins> p) { _plugins = p; }
+
+ // CommonInterface
+ void new_plugin(const string& uri, const string& type_uri, const string& symbol, const string& name);
+ void new_patch(const string& path, uint32_t poly);
+ void new_node(const string& path, const string& plugin_uri);
+ void new_port(const string& path, uint32_t index, const string& data_type, bool is_output);
+ void set_variable(const string& subject_path, const string& predicate, const Atom& value);
+ void set_property(const string& subject_path, const string& predicate, const Atom& value);
+ void set_port_value(const string& port_path, const Raul::Atom& value);
+ void set_voice_value(const string& port_path, uint32_t voice, const Raul::Atom& value);
+ void connect(const string& src_port_path, const string& dst_port_path);
+ void disconnect(const string& src_port_path, const string& dst_port_path);
sigc::signal<void, SharedPtr<ObjectModel> > signal_new_object;
sigc::signal<void, SharedPtr<PluginModel> > signal_new_plugin;
@@ -92,28 +107,24 @@ private:
void add_variable_orphan(const Path& subject, const string& predicate, const Atom& value);
void resolve_variable_orphans(SharedPtr<ObjectModel> subject);
+
+ void bundle_begin() {}
+ void bundle_end() {}
// Slots for SigClientInterface signals
- void destruction_event(const Path& path);
- void rename_event(const Path& old_path, const Path& new_path);
- void new_plugin_event(const string& uri, const string& type_uri, const string& symbol, const string& name);
- void new_patch_event(const Path& path, uint32_t poly);
- void new_node_event(const Path& path, const string& plugin_uri);
- void new_port_event(const Path& path, uint32_t index, const string& data_type, bool is_output);
- void patch_cleared_event(const Path& path);
- void variable_change_event(const Path& subject_path, const string& predicate, const Atom& value);
- void property_change_event(const Path& subject_path, const string& predicate, const Atom& value);
- void port_value_event(const Path& port_path, const Raul::Atom& value);
- void port_activity_event(const Path& port_path);
- void connection_event(const Path& src_port_path, const Path& dst_port_path);
- void disconnection_event(const Path& src_port_path, const Path& dst_port_path);
+ void destruction(const Path& path);
+ void rename(const Path& old_path, const Path& new_path);
+ void patch_cleared(const Path& path);
+ void port_activity(const Path& port_path);
bool attempt_connection(const Path& src_port_path, const Path& dst_port_path, bool add_orphan=false);
+ bool _handle_orphans;
+
SharedPtr<EngineInterface> _engine;
SharedPtr<SigClientInterface> _emitter;
- Plugins _plugins; ///< Map, keyed by plugin URI
+ SharedPtr<Plugins> _plugins; ///< Map, keyed by plugin URI
/** Objects we've received, but depend on the existance of another unknown object.
* Keyed by the path of the depended-on object (for tolerance of orderless comms) */
diff --git a/src/libs/client/ObjectModel.cpp b/src/libs/client/ObjectModel.cpp
index 0afb9ad8..e9a491a6 100644
--- a/src/libs/client/ObjectModel.cpp
+++ b/src/libs/client/ObjectModel.cpp
@@ -54,6 +54,23 @@ ObjectModel::get_variable(const string& key) const
}
+/** Get a variable for this object.
+ *
+ * @return Metadata value with key @a key, empty string otherwise.
+ */
+Atom&
+ObjectModel::get_variable( string& key)
+{
+ static Atom null_atom;
+
+ Variables::iterator i = _variables.find(key);
+ if (i != _variables.end())
+ return i->second;
+ else
+ return null_atom;
+}
+
+
/** Get a property of this object.
*
* @return Metadata value with key @a key, empty string otherwise.
@@ -71,6 +88,23 @@ ObjectModel::get_property(const string& key) const
}
+/** Get a property of this object.
+ *
+ * @return Metadata value with key @a key, empty string otherwise.
+ */
+Atom&
+ObjectModel::get_property(const string& key)
+{
+ static Atom null_atom;
+
+ Properties::iterator i = _properties.find(key);
+ if (i != _properties.end())
+ return i->second;
+ else
+ return null_atom;
+}
+
+
bool
ObjectModel::polyphonic() const
{
diff --git a/src/libs/client/ObjectModel.hpp b/src/libs/client/ObjectModel.hpp
index 2b4642da..11cc87a4 100644
--- a/src/libs/client/ObjectModel.hpp
+++ b/src/libs/client/ObjectModel.hpp
@@ -60,7 +60,9 @@ public:
virtual ~ObjectModel();
const Atom& get_variable(const string& key) const;
+ Atom& get_variable( string& key);
const Atom& get_property(const string& key) const;
+ Atom& get_property(const string& key);
virtual void set_variable(const string& key, const Atom& value)
{ _variables[key] = value; signal_variable.emit(key, value); }
@@ -70,6 +72,8 @@ public:
const Variables& variables() const { return _variables; }
const Properties& properties() const { return _properties; }
+ Variables& variables() { return _variables; }
+ Properties& properties() { return _properties; }
const Path path() const { return _path; }
const Symbol symbol() const { return _path.name(); }
SharedPtr<ObjectModel> parent() const { return _parent; }
diff --git a/src/libs/client/PortModel.hpp b/src/libs/client/PortModel.hpp
index 8fa18f1c..a86c9188 100644
--- a/src/libs/client/PortModel.hpp
+++ b/src/libs/client/PortModel.hpp
@@ -56,16 +56,21 @@ public:
inline bool operator==(const PortModel& pm) const { return (_path == pm._path); }
- inline void value(const Atom& val)
- {
+ inline void value(const Atom& val) {
if (val != _current_val) {
_current_val = val;
signal_value_changed.emit(val);
}
}
+ inline void value(uint32_t voice, const Atom& val) {
+ // FIXME: implement properly
+ signal_voice_changed.emit(voice, val);
+ }
+
// Signals
sigc::signal<void, const Atom&> signal_value_changed; ///< Value ports
+ sigc::signal<void, uint32_t, const Atom&> signal_voice_changed; ///< Polyphonic value ports
sigc::signal<void> signal_activity; ///< Message ports
sigc::signal<void, SharedPtr<PortModel> > signal_connection;
sigc::signal<void, SharedPtr<PortModel> > signal_disconnection;
diff --git a/src/libs/engine/EngineStore.cpp b/src/libs/engine/EngineStore.cpp
index 5f5e41e5..9fcd3806 100644
--- a/src/libs/engine/EngineStore.cpp
+++ b/src/libs/engine/EngineStore.cpp
@@ -82,19 +82,7 @@ EngineStore::add(GraphObject* obj)
assert(ThreadManager::current_thread_id() == THREAD_PRE_PROCESS);
- if (find(o->path()) != end()) {
- cerr << "[EngineStore] ERROR: Attempt to add duplicate object " << o->path() << endl;
- return;
- }
-
- insert(make_pair(o->path(), o));
-
- NodeImpl* node = dynamic_cast<NodeImpl*>(o);
- if (node) {
- for (uint32_t i=0; i < node->num_ports(); ++i) {
- add(node->port_impl(i));
- }
- }
+ Store::add(obj);
}
diff --git a/src/libs/engine/GraphObjectImpl.hpp b/src/libs/engine/GraphObjectImpl.hpp
index d1896b1b..bee10c98 100644
--- a/src/libs/engine/GraphObjectImpl.hpp
+++ b/src/libs/engine/GraphObjectImpl.hpp
@@ -87,6 +87,8 @@ public:
const Variables& variables() const { return _variables; }
const Properties& properties() const { return _properties; }
+ Variables& variables() { return _variables; }
+ Properties& properties() { return _properties; }
/** The Patch this object is a child of. */
virtual PatchImpl* parent_patch() const;
diff --git a/src/libs/engine/LV2Plugin.cpp b/src/libs/engine/LV2Plugin.cpp
index 871050e4..53d317b4 100644
--- a/src/libs/engine/LV2Plugin.cpp
+++ b/src/libs/engine/LV2Plugin.cpp
@@ -47,9 +47,8 @@ LV2Plugin::symbol() const
const string
LV2Plugin::name() const
{
- SLV2Value name = slv2_plugin_get_name(_slv2_plugin);
- if (name)
- return slv2_value_as_string(name);
+ if (_name)
+ return slv2_value_as_string(_name);
else
return "(no name)";
}
@@ -70,9 +69,21 @@ LV2Plugin::instantiate(const string& name,
delete n;
n = NULL;
}
+
+
return n;
}
+
+
+void
+LV2Plugin::slv2_plugin(SLV2Plugin p)
+{
+ _slv2_plugin = p;
+ if (_name)
+ slv2_value_free(_name);
+ _name = slv2_plugin_get_name(_slv2_plugin);
+}
} // namespace Ingen
diff --git a/src/libs/engine/LV2Plugin.hpp b/src/libs/engine/LV2Plugin.hpp
index effdefdc..827e7e89 100644
--- a/src/libs/engine/LV2Plugin.hpp
+++ b/src/libs/engine/LV2Plugin.hpp
@@ -53,6 +53,8 @@ class LV2Plugin : public PluginImpl
public:
LV2Plugin(SharedPtr<LV2Info> lv2_info, const string& uri)
: PluginImpl(Plugin::LV2, uri)
+ , _name(NULL)
+ , _slv2_plugin(NULL)
, _lv2_info(lv2_info)
{}
@@ -68,9 +70,10 @@ public:
SharedPtr<LV2Info> lv2_info() const { return _lv2_info; }
SLV2Plugin slv2_plugin() const { return _slv2_plugin; }
- void slv2_plugin(SLV2Plugin p) { _slv2_plugin = p; }
+ void slv2_plugin(SLV2Plugin p);
private:
+ SLV2Value _name;
SLV2Plugin _slv2_plugin;
SharedPtr<LV2Info> _lv2_info;
};
diff --git a/src/libs/gui/LoadPluginWindow.cpp b/src/libs/gui/LoadPluginWindow.cpp
index 92fcb221..436de188 100644
--- a/src/libs/gui/LoadPluginWindow.cpp
+++ b/src/libs/gui/LoadPluginWindow.cpp
@@ -211,11 +211,11 @@ LoadPluginWindow::plugin_compare(const Gtk::TreeModel::iterator& a_i,
void
-LoadPluginWindow::set_plugins(const Raul::Table<string, SharedPtr<PluginModel> >& m)
+LoadPluginWindow::set_plugins(SharedPtr<const ClientStore::Plugins> m)
{
_plugins_liststore->clear();
- for (Raul::Table<string, SharedPtr<PluginModel> >::const_iterator i = m.begin(); i != m.end(); ++i) {
+ for (ClientStore::Plugins::const_iterator i = m->begin(); i != m->end(); ++i) {
SharedPtr<PluginModel> plugin = (*i).second;
Gtk::TreeModel::iterator iter = _plugins_liststore->append();
@@ -396,8 +396,8 @@ LoadPluginWindow::filter_changed()
size_t num_visible = 0;
- for (Raul::Table<string, SharedPtr<PluginModel> >::const_iterator i = App::instance().store()->plugins().begin();
- i != App::instance().store()->plugins().end(); ++i) {
+ for (ClientStore::Plugins::const_iterator i = App::instance().store()->plugins()->begin();
+ i != App::instance().store()->plugins()->end(); ++i) {
const SharedPtr<PluginModel> plugin = (*i).second;
diff --git a/src/libs/gui/LoadPluginWindow.hpp b/src/libs/gui/LoadPluginWindow.hpp
index ef1420a0..a5246c39 100644
--- a/src/libs/gui/LoadPluginWindow.hpp
+++ b/src/libs/gui/LoadPluginWindow.hpp
@@ -26,6 +26,7 @@
#include "interface/GraphObject.hpp"
#include "client/PatchModel.hpp"
#include "client/PluginModel.hpp"
+#include "client/ClientStore.hpp"
using Ingen::Client::PluginModel;
using Ingen::Client::PatchModel;
using namespace Ingen::Shared;
@@ -93,7 +94,7 @@ public:
LoadPluginWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& xml);
void set_patch(SharedPtr<PatchModel> patch);
- void set_plugins(const Raul::Table<string, SharedPtr<PluginModel> >& m);
+ void set_plugins(SharedPtr<const ClientStore::Plugins> plugins);
void add_plugin(SharedPtr<PluginModel> plugin);
diff --git a/src/libs/gui/NodeModule.cpp b/src/libs/gui/NodeModule.cpp
index fe71dd2f..7ac86e40 100644
--- a/src/libs/gui/NodeModule.cpp
+++ b/src/libs/gui/NodeModule.cpp
@@ -104,13 +104,17 @@ NodeModule::create(boost::shared_ptr<PatchCanvas> canvas, SharedPtr<NodeModel> n
void
NodeModule::value_changed(uint32_t index, const Atom& value)
{
- float control = value.get_float();
- if (_plugin_ui) {
- SLV2UIInstance inst = _plugin_ui->instance();
- const LV2UI_Descriptor* ui_descriptor = slv2_ui_instance_get_descriptor(inst);
- LV2UI_Handle ui_handle = slv2_ui_instance_get_handle(inst);
- if (ui_descriptor->port_event)
- ui_descriptor->port_event(ui_handle, index, 4, 0, &control);
+ if (value.type() == Atom::FLOAT) {
+ float control = value.get_float();
+ if (_plugin_ui) {
+ SLV2UIInstance inst = _plugin_ui->instance();
+ const LV2UI_Descriptor* ui_descriptor = slv2_ui_instance_get_descriptor(inst);
+ LV2UI_Handle ui_handle = slv2_ui_instance_get_handle(inst);
+ if (ui_descriptor->port_event)
+ ui_descriptor->port_event(ui_handle, index, 4, 0, &control);
+ }
+ } else {
+ cerr << "WARNING: Unknown value type " << (int)value.type() << endl;
}
}
diff --git a/src/libs/gui/PatchCanvas.cpp b/src/libs/gui/PatchCanvas.cpp
index 019851f0..d625d2cd 100644
--- a/src/libs/gui/PatchCanvas.cpp
+++ b/src/libs/gui/PatchCanvas.cpp
@@ -23,6 +23,7 @@
#include <flowcanvas/Canvas.hpp>
#include <flowcanvas/Ellipse.hpp>
#include "interface/EngineInterface.hpp"
+#include "shared/Builder.hpp"
#include "serialisation/Serialiser.hpp"
#include "client/PluginModel.hpp"
#include "client/PatchModel.hpp"
@@ -41,6 +42,7 @@
#include "SubpatchModule.hpp"
#include "GladeFactory.hpp"
#include "WindowFactory.hpp"
+#include "ThreadedLoader.hpp"
using Ingen::Client::ClientStore;
using Ingen::Serialisation::Serialiser;
using Ingen::Client::PluginModel;
@@ -159,10 +161,10 @@ PatchCanvas::build_internal_menu()
_menu->reorder_child(*internal_menu_item, 2);
}
- const ClientStore::Plugins& plugins = App::instance().store()->plugins();
+ SharedPtr<const ClientStore::Plugins> plugins = App::instance().store()->plugins();
// Add Internal plugins
- for (ClientStore::Plugins::const_iterator i = plugins.begin(); i != plugins.end(); ++i) {
+ for (ClientStore::Plugins::const_iterator i = plugins->begin(); i != plugins->end(); ++i) {
SharedPtr<PluginModel> p = i->second;
if (p->type() == Plugin::Internal) {
_internal_menu->items().push_back(Gtk::Menu_Helpers::MenuElem(p->name(),
@@ -200,10 +202,10 @@ PatchCanvas::build_plugin_class_menu(Gtk::Menu* menu,
}
}
- const ClientStore::Plugins& plugins = App::instance().store()->plugins();
+ SharedPtr<const ClientStore::Plugins> plugins = App::instance().store()->plugins();
// Add LV2 plugins
- for (ClientStore::Plugins::const_iterator i = plugins.begin(); i != plugins.end(); ++i) {
+ for (ClientStore::Plugins::const_iterator i = plugins->begin(); i != plugins->end(); ++i) {
SLV2Plugin p = i->second->slv2_plugin();
if (p && slv2_plugin_get_class(p) == plugin_class) {
@@ -565,6 +567,36 @@ PatchCanvas::copy_selection()
Glib::RefPtr<Gtk::Clipboard> clipboard = Gtk::Clipboard::get();
clipboard->set_text(result);
}
+
+
+void
+PatchCanvas::paste()
+{
+ Glib::ustring str = Gtk::Clipboard::get()->wait_for_text();
+ SharedPtr<Parser> parser = App::instance().loader()->parser();
+ if (!parser) {
+ cerr << "Unable to load parser, paste unavailable" << endl;
+ return;
+ }
+
+ Builder builder(*App::instance().engine());
+ ClientStore clipboard;
+ clipboard.new_patch("/", _patch->poly());
+ clipboard.set_plugins(App::instance().store()->plugins());
+ parser->parse_string(App::instance().world(), &clipboard, str, "/");
+ for (Store::iterator i = clipboard.begin(); i != clipboard.end(); ++i) {
+ /*GraphObject::Properties::iterator s = i->second->properties().find("ingen:symbol");
+ const string sym = string(s->second.get_string()) + "_copy";
+ s->second = sym;*/
+ GraphObject::Variables::iterator x = i->second->variables().find("ingenuity:canvas-x");
+ if (x != i->second->variables().end())
+ x->second = x->second.get_float() + 20.0f;
+ GraphObject::Variables::iterator y = i->second->variables().find("ingenuity:canvas-y");
+ if (y != i->second->variables().end())
+ y->second = y->second.get_float() + 20.0f;
+ builder.build(i->second);
+ }
+}
string
diff --git a/src/libs/gui/PatchCanvas.hpp b/src/libs/gui/PatchCanvas.hpp
index 3998532d..f596c97b 100644
--- a/src/libs/gui/PatchCanvas.hpp
+++ b/src/libs/gui/PatchCanvas.hpp
@@ -79,6 +79,7 @@ public:
void destroy_selection();
void copy_selection();
+ void paste();
void show_menu(GdkEvent* event);
diff --git a/src/libs/gui/PatchWindow.cpp b/src/libs/gui/PatchWindow.cpp
index ad558903..125adeea 100644
--- a/src/libs/gui/PatchWindow.cpp
+++ b/src/libs/gui/PatchWindow.cpp
@@ -98,6 +98,8 @@ PatchWindow::PatchWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glad
sigc::mem_fun(this, &PatchWindow::event_upload));
_menu_copy->signal_activate().connect(
sigc::mem_fun(this, &PatchWindow::event_copy));
+ _menu_paste->signal_activate().connect(
+ sigc::mem_fun(this, &PatchWindow::event_paste));
_menu_delete->signal_activate().connect(
sigc::mem_fun(this, &PatchWindow::event_delete));
_menu_quit->signal_activate().connect(
@@ -130,6 +132,9 @@ PatchWindow::PatchWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glad
#ifndef HAVE_CURL
_menu_upload->hide();
#endif
+
+ Glib::RefPtr<Gtk::Clipboard> clipboard = Gtk::Clipboard::get();
+ clipboard->signal_owner_change().connect(sigc::mem_fun(this, &PatchWindow::event_clipboard_changed));
}
@@ -274,6 +279,14 @@ PatchWindow::event_show_engine()
void
+PatchWindow::event_clipboard_changed(GdkEventOwnerChange* ev)
+{
+ Glib::RefPtr<Gtk::Clipboard> clipboard = Gtk::Clipboard::get();
+ _menu_paste->set_sensitive(clipboard->wait_is_text_available());
+}
+
+
+void
PatchWindow::event_show_controls()
{
App::instance().window_factory()->present_controls(_patch);
@@ -386,6 +399,14 @@ PatchWindow::event_copy()
void
+PatchWindow::event_paste()
+{
+ if (_view)
+ _view->canvas()->paste();
+}
+
+
+void
PatchWindow::event_delete()
{
if (_view)
diff --git a/src/libs/gui/PatchWindow.hpp b/src/libs/gui/PatchWindow.hpp
index a3851dc1..2b5a90be 100644
--- a/src/libs/gui/PatchWindow.hpp
+++ b/src/libs/gui/PatchWindow.hpp
@@ -89,6 +89,7 @@ private:
void event_save_as();
void event_upload();
void event_copy();
+ void event_paste();
void event_delete();
void event_quit();
void event_destroy();
@@ -98,6 +99,7 @@ private:
void event_show_properties();
void event_show_controls();
void event_show_engine();
+ void event_clipboard_changed(GdkEventOwnerChange* ev);
SharedPtr<PatchModel> _patch;
SharedPtr<PatchView> _view;
diff --git a/src/libs/gui/ThreadedLoader.cpp b/src/libs/gui/ThreadedLoader.cpp
index d85d54a3..88dd4b1a 100644
--- a/src/libs/gui/ThreadedLoader.cpp
+++ b/src/libs/gui/ThreadedLoader.cpp
@@ -36,8 +36,18 @@ ThreadedLoader::ThreadedLoader(SharedPtr<EngineInterface> engine)
{
set_name("Loader");
- // FIXME: rework this so the thread is only present when it's doing something (save mem)
- // and module isn't loaded until required
+ if (parser())
+ start();
+ else
+ cerr << "WARNING: Failed to load ingen_serialisation module, load disabled." << endl;
+}
+
+
+SharedPtr<Parser>
+ThreadedLoader::parser()
+{
+ if (_parser)
+ return _parser;
World* world = App::instance().world();
if (!world->serialisation_module)
@@ -53,15 +63,7 @@ ThreadedLoader::ThreadedLoader(SharedPtr<EngineInterface> engine)
_parser = SharedPtr<Parser>(new_parser());
}
- if (_parser)
- start();
- else
- cerr << "WARNING: Failed to load ingen_serialisation module, load disabled." << endl;
-}
-
-
-ThreadedLoader::~ThreadedLoader()
-{
+ return _parser;
}
diff --git a/src/libs/gui/ThreadedLoader.hpp b/src/libs/gui/ThreadedLoader.hpp
index dd5909fe..3cf88cf9 100644
--- a/src/libs/gui/ThreadedLoader.hpp
+++ b/src/libs/gui/ThreadedLoader.hpp
@@ -56,11 +56,7 @@ class ThreadedLoader : public Raul::Slave
{
public:
ThreadedLoader(SharedPtr<EngineInterface> engine);
- ~ThreadedLoader();
- // FIXME: there's a pattern here....
- // (same core interface as Loader/Serialiser)
-
void load_patch(bool merge,
const Glib::ustring& data_base_uri,
const Path& data_path,
@@ -70,6 +66,8 @@ public:
void save_patch(SharedPtr<PatchModel> model, const string& filename);
+ SharedPtr<Parser> parser();
+
private:
void save_patch_event(SharedPtr<PatchModel> model, const string& filename);
diff --git a/src/libs/serialisation/Parser.cpp b/src/libs/serialisation/Parser.cpp
index b34a3e47..c1d8c4e5 100644
--- a/src/libs/serialisation/Parser.cpp
+++ b/src/libs/serialisation/Parser.cpp
@@ -38,6 +38,18 @@ namespace Serialisation {
#define NS_INGEN "http://drobilla.net/ns/ingen#"
+Glib::ustring
+Parser::uri_relative_to_base(const Glib::ustring base, const Glib::ustring uri)
+{
+ Glib::ustring ret;
+ if (uri.length() > base.length() && uri.substr(0, base.length()) == base)
+ ret = uri.substr(base.length());
+ else
+ ret = uri;
+ return ret;
+}
+
+
/** Parse a patch from RDF into a CommonInterface (engine or client).
*
* @param document_uri URI of file to load objects from.
@@ -56,13 +68,10 @@ Parser::parse_document(
{
Redland::Model model(*world->rdf_world, document_uri, document_uri);
- if (object_uri == "") {
- object_uri = string("<") + document_uri + ">";
+ if (object_uri == document_uri || object_uri == "")
cout << "[Parser] Parsing document " << object_uri << endl;
- } else {
- object_uri = string("<") + object_uri + ">";
+ else
cout << "[Parser] Parsing " << object_uri << " from " << document_uri << endl;
- }
return parse(world, target, model, document_uri, object_uri, parent, symbol, data);;
}
@@ -74,21 +83,18 @@ Parser::parse_string(
Ingen::Shared::CommonInterface* target,
const Glib::ustring& str,
const Glib::ustring& base_uri,
- Glib::ustring object_uri,
+ boost::optional<Glib::ustring> object_uri,
boost::optional<Raul::Path> parent,
boost::optional<Raul::Symbol> symbol,
boost::optional<GraphObject::Variables> data)
{
Redland::Model model(*world->rdf_world, str.c_str(), str.length(), base_uri);
-
- if (object_uri == "") {
- object_uri = string("<") + base_uri + ">";
- cout << "[Parser] Parsing document " << object_uri << endl;
- } else {
- object_uri = string("<") + object_uri + ">";
- cout << "[Parser] Parsing " << object_uri << " from string" << endl;
- }
-
+
+ if (object_uri)
+ cout << "[Parser] Parsing " << object_uri.get() << " (base " << base_uri << ")" << endl;
+ else
+ cout << "[Parser] Parsing all objects found in string (base " << base_uri << ")" << endl;
+
return parse(world, target, model, base_uri, object_uri, parent, symbol, data);;
}
@@ -98,40 +104,59 @@ Parser::parse(
Ingen::Shared::World* world,
Ingen::Shared::CommonInterface* target,
Redland::Model& model,
- const Glib::ustring& base_uri,
- Glib::ustring object_uri,
+ Glib::ustring base_uri,
+ boost::optional<Glib::ustring> object_uri,
boost::optional<Raul::Path> parent,
boost::optional<Raul::Symbol> symbol,
boost::optional<GraphObject::Variables> data)
{
- Redland::Query query(*world->rdf_world, Glib::ustring(
- "SELECT DISTINCT ?class WHERE { ") + object_uri + " a ?class . }");
-
- Redland::Query::Results results = query.run(*world->rdf_world, model);
+ //if (object_uri)
+ // object_uri = uri_relative_to_base(base_uri, object_uri.get());
+
+ Glib::ustring query_str;
+ if (object_uri)
+ query_str = Glib::ustring("SELECT DISTINCT ?class WHERE { <") + object_uri.get() + "> a ?class . }";
+ else
+ query_str = Glib::ustring("SELECT DISTINCT ?subject ?class WHERE { ?subject a ?class . }");
+
+ Redland::Query query(*world->rdf_world, query_str);
+ Redland::Query::Results results = query.run(*world->rdf_world, model, base_uri);
const Redland::Node patch_class(*world->rdf_world, Redland::Node::RESOURCE, NS_INGEN "Patch");
const Redland::Node node_class(*world->rdf_world, Redland::Node::RESOURCE, NS_INGEN "Node");
const Redland::Node port_class(*world->rdf_world, Redland::Node::RESOURCE, NS_INGEN "Port");
+
+ const Redland::Node subject_uri(*world->rdf_world, Redland::Node::RESOURCE,
+ (object_uri ? object_uri.get() : "http://example.org"));
+
+ bool ret = false;
for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) {
+ const Redland::Node subject = (object_uri ? subject_uri : (*i)["subject"]);
+ cout << "SUBJECT FROM RDF: " << subject.to_string() << endl;
const Redland::Node rdf_class = (*i)["class"];
+ cout << subject.to_c_string() << " :: " << rdf_class.to_c_string() << endl;
if (rdf_class == patch_class || rdf_class == node_class || rdf_class == port_class) {
- Path path = parse_path(world, model, base_uri, object_uri, parent, symbol);
- bool ret = false;
+ Path path = parse_path(world, model, base_uri, subject.to_c_string(), parent, symbol);
if (rdf_class == patch_class) {
- ret = parse_patch(world, target, model, object_uri, path, data);
+ ret = parse_patch(world, target, model, base_uri, subject.to_c_string(), path, data);
if (ret)
target->set_variable(path, "ingen:document", Atom(base_uri.c_str()));
} else if (rdf_class == node_class) {
- cout << "NODE" << endl;
+ ret = parse_node(world, target, model,
+ base_uri, Glib::ustring("<") + subject.to_c_string() + ">", path, data);
} else if (rdf_class == port_class) {
cout << "PORT" << endl;
}
- return ret;
+ if (ret == false) {
+ cerr << "Failed to parse object " << object_uri << endl;
+ return ret;
+ }
}
+
}
- return false;
+ return ret;
}
@@ -143,19 +168,25 @@ Parser::parse_path(Ingen::Shared::World* world,
boost::optional<Raul::Path>& parent,
boost::optional<Raul::Symbol>& symbol)
{
+ string subject = string("</") + uri_relative_to_base(base_uri, object_uri) + ">";
+
Redland::Query query(*world->rdf_world, Glib::ustring(
- "SELECT DISTINCT ?sym WHERE { ") + object_uri + " ingen:symbol ?sym }");
+ "SELECT DISTINCT ?sym WHERE { ") + subject + " ingen:symbol ?sym }");
- Redland::Query::Results results = query.run(*world->rdf_world, model);
+ Redland::Query::Results results = query.run(*world->rdf_world, model, base_uri);
if (results.size() > 0) {
symbol = (*results.begin())["sym"].to_string();
} else {
- const string sym = base_uri.substr(base_uri.find_last_of("/")+1);
- symbol = sym.substr(0, sym.find("."));
+ const string sym = object_uri.substr(base_uri.find_last_of("/")+1);
+ symbol = Symbol::symbolify(sym.substr(0, sym.find(".")));
}
-
- Path ret = (parent ? (parent.get().base() + symbol.get()) : Path("/"));
- cout << "Parsing " << object_uri << " from " << base_uri << " as " << ret << endl;
+
+ Path ret;
+ if (base_uri == object_uri)
+ ret = (parent ? parent.get().base() : Path("/"));
+ else
+ ret = (parent ? parent.get().base() : Path("/")) + symbol.get();
+ cout << "Parsing " << object_uri << " (base " << base_uri << ") to " << ret << endl;
return ret;
}
@@ -165,6 +196,7 @@ Parser::parse_patch(
Ingen::Shared::World* world,
Ingen::Shared::CommonInterface* target,
Redland::Model& model,
+ const Glib::ustring& base_uri,
const Glib::ustring& object_uri,
Raul::Path patch_path,
boost::optional<GraphObject::Variables> data=boost::optional<GraphObject::Variables>())
@@ -178,14 +210,16 @@ Parser::parse_patch(
if (poly_param != data.get().end() && poly_param->second.type() == Atom::INT)
patch_poly = poly_param->second.get_int32();
}
+
+ const Glib::ustring subject = ((object_uri[0] == '<')
+ ? object_uri : Glib::ustring("<") + object_uri + ">");
/* Get polyphony from file (mandatory if not specified in parameters) */
if (patch_poly == 0) {
Redland::Query query(*world->rdf_world, Glib::ustring(
- "SELECT DISTINCT ?poly WHERE {\n") +
- object_uri + " ingen:polyphony ?poly\n }");
+ "SELECT DISTINCT ?poly WHERE { ") + subject + " ingen:polyphony ?poly\n }");
- Redland::Query::Results results = query.run(*world->rdf_world, model);
+ Redland::Query::Results results = query.run(*world->rdf_world, model, base_uri);
if (results.size() == 0) {
cerr << "[Parser] ERROR: No polyphony found!" << endl;
@@ -200,27 +234,20 @@ Parser::parse_patch(
if (patch_path != "/")
target->new_patch(patch_path, patch_poly);
- /* Set document metadata (so File->Save doesn't prompt)
- * FIXME: This needs some thinking for multiple clients... */
-
-
/* Load (plugin) nodes */
-
Redland::Query query(*world->rdf_world, Glib::ustring(
"SELECT DISTINCT ?name ?plugin ?varkey ?varval ?poly WHERE {\n") +
- object_uri + " ingen:node ?node .\n"
- "?node ingen:symbol ?name ;\n"
- " ingen:plugin ?plugin ;\n"
- " ingen:polyphonic ?poly .\n"
+ subject + " ingen:node ?node .\n"
+ "?node ingen:symbol ?name ;\n"
+ " ingen:plugin ?plugin ;\n"
+ " ingen:polyphonic ?poly .\n"
"OPTIONAL { ?node ingen:variable ?variable .\n"
" ?variable ingen:key ?varkey ;\n"
" ingen:value ?varval .\n"
" }"
"}");
- Redland::Query::Results results = query.run(*world->rdf_world, model);
-
- map<const string, const Atom> variable;
+ Redland::Query::Results results = query.run(*world->rdf_world, model, base_uri);
world->rdf_world->mutex().lock();
@@ -253,16 +280,14 @@ Parser::parse_patch(
/* Load subpatches */
-
query = Redland::Query(*world->rdf_world, Glib::ustring(
"SELECT DISTINCT ?patch ?symbol WHERE {\n") +
- object_uri + " ingen:node ?patch .\n"
- "?patch a ingen:Patch ;\n"
- " ingen:symbol ?symbol .\n"
+ subject + " ingen:node ?patch .\n"
+ "?patch a ingen:Patch ;\n"
+ " ingen:symbol ?symbol .\n"
"}");
- results = query.run(*world->rdf_world, model);
-
+ results = query.run(*world->rdf_world, model, base_uri);
for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) {
const string symbol = (*i)["symbol"].to_string();
@@ -272,7 +297,7 @@ Parser::parse_patch(
if (created.find(subpatch_path) == created.end()) {
created.insert(subpatch_path);
- parse_patch(world, target, model, Glib::ustring(object_uri + subpatch_path), subpatch_path);
+ parse_patch(world, target, model, base_uri, Glib::ustring(object_uri + subpatch_path), subpatch_path);
}
}
@@ -280,19 +305,17 @@ Parser::parse_patch(
/* Set node port control values */
-
query = Redland::Query(*world->rdf_world, Glib::ustring(
"SELECT DISTINCT ?nodename ?portname ?portval WHERE {\n") +
- object_uri + " ingen:node ?node .\n"
- "?node ingen:symbol ?nodename ;\n"
- " ingen:port ?port .\n"
- "?port ingen:symbol ?portname ;\n"
- " ingen:value ?portval .\n"
+ subject + " ingen:node ?node .\n"
+ "?node ingen:symbol ?nodename ;\n"
+ " ingen:port ?port .\n"
+ "?port ingen:symbol ?portname ;\n"
+ " ingen:value ?portval .\n"
"FILTER ( datatype(?portval) = xsd:decimal )\n"
- "}\n");
-
- results = query.run(*world->rdf_world, model);
+ "}");
+ results = query.run(*world->rdf_world, model, base_uri);
for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) {
const string node_name = (*i)["nodename"].to_string();
@@ -307,13 +330,12 @@ Parser::parse_patch(
/* Load this patch's ports */
-
query = Redland::Query(*world->rdf_world, Glib::ustring(
"SELECT DISTINCT ?port ?type ?name ?datatype ?varkey ?varval ?portval WHERE {\n") +
- object_uri + " ingen:port ?port .\n"
- "?port a ?type ;\n"
- " a ?datatype ;\n"
- " ingen:symbol ?name .\n"
+ subject + " ingen:port ?port .\n"
+ "?port a ?type ;\n"
+ " a ?datatype ;\n"
+ " ingen:symbol ?name .\n"
" FILTER (?type != ?datatype && ((?type = ingen:InputPort) || (?type = ingen:OutputPort)))\n"
"OPTIONAL { ?port ingen:value ?portval . \n"
" FILTER ( datatype(?portval) = xsd:decimal ) }\n"
@@ -323,8 +345,7 @@ Parser::parse_patch(
" }"
"}");
- results = query.run(*world->rdf_world, model);
-
+ results = query.run(*world->rdf_world, model, base_uri);
for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) {
const string name = (*i)["name"].to_string();
const string type = world->rdf_world->qualify((*i)["type"].to_string());
@@ -354,22 +375,20 @@ Parser::parse_patch(
/* Node -> Node connections */
-
query = Redland::Query(*world->rdf_world, Glib::ustring(
"SELECT DISTINCT ?srcnodename ?srcname ?dstnodename ?dstname WHERE {\n") +
- object_uri + "ingen:node ?srcnode ;\n"
- " ingen:node ?dstnode .\n"
- "?srcnode ingen:port ?src ;\n"
- " ingen:symbol ?srcnodename .\n"
- "?dstnode ingen:port ?dst ;\n"
- " ingen:symbol ?dstnodename .\n"
- "?src ingen:symbol ?srcname .\n"
- "?dst ingen:connectedTo ?src ;\n"
- " ingen:symbol ?dstname .\n"
- "}\n");
-
- results = query.run(*world->rdf_world, model);
+ subject + "ingen:node ?srcnode ;\n"
+ " ingen:node ?dstnode .\n"
+ "?srcnode ingen:port ?src ;\n"
+ " ingen:symbol ?srcnodename .\n"
+ "?dstnode ingen:port ?dst ;\n"
+ " ingen:symbol ?dstnodename .\n"
+ "?src ingen:symbol ?srcname .\n"
+ "?dst ingen:connectedTo ?src ;\n"
+ " ingen:symbol ?dstname .\n"
+ "}");
+ results = query.run(*world->rdf_world, model, base_uri);
for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) {
Path src_node = patch_path.base() + Path::nameify((*i)["srcnodename"].to_string());
Path src_port = src_node.base() + Path::nameify((*i)["srcname"].to_string());
@@ -383,20 +402,18 @@ Parser::parse_patch(
/* This Patch -> Node connections */
-
query = Redland::Query(*world->rdf_world, Glib::ustring(
"SELECT DISTINCT ?srcname ?dstnodename ?dstname WHERE {\n") +
- object_uri + " ingen:port ?src ;\n"
- " ingen:node ?dstnode .\n"
- "?dstnode ingen:port ?dst ;\n"
- " ingen:symbol ?dstnodename .\n"
- "?dst ingen:connectedTo ?src ;\n"
- " ingen:symbol ?dstname .\n"
- "?src ingen:symbol ?srcname .\n"
- "}\n");
-
- results = query.run(*world->rdf_world, model);
+ subject + " ingen:port ?src ;\n"
+ " ingen:node ?dstnode .\n"
+ "?dstnode ingen:port ?dst ;\n"
+ " ingen:symbol ?dstnodename .\n"
+ "?dst ingen:connectedTo ?src ;\n"
+ " ingen:symbol ?dstname .\n"
+ "?src ingen:symbol ?srcname .\n"
+ "}");
+ results = query.run(*world->rdf_world, model, base_uri);
for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) {
Path src_port = patch_path.base() + Path::nameify((*i)["srcname"].to_string());
Path dst_node = patch_path.base() + Path::nameify((*i)["dstnodename"].to_string());
@@ -409,20 +426,18 @@ Parser::parse_patch(
/* Node -> This Patch connections */
-
query = Redland::Query(*world->rdf_world, Glib::ustring(
"SELECT DISTINCT ?srcnodename ?srcname ?dstname WHERE {\n") +
- object_uri + " ingen:port ?dst ;\n"
- " ingen:node ?srcnode .\n"
- "?srcnode ingen:port ?src ;\n"
- " ingen:symbol ?srcnodename .\n"
- "?dst ingen:connectedTo ?src ;\n"
- " ingen:symbol ?dstname .\n"
- "?src ingen:symbol ?srcname .\n"
- "}\n");
-
- results = query.run(*world->rdf_world, model);
+ subject + " ingen:port ?dst ;\n"
+ " ingen:node ?srcnode .\n"
+ "?srcnode ingen:port ?src ;\n"
+ " ingen:symbol ?srcnodename .\n"
+ "?dst ingen:connectedTo ?src ;\n"
+ " ingen:symbol ?dstname .\n"
+ "?src ingen:symbol ?srcname .\n"
+ "}");
+ results = query.run(*world->rdf_world, model, base_uri);
for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) {
Path dst_port = patch_path.base() + Path::nameify((*i)["dstname"].to_string());
Path src_node = patch_path.base() + Path::nameify((*i)["srcnodename"].to_string());
@@ -435,18 +450,16 @@ Parser::parse_patch(
/* This Patch -> This Patch connections */
-
query = Redland::Query(*world->rdf_world, Glib::ustring(
"SELECT DISTINCT ?srcname ?dstname WHERE {\n") +
- object_uri + " ingen:port ?src ;\n"
- " ingen:port ?dst .\n"
- "?dst ingen:connectedTo ?src ;\n"
- " ingen:symbol ?dstname .\n"
- "?src ingen:symbol ?srcname .\n"
- "}\n");
-
- results = query.run(*world->rdf_world, model);
+ subject + " ingen:port ?src ;\n"
+ " ingen:port ?dst .\n"
+ "?dst ingen:connectedTo ?src ;\n"
+ " ingen:symbol ?dstname .\n"
+ "?src ingen:symbol ?srcname .\n"
+ "}");
+ results = query.run(*world->rdf_world, model, base_uri);
for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) {
Path src_port = patch_path.base() + Path::nameify((*i)["srcname"].to_string());
Path dst_port = patch_path.base() + Path::nameify((*i)["dstname"].to_string());
@@ -456,58 +469,104 @@ Parser::parse_patch(
target->connect(src_port, dst_port);
}
+ parse_variables(world, target, model, base_uri, subject, patch_path, data);
- /* Load variables */
-
+ /* Enable */
query = Redland::Query(*world->rdf_world, Glib::ustring(
- "SELECT DISTINCT ?varkey ?varval WHERE {\n") +
- object_uri + " ingen:variable ?variable .\n"
- "?variable ingen:key ?varkey ;\n"
- " ingen:value ?varval .\n"
- "}");
-
- results = query.run(*world->rdf_world, model);
+ "SELECT DISTINCT ?enabled WHERE { ") + subject + " ingen:enabled ?enabled }");
+ results = query.run(*world->rdf_world, model, base_uri);
for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) {
+ Redland::Node enabled_node = (*i)["enabled"];
- const string key = world->rdf_world->prefixes().qualify(string((*i)["varkey"]));
- Redland::Node val_node = (*i)["varval"];
-
- if (key != "")
- target->set_variable(patch_path, key, AtomRDF::node_to_atom(val_node));
+ if (enabled_node.is_bool() && enabled_node) {
+ target->set_property(patch_path, "ingen:enabled", (bool)true);
+ break;
+ } else {
+ cerr << "WARNING: Unknown type for property ingen:enabled" << endl;
+ }
}
+ return true;
+}
- // Set passed variables last to override any loaded values
- if (data)
- for (GraphObject::Variables::const_iterator i = data.get().begin(); i != data.get().end(); ++i)
- target->set_variable(patch_path, i->first, i->second);
+bool
+Parser::parse_node(
+ Ingen::Shared::World* world,
+ Ingen::Shared::CommonInterface* target,
+ Redland::Model& model,
+ const Glib::ustring& base_uri,
+ Glib::ustring subject,
+ Raul::Path path,
+ boost::optional<GraphObject::Variables> data=boost::optional<GraphObject::Variables>())
+{
+ /* Get plugin */
+ Redland::Query query(*world->rdf_world, Glib::ustring(
+ "SELECT DISTINCT ?plug WHERE { ") + subject + " ingen:plugin ?plug }");
- /* Enable */
+ Redland::Query::Results results = query.run(*world->rdf_world, model, base_uri);
- query = Redland::Query(*world->rdf_world, Glib::ustring(
- "SELECT DISTINCT ?enabled WHERE {\n") +
- object_uri + " ingen:enabled ?enabled .\n"
- "}");
+ if (results.size() == 0) {
+ cerr << "[Parser] ERROR: Node missing mandatory ingen:plugin property" << endl;
+ return false;
+ }
+
+ for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) {
+ Redland::Node s_node = (*i)["s"];
+ Redland::Node plug_node = (*i)["plug"];
+ cout << s_node.to_c_string() << " :: " << plug_node.to_c_string() << endl;
+ }
- results = query.run(*world->rdf_world, model);
+ const Redland::Node& plugin_node = (*results.begin())["plug"];
+ if (plugin_node.type() != Redland::Node::RESOURCE) {
+ cerr << "[Parser] ERROR: node's ingen:plugin property is not a resource" << endl;
+ return false;
+ }
- for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) {
+ target->new_node(path, plugin_node.to_c_string());
+ parse_variables(world, target, model, base_uri, subject, path, data);
- Redland::Node enabled_node = (*i)["enabled"];
+ return true;
+}
- if (enabled_node.is_bool() && enabled_node) {
- target->set_property(patch_path, "ingen:enabled", (bool)true);
- break;
- } else {
- cerr << "WARNING: Unknown type for property ingen:enabled" << endl;
- }
+
+
+bool
+Parser::parse_variables(
+ Ingen::Shared::World* world,
+ Ingen::Shared::CommonInterface* target,
+ Redland::Model& model,
+ const Glib::ustring& base_uri,
+ const Glib::ustring& subject,
+ Raul::Path path,
+ boost::optional<GraphObject::Variables> data=boost::optional<GraphObject::Variables>())
+{
+ /* Parse variables */
+ Redland::Query query = Redland::Query(*world->rdf_world, Glib::ustring(
+ "SELECT DISTINCT ?varkey ?varval WHERE {\n") +
+ subject + " ingen:variable ?variable .\n"
+ "?variable ingen:key ?varkey ;\n"
+ " ingen:value ?varval .\n"
+ "}");
+
+ Redland::Query::Results results = query.run(*world->rdf_world, model, base_uri);
+ for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) {
+ const string key = world->rdf_world->prefixes().qualify(string((*i)["varkey"]));
+ Redland::Node val_node = (*i)["varval"];
+ if (key != "")
+ target->set_variable(path, key, AtomRDF::node_to_atom(val_node));
}
+ // Set passed variables last to override any loaded values
+ if (data)
+ for (GraphObject::Variables::const_iterator i = data.get().begin(); i != data.get().end(); ++i)
+ target->set_variable(path, i->first, i->second);
+
return true;
}
+
} // namespace Serialisation
} // namespace Ingen
diff --git a/src/libs/serialisation/Parser.hpp b/src/libs/serialisation/Parser.hpp
index 2aaf3bfb..4ee94d46 100644
--- a/src/libs/serialisation/Parser.hpp
+++ b/src/libs/serialisation/Parser.hpp
@@ -54,18 +54,21 @@ public:
Shared::CommonInterface* target,
const Glib::ustring& str,
const Glib::ustring& base_uri,
- Glib::ustring object_uri,
+ boost::optional<Glib::ustring> object_uri=boost::optional<Glib::ustring>(),
boost::optional<Raul::Path> parent=boost::optional<Raul::Path>(),
boost::optional<Raul::Symbol> symbol=boost::optional<Raul::Symbol>(),
boost::optional<GraphObject::Variables> data=boost::optional<GraphObject::Variables>());
private:
+
+ Glib::ustring uri_relative_to_base(const Glib::ustring base, const Glib::ustring uri);
+
bool parse(
Ingen::Shared::World* world,
Shared::CommonInterface* target,
Redland::Model& model,
- const Glib::ustring& base_uri,
- Glib::ustring object_uri,
+ Glib::ustring base_uri,
+ boost::optional<Glib::ustring> object_uri=boost::optional<Glib::ustring>(),
boost::optional<Raul::Path> parent=boost::optional<Raul::Path>(),
boost::optional<Raul::Symbol> symbol=boost::optional<Raul::Symbol>(),
boost::optional<GraphObject::Variables> data=boost::optional<GraphObject::Variables>());
@@ -82,9 +85,28 @@ private:
Ingen::Shared::World* world,
Ingen::Shared::CommonInterface* target,
Redland::Model& model,
+ const Glib::ustring& base_uri,
const Glib::ustring& object_uri,
Raul::Path path,
boost::optional<GraphObject::Variables> data);
+
+ bool parse_node(
+ Ingen::Shared::World* world,
+ Ingen::Shared::CommonInterface* target,
+ Redland::Model& model,
+ const Glib::ustring& base_uri,
+ Glib::ustring subject,
+ Raul::Path path,
+ boost::optional<GraphObject::Variables> data);
+
+ bool parse_variables(
+ Ingen::Shared::World* world,
+ Ingen::Shared::CommonInterface* target,
+ Redland::Model& model,
+ const Glib::ustring& base_uri,
+ const Glib::ustring& subject,
+ Raul::Path path,
+ boost::optional<GraphObject::Variables> data);
};
diff --git a/src/libs/serialisation/Serialiser.cpp b/src/libs/serialisation/Serialiser.cpp
index a56d6add..8f0241e0 100644
--- a/src/libs/serialisation/Serialiser.cpp
+++ b/src/libs/serialisation/Serialiser.cpp
@@ -380,6 +380,11 @@ Serialiser::serialise_node(SharedPtr<Shared::Node> node, const Redland::Node& no
Redland::Node(_model->world(), Redland::Node::LITERAL, node->path().name()));
_model->add_statement(
+ plugin_id,
+ "rdf:type",
+ Redland::Node(_model->world(), Redland::Node::RESOURCE, "ingen:Plugin"));
+
+ _model->add_statement(
node_id,
"ingen:plugin",
plugin_id);
diff --git a/src/libs/shared/Builder.cpp b/src/libs/shared/Builder.cpp
new file mode 100644
index 00000000..062afc63
--- /dev/null
+++ b/src/libs/shared/Builder.cpp
@@ -0,0 +1,88 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "Builder.hpp"
+#include "common/interface/CommonInterface.hpp"
+#include "common/interface/Patch.hpp"
+#include "common/interface/Node.hpp"
+#include "common/interface/Port.hpp"
+#include "common/interface/Connection.hpp"
+#include "common/interface/Plugin.hpp"
+#include <iostream>
+using namespace std;
+
+namespace Ingen {
+namespace Shared {
+
+
+Builder::Builder(CommonInterface& interface)
+ : _interface(interface)
+{
+}
+
+
+void
+Builder::build(SharedPtr<const GraphObject> object)
+{
+ cout << "BUILDING: " << object->path() << endl;
+
+ SharedPtr<const Patch> patch = PtrCast<const Patch>(object);
+ if (patch) {
+ if (patch->path() != "/")
+ _interface.new_patch(patch->path() + "_copy", patch->internal_polyphony());
+ build_object(object);
+ for (Patch::Connections::const_iterator i = patch->connections().begin();
+ i != patch->connections().end(); ++i)
+ _interface.connect((*i)->src_port_path(), (*i)->dst_port_path());
+ return;
+ }
+
+ SharedPtr<const Node> node = PtrCast<const Node>(object);
+ if (node) {
+ _interface.new_node(node->path() + "_copy", node->plugin()->uri());
+ build_object(object);
+ return;
+ }
+
+ SharedPtr<const Port> port = PtrCast<const Port>(object);
+ if (port) {
+ _interface.new_port(port->path() + "_copy", port->index(), port->type().uri(), !port->is_input());
+ build_object(object);
+ return;
+ }
+}
+
+
+void
+Builder::build_object(SharedPtr<const GraphObject> object)
+{
+ for (GraphObject::Variables::const_iterator i = object->variables().begin();
+ i != object->variables().end(); ++i) {
+ cout << "SETTING " << object->path() << " . " << i->first << endl;
+ _interface.set_variable(object->path() + "_copy", i->first, i->second);
+ }
+
+ for (GraphObject::Properties::const_iterator i = object->properties().begin();
+ i != object->properties().end(); ++i) {
+ cout << "SETTING " << object->path() << " . " << i->first << endl;
+ _interface.set_property(object->path() + "_copy", i->first, i->second);
+ }
+}
+
+
+} // namespace Shared
+} // namespace Ingen
diff --git a/src/libs/shared/Builder.hpp b/src/libs/shared/Builder.hpp
new file mode 100644
index 00000000..01d3b7e5
--- /dev/null
+++ b/src/libs/shared/Builder.hpp
@@ -0,0 +1,53 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef BUILDER_H
+#define BUILDER_H
+
+#include <raul/SharedPtr.hpp>
+
+namespace Ingen {
+namespace Shared {
+
+class GraphObject;
+class CommonInterface;
+
+
+/** Wrapper for CommonInterface to create existing objects/models.
+ *
+ * \ingroup interface
+ */
+class Builder
+{
+public:
+ Builder(CommonInterface& interface);
+ virtual ~Builder() {}
+
+ void build(SharedPtr<const GraphObject> object);
+
+private:
+ void build_object(SharedPtr<const GraphObject> object);
+
+ CommonInterface& _interface;
+};
+
+
+} // namespace Shared
+} // namespace Ingen
+
+#endif // BUILDER_H
+
diff --git a/src/libs/shared/Makefile.am b/src/libs/shared/Makefile.am
index 9e52923a..fcb261c8 100644
--- a/src/libs/shared/Makefile.am
+++ b/src/libs/shared/Makefile.am
@@ -8,6 +8,8 @@ libingen_shared_la_CXXFLAGS = \
@SLV2_CFLAGS@
libingen_shared_la_SOURCES = \
+ Builder.cpp \
+ Builder.hpp \
LV2Features.cpp \
LV2Features.hpp \
LV2URIMap.cpp \
diff --git a/src/libs/shared/Store.cpp b/src/libs/shared/Store.cpp
index 88fb9cb8..f77be312 100644
--- a/src/libs/shared/Store.cpp
+++ b/src/libs/shared/Store.cpp
@@ -17,6 +17,8 @@
#include <raul/PathTable.hpp>
#include <raul/TableImpl.hpp>
+#include "common/interface/Node.hpp"
+#include "common/interface/Port.hpp"
#include "Store.hpp"
using namespace std;
@@ -26,6 +28,25 @@ namespace Ingen {
namespace Shared {
+void
+Store::add(GraphObject* o)
+{
+ if (find(o->path()) != end()) {
+ cerr << "[Store] ERROR: Attempt to add duplicate object " << o->path() << endl;
+ return;
+ }
+
+ insert(make_pair(o->path(), o));
+
+ Node* node = dynamic_cast<Node*>(o);
+ if (node) {
+ for (uint32_t i=0; i < node->num_ports(); ++i) {
+ add(node->port(i));
+ }
+ }
+}
+
+
Store::const_iterator
Store::children_begin(SharedPtr<Shared::GraphObject> o) const
{
diff --git a/src/libs/shared/Store.hpp b/src/libs/shared/Store.hpp
index f0a89024..573c4837 100644
--- a/src/libs/shared/Store.hpp
+++ b/src/libs/shared/Store.hpp
@@ -31,8 +31,10 @@ namespace Shared {
class Store : public Raul::PathTable< SharedPtr<Shared::GraphObject> > {
public:
- virtual void add(GraphObject* o) = 0;
+ virtual ~Store() {}
+ virtual void add(Shared::GraphObject* o);
+
typedef Raul::Table< Raul::Path, SharedPtr<Shared::GraphObject> > Objects;
const_iterator children_begin(SharedPtr<Shared::GraphObject> o) const;