summaryrefslogtreecommitdiffstats
path: root/src/libs/client/ClientStore.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/client/ClientStore.cpp')
-rw-r--r--src/libs/client/ClientStore.cpp721
1 files changed, 623 insertions, 98 deletions
diff --git a/src/libs/client/ClientStore.cpp b/src/libs/client/ClientStore.cpp
index 24c23f14..13250abc 100644
--- a/src/libs/client/ClientStore.cpp
+++ b/src/libs/client/ClientStore.cpp
@@ -15,141 +15,666 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef STORE_H
-#define STORE_H
-
-#include <cassert>
-#include <string>
-#include <list>
-#include <raul/SharedPtr.hpp>
-#include <sigc++/sigc++.h>
-#include <raul/Path.hpp>
-#include <raul/Atom.hpp>
#include <raul/PathTable.hpp>
-#include <raul/TableImpl.hpp>
-#include "interface/EngineInterface.hpp"
-#include "shared/Store.hpp"
-using std::string; using std::list;
-using Ingen::Shared::EngineInterface;
-using Raul::Path;
-using Raul::Atom;
+#include "ClientStore.hpp"
+#include "ObjectModel.hpp"
+#include "PatchModel.hpp"
+#include "NodeModel.hpp"
+#include "PortModel.hpp"
+#include "PluginModel.hpp"
+#include "PatchModel.hpp"
+#include "SigClientInterface.hpp"
+
+using namespace std;
+using namespace Raul;
namespace Ingen {
+namespace Client {
-namespace Shared { class GraphObject; }
-namespace Client {
+ClientStore::ClientStore(SharedPtr<EngineInterface> engine, SharedPtr<SigClientInterface> emitter)
+ : _engine(engine)
+ , _emitter(emitter)
+{
+ 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_polyphonic.connect(sigc::mem_fun(this, &ClientStore::polyphonic_event));
+ emitter->signal_patch_enabled.connect(sigc::mem_fun(this, &ClientStore::patch_enabled_event));
+ emitter->signal_patch_disabled.connect(sigc::mem_fun(this, &ClientStore::patch_disabled_event));
+ emitter->signal_patch_polyphony.connect(sigc::mem_fun(this, &ClientStore::patch_polyphony_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_control_change.connect(sigc::mem_fun(this, &ClientStore::control_change_event));
+ emitter->signal_port_activity.connect(sigc::mem_fun(this, &ClientStore::port_activity_event));
+}
-class SigClientInterface;
-class ObjectModel;
-class PluginModel;
-class PatchModel;
-class NodeModel;
-class PortModel;
-class ConnectionModel;
+void
+ClientStore::clear()
+{
+ _objects.clear();
+ _plugins.clear();
+}
-/** Automatically manages models of objects in the engine.
- *
- * \ingroup IngenClient
- */
-class ClientStore : public Shared::Store, public sigc::trackable { // FIXME: is trackable necessary?
-public:
- ClientStore(SharedPtr<EngineInterface> engine, SharedPtr<SigClientInterface> emitter);
- SharedPtr<PluginModel> plugin(const string& uri);
- SharedPtr<ObjectModel> object(const Path& path);
+void
+ClientStore::add_plugin_orphan(SharedPtr<NodeModel> node)
+{
+ cerr << "WARNING: Node " << node->path() << " received, but plugin "
+ << node->plugin_uri() << " unknown." << endl;
+
+ Raul::Table<string, list<SharedPtr<NodeModel> > >::iterator spawn
+ = _plugin_orphans.find(node->plugin_uri());
+
+ _engine->request_plugin(node->plugin_uri());
+
+ if (spawn != _plugin_orphans.end()) {
+ spawn->second.push_back(node);
+ } else {
+ list<SharedPtr<NodeModel> > l;
+ l.push_back(node);
+ _plugin_orphans[node->plugin_uri()] = l;
+ }
+}
+
+
+void
+ClientStore::resolve_plugin_orphans(SharedPtr<PluginModel> plugin)
+{
+ Raul::Table<string, list<SharedPtr<NodeModel> > >::iterator n
+ = _plugin_orphans.find(plugin->uri());
+
+ if (n != _plugin_orphans.end()) {
+
+ list<SharedPtr<NodeModel> > spawn = n->second; // take a copy
+ cerr << "Missing dependant " << plugin->uri() << " received" << endl;
+
+ _plugin_orphans.erase(plugin->uri()); // prevent infinite recursion
+
+ for (list<SharedPtr<NodeModel> >::iterator i = spawn.begin();
+ i != spawn.end(); ++i) {
+ (*i)->_plugin = plugin;
+ add_object(*i);
+ }
+ }
+}
+
+
+void
+ClientStore::add_connection_orphan(std::pair<Path, Path> orphan)
+{
+ cerr << "WARNING: Orphan connection " << orphan.first
+ << " -> " << orphan.second << " received." << endl;
+
+ _connection_orphans.push_back(orphan);
+}
+
+
+void
+ClientStore::resolve_connection_orphans(SharedPtr<PortModel> port)
+{
+ assert(port->parent());
+
+ for (list< pair<Path, Path> >::iterator c = _connection_orphans.begin();
+ c != _connection_orphans.end(); ) {
+
+ list< pair<Path, Path> >::iterator next = c;
+ ++next;
+
+ if (c->first == port->path() || c->second == port->path()) {
+ cerr << "Missing dependant (" << c->first << " -> " << c->second << ") received" << endl;
+ bool success = attempt_connection(c->first, c->second);
+ if (success)
+ _connection_orphans.erase(c);
+ }
+
+ c = next;
+ }
+}
+
+
+void
+ClientStore::add_orphan(SharedPtr<ObjectModel> child)
+{
+ cerr << "WARNING: Orphan object " << child->path() << " received." << endl;
+
+ Raul::PathTable<list<SharedPtr<ObjectModel> > >::iterator children
+ = _orphans.find(child->path().parent());
+
+ _engine->request_object(child->path().parent());
+
+ if (children != _orphans.end()) {
+ children->second.push_back(child);
+ } else {
+ list<SharedPtr<ObjectModel> > l;
+ l.push_back(child);
+ _orphans.insert(make_pair(child->path().parent(), l));
+ }
+}
+
+
+void
+ClientStore::add_variable_orphan(const Path& subject_path, const string& predicate, const Atom& value)
+{
+ Raul::PathTable<list<std::pair<string, Atom> > >::iterator orphans
+ = _variable_orphans.find(subject_path);
+
+ _engine->request_object(subject_path);
+
+ if (orphans != _variable_orphans.end()) {
+ orphans->second.push_back(std::pair<string, Atom>(predicate, value));
+ } else {
+ list<std::pair<string, Atom> > l;
+ l.push_back(std::pair<string, Atom>(predicate, value));
+ _variable_orphans[subject_path] = l;
+ }
+}
+
+
+void
+ClientStore::resolve_variable_orphans(SharedPtr<ObjectModel> subject)
+{
+ Raul::PathTable<list<std::pair<string, Atom> > >::iterator v
+ = _variable_orphans.find(subject->path());
+
+ if (v != _variable_orphans.end()) {
+
+ list<std::pair<string, Atom> > values = v->second; // take a copy
+
+ _variable_orphans.erase(subject->path());
+ cerr << "Missing dependant " << subject->path() << " received" << endl;
+
+ for (list<std::pair<string, Atom> >::iterator i = values.begin();
+ i != values.end(); ++i) {
+ subject->set_variable(i->first, i->second);
+ }
+ }
+}
+
+
+void
+ClientStore::resolve_orphans(SharedPtr<ObjectModel> parent)
+{
+ Raul::PathTable<list<SharedPtr<ObjectModel> > >::iterator c
+ = _orphans.find(parent->path());
+
+ if (c != _orphans.end()) {
+
+ list<SharedPtr<ObjectModel> > children = c->second; // take a copy
+
+ _orphans.erase(parent->path()); // prevent infinite recursion
+
+ for (list<SharedPtr<ObjectModel> >::iterator i = children.begin();
+ i != children.end(); ++i) {
+ add_object(*i);
+ }
+ }
+}
+
+
+void
+ClientStore::add_object(SharedPtr<ObjectModel> object)
+{
+ // If we already have "this" object, merge the existing one into the new
+ // one (with precedence to the new values).
+ Objects::iterator existing = _objects.find(object->path());
+ if (existing != _objects.end()) {
+ PtrCast<ObjectModel>(existing->second)->set(object);
+ } else {
+
+ if (object->path() != "/") {
+ SharedPtr<ObjectModel> parent = this->object(object->path().parent());
+ if (parent) {
+ assert(object->path().is_child_of(parent->path()));
+ object->set_parent(parent);
+ parent->add_child(object);
+ assert(parent && (object->parent() == parent));
+
+ _objects[object->path()] = object;
+ signal_new_object.emit(object);
+
+ resolve_variable_orphans(parent);
+ resolve_orphans(parent);
+
+ SharedPtr<PortModel> port = PtrCast<PortModel>(object);
+ if (port)
+ resolve_connection_orphans(port);
+
+ } else {
+ add_orphan(object);
+ }
+ } else {
+ _objects[object->path()] = object;
+ signal_new_object.emit(object);
+ }
+
+ }
+
+ /*cout << "[Store] Added " << object->path() << " {" << endl;
+ for (Objects::iterator i = _objects.begin(); i != _objects.end(); ++i) {
+ cout << "\t" << i->first << endl;
+ }
+ cout << "}" << endl;*/
+}
+
+
+SharedPtr<ObjectModel>
+ClientStore::remove_object(const Path& path)
+{
+ Objects::iterator i = _objects.find(path);
+
+ if (i != _objects.end()) {
+ assert((*i).second->path() == path);
+ SharedPtr<ObjectModel> result = PtrCast<ObjectModel>((*i).second);
+ assert(result);
+ //_objects.erase(i);
+ Objects::iterator descendants_end = _objects.find_descendants_end(i);
+ SharedPtr< Table<Path, SharedPtr<Shared::GraphObject> > > removed
+ = _objects.yank(i, descendants_end);
+
+ /*cout << "[Store] Removing " << i->first << " {" << endl;
+ for (Objects::iterator i = removed.begin(); i != removed.end(); ++i) {
+ cout << "\t" << i->first << endl;
+ }
+ cout << "}" << endl;*/
+
+ if (result)
+ result->signal_destroyed.emit();
+
+ if (result->path() != "/") {
+ assert(result->parent());
+
+ SharedPtr<ObjectModel> parent = this->object(result->path().parent());
+ if (parent) {
+ parent->remove_child(result);
+ }
+ }
+
+ assert(!object(path));
+
+ return result;
+
+ } else {
+ cerr << "[Store] Unable to find object " << path << " to remove." << endl;
+ return SharedPtr<ObjectModel>();
+ }
+}
+
- void clear();
+SharedPtr<PluginModel>
+ClientStore::plugin(const string& uri)
+{
+ assert(uri.length() > 0);
+ Plugins::iterator i = _plugins.find(uri);
+ if (i == _plugins.end())
+ return SharedPtr<PluginModel>();
+ else
+ return (*i).second;
+}
- size_t num_object() { return _objects.size(); }
+
+SharedPtr<ObjectModel>
+ClientStore::object(const Path& path)
+{
+ assert(path.length() > 0);
+ Objects::iterator i = _objects.find(path);
+ if (i == _objects.end()) {
+ return SharedPtr<ObjectModel>();
+ } else {
+ SharedPtr<ObjectModel> model = PtrCast<ObjectModel>(i->second);
+ assert(model);
+ assert(model->path() == "/" || model->parent());
+ return model;
+ }
+}
+
+void
+ClientStore::add_plugin(SharedPtr<PluginModel> pm)
+{
+ // FIXME: dupes? merge, like with objects?
+
+ _plugins[pm->uri()] = pm;
+ signal_new_plugin(pm);
+ //cerr << "Plugin: " << pm->uri() << ", # plugins: " << _plugins.size() << endl;
+}
+
+
+ClientStore::Objects::const_iterator
+ClientStore::children_begin(SharedPtr<Shared::GraphObject> o) const
+{
+ Objects::const_iterator parent = _objects.find(o->path());
+ assert(parent != _objects.end());
+ ++parent;
+ return parent;
+}
+
+
+ClientStore::Objects::const_iterator
+ClientStore::children_end(SharedPtr<Shared::GraphObject> o) const
+{
+ Objects::const_iterator parent = _objects.find(o->path());
+ assert(parent != _objects.end());
+ return _objects.find_descendants_end(parent);
+}
+
+
+SharedPtr<Shared::GraphObject>
+ClientStore::find_child(SharedPtr<Shared::GraphObject> parent, const string& child_name) const
+{
+ Objects::const_iterator pi = _objects.find(parent->path());
+ assert(pi != _objects.end());
+ Objects::const_iterator children_end = _objects.find_descendants_end(pi);
+ Objects::const_iterator child = _objects.find(pi, children_end, parent->path().base() + child_name);
+ if (child != _objects.end())
+ return PtrCast<ObjectModel>(child->second);
+ else
+ return SharedPtr<ObjectModel>();
+}
+
+
+/* ****** Signal Handlers ******** */
+
+
+void
+ClientStore::destruction_event(const Path& path)
+{
+ SharedPtr<ObjectModel> removed = remove_object(path);
+
+ removed.reset();
+
+ /*cerr << "Store removed object " << path
+ << ", count: " << removed.use_count();*/
+}
+
+void
+ClientStore::rename_event(const Path& old_path, const Path& new_path)
+{
+ Objects::iterator parent = _objects.find(old_path);
+ if (parent == _objects.end()) {
+ cerr << "[Store] Failed to find object " << old_path << " to rename." << endl;
+ return;
+ }
+
+ Objects::iterator descendants_end = _objects.find_descendants_end(parent);
+
+ SharedPtr< Table<Path, SharedPtr<Shared::GraphObject> > > removed
+ = _objects.yank(parent, descendants_end);
- Objects::iterator find(const Path& path) { return _objects.find(path); }
+ assert(removed->size() > 0);
+
+ for (Table<Path, SharedPtr<Shared::GraphObject> >::iterator i = removed->begin(); i != removed->end(); ++i) {
+ const Path& child_old_path = i->first;
+ assert(Path::descendant_comparator(old_path, child_old_path));
+
+ Path child_new_path;
+ if (child_old_path == old_path)
+ child_new_path = new_path;
+ else
+ child_new_path = new_path.base() + child_old_path.substr(old_path.length()+1);
+
+ cerr << "[Store] Renamed " << child_old_path << " -> " << child_new_path << endl;
+ PtrCast<ObjectModel>(i->second)->set_path(child_new_path);
+ i->first = child_new_path;
+ }
+
+ _objects.cram(*removed.get());
+
+ //cerr << "[Store] Table:" << endl;
+ //for (size_t i=0; i < removed.size(); ++i) {
+ // cerr << removed[i].first << "\t\t: " << removed[i].second << endl;
+ //}
+ /*for (Objects::iterator i = _objects.begin(); i != _objects.end(); ++i) {
+ cerr << i->first << "\t\t: " << i->second << endl;
+ }*/
+}
+
+void
+ClientStore::new_plugin_event(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);
+ resolve_plugin_orphans(p);
+}
+
+
+void
+ClientStore::new_patch_event(const Path& path, uint32_t poly)
+{
+ SharedPtr<PatchModel> p(new PatchModel(path, poly));
+ add_object(p);
+}
+
+
+void
+ClientStore::new_node_event(const string& plugin_uri, const Path& node_path, bool is_polyphonic, uint32_t num_ports)
+{
+ // FIXME: num_ports unused
- typedef Raul::Table<string, SharedPtr<PluginModel> > Plugins;
- const Plugins& plugins() const { return _plugins; }
+ SharedPtr<PluginModel> plug = plugin(plugin_uri);
+ if (!plug) {
+ SharedPtr<NodeModel> n(new NodeModel(plugin_uri, node_path, is_polyphonic));
+ add_plugin_orphan(n);
+ } else {
+ SharedPtr<NodeModel> n(new NodeModel(plug, node_path, is_polyphonic));
+ add_object(n);
+ }
+}
+
- typedef Raul::PathTable< SharedPtr<Shared::GraphObject> > Objects;
- const Objects& objects() const { return _objects; }
- Objects& objects() { return _objects; }
+void
+ClientStore::new_port_event(const Path& path, uint32_t index, const string& type, bool is_output)
+{
+ PortModel::Direction pdir = is_output ? PortModel::OUTPUT : PortModel::INPUT;
- Objects::const_iterator children_begin(SharedPtr<Shared::GraphObject> o) const;
- Objects::const_iterator children_end(SharedPtr<Shared::GraphObject> o) const;
+ SharedPtr<PortModel> p(new PortModel(path, index, type, pdir));
+ add_object(p);
+ if (p->parent())
+ resolve_connection_orphans(p);
+}
+
+
+void
+ClientStore::polyphonic_event(const Path& path, bool polyphonic)
+{
+ SharedPtr<ObjectModel> object = this->object(path);
+ if (object)
+ object->set_polyphonic(polyphonic);
+}
- SharedPtr<Shared::GraphObject> find_child(SharedPtr<Shared::GraphObject> parent,
- const string& child_name) const;
- sigc::signal<void, SharedPtr<ObjectModel> > signal_new_object;
- sigc::signal<void, SharedPtr<PluginModel> > signal_new_plugin;
+void
+ClientStore::patch_enabled_event(const Path& path)
+{
+ SharedPtr<PatchModel> patch = PtrCast<PatchModel>(object(path));
+ if (patch)
+ patch->enable();
+}
-private:
- void add(Shared::GraphObject* o) { throw; }
+void
+ClientStore::patch_disabled_event(const Path& path)
+{
+ SharedPtr<PatchModel> patch = PtrCast<PatchModel>(object(path));
+ if (patch)
+ patch->disable();
+}
- void add_object(SharedPtr<ObjectModel> object);
- SharedPtr<ObjectModel> remove_object(const Path& path);
- void add_plugin(SharedPtr<PluginModel> plugin);
+void
+ClientStore::patch_polyphony_event(const Path& path, uint32_t poly)
+{
+ SharedPtr<PatchModel> patch = PtrCast<PatchModel>(object(path));
+ if (patch)
+ patch->poly(poly);
+}
+
+
+void
+ClientStore::patch_cleared_event(const Path& path)
+{
+ Objects::iterator i = _objects.find(path);
+ if (i != _objects.end()) {
+ assert((*i).second->path() == path);
+ SharedPtr<PatchModel> patch = PtrCast<PatchModel>(i->second);
+
+ Objects::iterator first_descendant = i;
+ ++first_descendant;
+ Objects::iterator descendants_end = _objects.find_descendants_end(i);
+ SharedPtr< Table<Path, SharedPtr<Shared::GraphObject> > > removed
+ = _objects.yank(first_descendant, descendants_end);
+
+ for (Objects::iterator i = removed->begin(); i != removed->end(); ++i) {
+ SharedPtr<ObjectModel> model = PtrCast<ObjectModel>(i->second);
+ assert(model);
+ model->signal_destroyed.emit();
+ if (model->parent() == patch)
+ patch->remove_child(model);
+ }
+
+ } else {
+ cerr << "[Store] Unable to find patch " << path << " to clear." << endl;
+ }
+}
+
- SharedPtr<PatchModel> connection_patch(const Path& src_port_path, const Path& dst_port_path);
+void
+ClientStore::variable_change_event(const Path& subject_path, const string& predicate, const Atom& value)
+{
+ SharedPtr<ObjectModel> subject = object(subject_path);
+
+ if (!value.is_valid()) {
+ cerr << "ERROR: variable '" << predicate << "' has no type" << endl;
+ } else if (subject) {
+ subject->set_variable(predicate, value);
+ } else {
+ add_variable_orphan(subject_path, predicate, value);
+ cerr << "WARNING: variable for unknown object " << subject_path << endl;
+ }
+}
+
+
+void
+ClientStore::control_change_event(const Path& port_path, float value)
+{
+ SharedPtr<PortModel> port = PtrCast<PortModel>(object(port_path));
+ if (port)
+ port->value(value);
+ else
+ cerr << "ERROR: control change for nonexistant port " << port_path << endl;
+}
- // It would be nice to integrate these somehow..
- void add_orphan(SharedPtr<ObjectModel> orphan);
- void resolve_orphans(SharedPtr<ObjectModel> parent);
+void
+ClientStore::port_activity_event(const Path& port_path)
+{
+ SharedPtr<PortModel> port = PtrCast<PortModel>(object(port_path));
+ if (port)
+ port->signal_activity.emit();
+ else
+ cerr << "ERROR: activity for nonexistant port " << port_path << endl;
+}
+
+
+SharedPtr<PatchModel>
+ClientStore::connection_patch(const Path& src_port_path, const Path& dst_port_path)
+{
+ SharedPtr<PatchModel> patch;
+
+ if (src_port_path.parent() == dst_port_path.parent())
+ patch = PtrCast<PatchModel>(this->object(src_port_path.parent()));
- void add_connection_orphan(std::pair<Path, Path> orphan);
- void resolve_connection_orphans(SharedPtr<PortModel> port);
+ if (!patch && src_port_path.parent() == dst_port_path.parent().parent())
+ patch = PtrCast<PatchModel>(this->object(src_port_path.parent()));
+
+ if (!patch && src_port_path.parent().parent() == dst_port_path.parent())
+ patch = PtrCast<PatchModel>(this->object(dst_port_path.parent()));
- void add_plugin_orphan(SharedPtr<NodeModel> orphan);
- void resolve_plugin_orphans(SharedPtr<PluginModel> plugin);
+ if (!patch)
+ patch = PtrCast<PatchModel>(this->object(src_port_path.parent().parent()));
+
+ if (!patch)
+ cerr << "ERROR: Unable to find connection patch " << src_port_path
+ << " -> " << dst_port_path << endl;
+
+ return patch;
+}
+
+
+bool
+ClientStore::attempt_connection(const Path& src_port_path, const Path& dst_port_path, bool add_orphan)
+{
+ SharedPtr<PortModel> src_port = PtrCast<PortModel>(object(src_port_path));
+ SharedPtr<PortModel> dst_port = PtrCast<PortModel>(object(dst_port_path));
+
+ if (src_port && dst_port) {
- void add_variable_orphan(const Path& subject, const string& predicate, const Atom& value);
- void resolve_variable_orphans(SharedPtr<ObjectModel> subject);
+ assert(src_port->parent());
+ assert(dst_port->parent());
+
+ SharedPtr<PatchModel> patch = connection_patch(src_port_path, dst_port_path);
+ assert(patch);
+
+ SharedPtr<ConnectionModel> cm(new ConnectionModel(src_port, dst_port));
+
+ src_port->connected_to(dst_port);
+ dst_port->connected_to(src_port);
- // 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 string& plugin_uri, const Path& node_path, bool is_polyphonic, uint32_t num_ports);
- void new_port_event(const Path& path, uint32_t index, const string& data_type, bool is_output);
- void polyphonic_event(const Path& path, bool polyphonic);
- void patch_enabled_event(const Path& path);
- void patch_disabled_event(const Path& path);
- void patch_polyphony_event(const Path& path, uint32_t poly);
- void patch_cleared_event(const Path& path);
- void variable_change_event(const Path& subject_path, const string& predicate, const Atom& value);
- void control_change_event(const Path& port_path, float 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);
+ patch->add_connection(cm);
+
+ return true;
- bool attempt_connection(const Path& src_port_path, const Path& dst_port_path, bool add_orphan=false);
+ } else if (add_orphan) {
+
+ add_connection_orphan(make_pair(src_port_path, dst_port_path));
+
+ }
+
+ return false;
+}
+
- SharedPtr<EngineInterface> _engine;
- SharedPtr<SigClientInterface> _emitter;
+void
+ClientStore::connection_event(const Path& src_port_path, const Path& dst_port_path)
+{
+ attempt_connection(src_port_path, dst_port_path, true);
+}
- Objects _objects; ///< Map, keyed by Ingen path
- 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) */
- Raul::PathTable<list<SharedPtr<ObjectModel> > > _orphans;
+void
+ClientStore::disconnection_event(const Path& src_port_path, const Path& 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.
- /** Same idea, except with plugins instead of parents.
- * It's unfortunate everything doesn't just have a URI and this was the same.. ahem.. */
- Raul::Table<string, list<SharedPtr<NodeModel> > > _plugin_orphans;
+ SharedPtr<PortModel> src_port = PtrCast<PortModel>(object(src_port_path));
+ SharedPtr<PortModel> dst_port = PtrCast<PortModel>(object(dst_port_path));
+
+ if (src_port)
+ src_port->disconnected_from(dst_port);
+ else
+ cerr << "WARNING: Disconnection from nonexistant src port " << src_port_path << endl;
- /** Not orphans OF variable like the above, but orphans which are variable */
- Raul::PathTable<list<std::pair<string, Atom> > > _variable_orphans;
+ if (dst_port)
+ dst_port->disconnected_from(dst_port);
+ else
+ cerr << "WARNING: Disconnection from nonexistant dst port " << dst_port_path << endl;
+
+ SharedPtr<PatchModel> patch = connection_patch(src_port_path, dst_port_path);
- /** Ditto */
- list<std::pair<Path, Path> > _connection_orphans;
-};
+ if (patch)
+ patch->remove_connection(src_port_path, dst_port_path);
+ else
+ cerr << "ERROR: disconnection in nonexistant patch: "
+ << src_port_path << " -> " << dst_port_path << endl;
+}
} // namespace Client
} // namespace Ingen
-#endif // STORE_H