From 763bba9de67fb1bd06658a0bac91440727ee5a51 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 8 Oct 2007 16:30:57 +0000 Subject: SharedPtr-ify engine side store. Fix reattaching to engine. Fix connection paths. Remove last dependencies on client (model) library from Serialiser. Fix Raul::PathTable::find_descendants_end. git-svn-id: http://svn.drobilla.net/lad/ingen@847 a436a847-0d15-0410-975c-d299462d15a1 --- src/libs/client/ConnectionModel.hpp | 5 +- src/libs/client/NodeModel.hpp | 1 + src/libs/client/OSCClientReceiver.cpp | 2 +- src/libs/client/ObjectModel.cpp | 9 +- src/libs/client/ObjectModel.hpp | 12 +- src/libs/client/PatchModel.cpp | 31 +- src/libs/client/PatchModel.hpp | 26 +- src/libs/client/PortModel.hpp | 2 +- src/libs/client/Serializer.cpp | 27 +- src/libs/client/Serializer.hpp | 5 +- src/libs/client/Store.cpp | 25 +- src/libs/client/Store.hpp | 6 +- src/libs/engine/AudioDriver.hpp | 6 +- src/libs/engine/ClientBroadcaster.cpp | 4 +- src/libs/engine/ClientBroadcaster.hpp | 6 +- src/libs/engine/ConnectionImpl.cpp | 2 + src/libs/engine/ConnectionImpl.hpp | 2 +- src/libs/engine/Engine.cpp | 11 +- src/libs/engine/Engine.hpp | 2 +- src/libs/engine/GraphObjectImpl.cpp | 27 +- src/libs/engine/GraphObjectImpl.hpp | 8 +- src/libs/engine/JackAudioDriver.cpp | 2 +- src/libs/engine/JackAudioDriver.hpp | 8 +- src/libs/engine/LADSPANode.cpp | 2 +- src/libs/engine/LADSPANode.hpp | 2 +- src/libs/engine/LV2Node.cpp | 2 +- src/libs/engine/LV2Node.hpp | 2 +- src/libs/engine/Makefile.am | 4 +- src/libs/engine/MidiControlNode.cpp | 2 +- src/libs/engine/MidiControlNode.hpp | 2 +- src/libs/engine/MidiNoteNode.cpp | 4 +- src/libs/engine/MidiNoteNode.hpp | 2 +- src/libs/engine/MidiTriggerNode.cpp | 2 +- src/libs/engine/MidiTriggerNode.hpp | 2 +- src/libs/engine/NodeBase.cpp | 8 +- src/libs/engine/NodeBase.hpp | 6 +- src/libs/engine/NodeFactory.cpp | 12 +- src/libs/engine/NodeFactory.hpp | 10 +- src/libs/engine/NodeImpl.hpp | 6 +- src/libs/engine/OSCClientSender.cpp | 2 +- src/libs/engine/OSCEngineReceiver.hpp | 2 +- src/libs/engine/ObjectSender.cpp | 10 +- src/libs/engine/ObjectSender.hpp | 4 +- src/libs/engine/ObjectStore.cpp | 22 +- src/libs/engine/ObjectStore.hpp | 15 +- src/libs/engine/Patch.cpp | 445 ---------------------- src/libs/engine/Patch.hpp | 165 -------- src/libs/engine/PatchImpl.cpp | 445 ++++++++++++++++++++++ src/libs/engine/PatchImpl.hpp | 165 ++++++++ src/libs/engine/PluginImpl.cpp | 2 +- src/libs/engine/PluginImpl.hpp | 4 +- src/libs/engine/TransportNode.cpp | 2 +- src/libs/engine/TransportNode.hpp | 2 +- src/libs/engine/events/AllNotesOffEvent.cpp | 6 +- src/libs/engine/events/AllNotesOffEvent.hpp | 8 +- src/libs/engine/events/ClearPatchEvent.cpp | 4 +- src/libs/engine/events/ClearPatchEvent.hpp | 8 +- src/libs/engine/events/ConnectionEvent.cpp | 12 +- src/libs/engine/events/ConnectionEvent.hpp | 8 +- src/libs/engine/events/CreateNodeEvent.cpp | 6 +- src/libs/engine/events/CreateNodeEvent.hpp | 4 +- src/libs/engine/events/CreatePatchEvent.cpp | 8 +- src/libs/engine/events/CreatePatchEvent.hpp | 14 +- src/libs/engine/events/CreatePortEvent.cpp | 4 +- src/libs/engine/events/CreatePortEvent.hpp | 4 +- src/libs/engine/events/DestroyEvent.cpp | 24 +- src/libs/engine/events/DestroyEvent.hpp | 26 +- src/libs/engine/events/DisconnectNodeEvent.cpp | 4 +- src/libs/engine/events/DisconnectNodeEvent.hpp | 4 +- src/libs/engine/events/DisconnectPortEvent.cpp | 6 +- src/libs/engine/events/DisconnectPortEvent.hpp | 6 +- src/libs/engine/events/DisconnectionEvent.cpp | 12 +- src/libs/engine/events/DisconnectionEvent.hpp | 4 +- src/libs/engine/events/EnablePatchEvent.cpp | 2 +- src/libs/engine/events/EnablePatchEvent.hpp | 4 +- src/libs/engine/events/RenameEvent.cpp | 10 +- src/libs/engine/events/RenameEvent.hpp | 4 +- src/libs/engine/events/RequestAllObjectsEvent.cpp | 2 +- src/libs/engine/events/RequestObjectEvent.cpp | 4 +- src/libs/engine/events/SetPolyphonicEvent.cpp | 2 +- src/libs/engine/events/SetPolyphonyEvent.cpp | 4 +- src/libs/engine/events/SetPolyphonyEvent.hpp | 9 +- src/libs/gui/PatchCanvas.cpp | 11 +- 83 files changed, 921 insertions(+), 885 deletions(-) delete mode 100644 src/libs/engine/Patch.cpp delete mode 100644 src/libs/engine/Patch.hpp create mode 100644 src/libs/engine/PatchImpl.cpp create mode 100644 src/libs/engine/PatchImpl.hpp (limited to 'src/libs') diff --git a/src/libs/client/ConnectionModel.hpp b/src/libs/client/ConnectionModel.hpp index 83ddbd58..5ace402f 100644 --- a/src/libs/client/ConnectionModel.hpp +++ b/src/libs/client/ConnectionModel.hpp @@ -62,10 +62,11 @@ private: assert(_dst_port); assert(_src_port->parent()); assert(_dst_port->parent()); + assert(_src_port->path() != _dst_port->path()); } - SharedPtr _src_port; - SharedPtr _dst_port; + const SharedPtr _src_port; + const SharedPtr _dst_port; }; diff --git a/src/libs/client/NodeModel.hpp b/src/libs/client/NodeModel.hpp index a38c519c..9e26daaa 100644 --- a/src/libs/client/NodeModel.hpp +++ b/src/libs/client/NodeModel.hpp @@ -26,6 +26,7 @@ #include #include #include "interface/Node.hpp" +#include "interface/Port.hpp" #include "ObjectModel.hpp" #include "PortModel.hpp" #include "PluginModel.hpp" diff --git a/src/libs/client/OSCClientReceiver.cpp b/src/libs/client/OSCClientReceiver.cpp index b9f5a70d..0a1fa105 100644 --- a/src/libs/client/OSCClientReceiver.cpp +++ b/src/libs/client/OSCClientReceiver.cpp @@ -35,7 +35,7 @@ OSCClientReceiver::OSCClientReceiver(int listen_port) _listen_port(listen_port), _st(NULL) { - start(false); + start(true); } diff --git a/src/libs/client/ObjectModel.cpp b/src/libs/client/ObjectModel.cpp index ca38b42f..7d144faf 100644 --- a/src/libs/client/ObjectModel.cpp +++ b/src/libs/client/ObjectModel.cpp @@ -15,9 +15,10 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "ObjectModel.hpp" -#include #include +#include +#include "interface/GraphObject.hpp" +#include "ObjectModel.hpp" using namespace std; @@ -57,7 +58,7 @@ ObjectModel::children_end() const } -SharedPtr +SharedPtr ObjectModel::find_child(const string& name) const { const_iterator me = _store.objects().find(_path); @@ -65,7 +66,7 @@ ObjectModel::find_child(const string& name) const const_iterator children_end = _store.objects().find_descendants_end(me); const_iterator child = _store.objects().find(me, children_end, _path.base() + name); if (child != _store.objects().end()) - return child->second; + return PtrCast(child->second); else return SharedPtr(); } diff --git a/src/libs/client/ObjectModel.hpp b/src/libs/client/ObjectModel.hpp index ede796e4..3c13b227 100644 --- a/src/libs/client/ObjectModel.hpp +++ b/src/libs/client/ObjectModel.hpp @@ -28,10 +28,11 @@ #include #include #include -#include +#include #include "interface/GraphObject.hpp" #include "Store.hpp" +using Raul::PathTable; using std::string; using Raul::Atom; using Raul::Path; @@ -68,12 +69,9 @@ public: SharedPtr parent() const { return _parent; } bool polyphonic() const { return _polyphonic; } - typedef Store::Objects::iterator iterator; - typedef Store::Objects::const_iterator const_iterator; - - const_iterator children_begin() const; - const_iterator children_end() const; - SharedPtr find_child(const string& name) const; + const_iterator children_begin() const; + const_iterator children_end() const; + SharedPtr find_child(const string& name) const; // Signals sigc::signal > signal_new_child; diff --git a/src/libs/client/PatchModel.cpp b/src/libs/client/PatchModel.cpp index 3997ac77..a0f0aa4b 100644 --- a/src/libs/client/PatchModel.cpp +++ b/src/libs/client/PatchModel.cpp @@ -31,8 +31,6 @@ void PatchModel::add_child(SharedPtr c) { assert(c->parent().get() == this); - - //ObjectModel::add_child(c); SharedPtr pm = PtrCast(c); if (pm) { @@ -45,13 +43,6 @@ PatchModel::add_child(SharedPtr c) signal_new_node.emit(nm); } -/* -SharedPtr -PatchModel::get_node(const string& name) const -{ - return PtrCast(get_child(name)); -} -*/ bool PatchModel::remove_child(SharedPtr o) @@ -67,10 +58,11 @@ PatchModel::remove_child(SharedPtr o) // since they can't possibly exist anymore for (Connections::iterator j = _connections.begin(); j != _connections.end() ; ) { - list >::iterator next = j; + Connections::iterator next = j; ++next; - SharedPtr cm = (*j); + SharedPtr cm = PtrCast(*j); + assert(cm); if (cm->src_port_path().parent() == o->path() || cm->src_port_path() == o->path() @@ -106,9 +98,10 @@ PatchModel::clear() SharedPtr PatchModel::get_connection(const string& src_port_path, const string& dst_port_path) const { - for (list >::const_iterator i = _connections.begin(); i != _connections.end(); ++i) + for (Connections::const_iterator i = _connections.begin(); i != _connections.end(); ++i) if ((*i)->src_port_path() == src_port_path && (*i)->dst_port_path() == dst_port_path) - return (*i); + return PtrCast(*i); + return SharedPtr(); } @@ -129,18 +122,19 @@ PatchModel::add_connection(SharedPtr cm) assert(cm->dst_port()); assert(cm->src_port()->parent()); assert(cm->dst_port()->parent()); + assert(cm->src_port_path() != cm->dst_port_path()); assert(cm->src_port()->parent().get() == this || cm->src_port()->parent()->parent().get() == this); assert(cm->dst_port()->parent().get() == this || cm->dst_port()->parent()->parent().get() == this); SharedPtr existing = get_connection(cm->src_port_path(), cm->dst_port_path()); - + if (existing) { assert(cm->src_port() == existing->src_port()); assert(cm->dst_port() == existing->dst_port()); } else { - _connections.push_back(cm); + _connections.push_back(new Connections::Node(cm)); signal_new_connection.emit(cm); } } @@ -149,11 +143,12 @@ PatchModel::add_connection(SharedPtr cm) void PatchModel::remove_connection(const string& src_port_path, const string& dst_port_path) { - for (list >::iterator i = _connections.begin(); i != _connections.end(); ++i) { - SharedPtr cm = (*i); + for (Connections::iterator i = _connections.begin(); i != _connections.end(); ++i) { + SharedPtr cm = PtrCast(*i); + assert(cm); if (cm->src_port_path() == src_port_path && cm->dst_port_path() == dst_port_path) { signal_removed_connection.emit(cm); - _connections.erase(i); // cuts our reference + delete _connections.erase(i); // cuts our reference assert(!get_connection(src_port_path, dst_port_path)); // no duplicates return; } diff --git a/src/libs/client/PatchModel.hpp b/src/libs/client/PatchModel.hpp index 642bf34f..5d375faf 100644 --- a/src/libs/client/PatchModel.hpp +++ b/src/libs/client/PatchModel.hpp @@ -22,8 +22,10 @@ #include #include #include -#include "NodeModel.hpp" #include +#include "interface/Patch.hpp" +#include "NodeModel.hpp" + #include "ConnectionModel.hpp" using std::list; using std::string; @@ -38,22 +40,21 @@ class Store; * * \ingroup IngenClient */ -class PatchModel : public NodeModel +class PatchModel : public NodeModel, public Ingen::Shared::Patch { public: - typedef std::list > Connections; - const Connections& connections() const { return _connections; } - SharedPtr get_connection(const string& src_port_path, const string& dst_port_path) const; - //SharedPtr get_node(const string& node_name) const; + SharedPtr get_connection(const string& src_port_path, + const string& dst_port_path) const; void set_filename(const string& filename) { _filename = filename; } - size_t poly() const { return _poly; } - const string& filename() const { return _filename; } - bool enabled() const { return _enabled; } - bool polyphonic() const; + size_t poly() const { return _poly; } + const string& filename() const { return _filename; } + bool enabled() const { return _enabled; } + uint32_t internal_polyphony() const { return _poly; } + bool polyphonic() const; /** "editable" = arranging,connecting,adding,deleting,etc * not editable (control mode) you can just change controllers (performing) @@ -96,13 +97,10 @@ private: void add_connection(SharedPtr cm); void remove_connection(const string& src_port_path, const string& dst_port_path); - void rename_node(const Path& old_path, const Path& new_path); - void rename_node_port(const Path& old_path, const Path& new_path); - Connections _connections; string _filename; bool _enabled; - size_t _poly; + uint32_t _poly; bool _editable; }; diff --git a/src/libs/client/PortModel.hpp b/src/libs/client/PortModel.hpp index 06f04e78..5455c1f9 100644 --- a/src/libs/client/PortModel.hpp +++ b/src/libs/client/PortModel.hpp @@ -38,7 +38,7 @@ namespace Client { * * \ingroup IngenClient */ -class PortModel : public ObjectModel, public Shared::Port +class PortModel : public ObjectModel, public Ingen::Shared::Port { public: enum Direction { INPUT, OUTPUT }; diff --git a/src/libs/client/Serializer.cpp b/src/libs/client/Serializer.cpp index e37391d7..e15ce4dc 100644 --- a/src/libs/client/Serializer.cpp +++ b/src/libs/client/Serializer.cpp @@ -35,11 +35,12 @@ #include #include #include "interface/EngineInterface.hpp" +#include "interface/Plugin.hpp" +#include "interface/Patch.hpp" +#include "interface/Node.hpp" #include "interface/Port.hpp" #include "interface/Connection.hpp" -#include "PatchModel.hpp" #include "Serializer.hpp" -#include "Store.hpp" using namespace std; using namespace Raul; @@ -218,7 +219,7 @@ Serializer::serialize(SharedPtr object) throw (std::logic_error) if (!_model) throw std::logic_error("serialize called without serialization in progress"); - SharedPtr patch = PtrCast(object); + SharedPtr patch = PtrCast(object); if (patch) { serialize_patch(patch); return; @@ -230,7 +231,7 @@ Serializer::serialize(SharedPtr object) throw (std::logic_error) return; } - SharedPtr port = PtrCast(object); + SharedPtr port = PtrCast(object); if (port) { serialize_port(port.get(), path_to_node_id(port->path())); return; @@ -255,7 +256,7 @@ Serializer::patch_path_to_rdf_id(const Path& path) void -Serializer::serialize_patch(SharedPtr patch) +Serializer::serialize_patch(SharedPtr patch) { assert(_model); @@ -275,7 +276,7 @@ Serializer::serialize_patch(SharedPtr patch) _model->add_statement( patch_id, "ingen:polyphony", - Atom((int)patch->poly())); + Atom((int)patch->internal_polyphony())); _model->add_statement( patch_id, @@ -292,9 +293,9 @@ Serializer::serialize_patch(SharedPtr patch) } } - for (Store::Objects::const_iterator n = patch->children_begin(); n != patch->children_end(); ++n) { - SharedPtr patch = PtrCast(n->second); - SharedPtr node = PtrCast(n->second); + for (GraphObject::const_iterator n = patch->children_begin(); n != patch->children_end(); ++n) { + SharedPtr patch = PtrCast(n->second); + SharedPtr node = PtrCast(n->second); if (patch) { _model->add_statement(patch_id, "ingen:node", patch_path_to_rdf_id(patch->path())); serialize_patch(patch); @@ -312,7 +313,8 @@ Serializer::serialize_patch(SharedPtr patch) serialize_port(p, port_id); } - for (PatchModel::Connections::const_iterator c = patch->connections().begin(); c != patch->connections().end(); ++c) { + for (Shared::Patch::Connections::const_iterator c = patch->connections().begin(); + c != patch->connections().end(); ++c) { serialize_connection(*c); } } @@ -360,11 +362,6 @@ Serializer::serialize_node(SharedPtr node, const RDF::Node& node_i //serialize_plugin(node->plugin()); - /*_model->add_statement(_serializer, - node_uri_ref.c_str(), - "ingen:name", - Atom(node->path().name()));*/ - for (uint32_t i=0; i < node->num_ports(); ++i) { Port* p = node->port(i); assert(p); diff --git a/src/libs/client/Serializer.hpp b/src/libs/client/Serializer.hpp index 7a739f94..f8b99750 100644 --- a/src/libs/client/Serializer.hpp +++ b/src/libs/client/Serializer.hpp @@ -37,6 +37,7 @@ namespace Ingen { namespace Shared { class Plugin; class GraphObject; + class Patch; class Node; class Port; class Connection; @@ -44,8 +45,6 @@ namespace Shared { namespace Client { -class PatchModel; - /** Serializes Ingen objects (patches, nodes, etc) to RDF. * @@ -73,7 +72,7 @@ private: void serialize_plugin(SharedPtr p); - void serialize_patch(SharedPtr p); + void serialize_patch(SharedPtr p); void serialize_node(SharedPtr n, const Raul::RDF::Node& id); void serialize_port(const Shared::Port* p, const Raul::RDF::Node& id); diff --git a/src/libs/client/Store.cpp b/src/libs/client/Store.cpp index e1744ac0..ae07fa08 100644 --- a/src/libs/client/Store.cpp +++ b/src/libs/client/Store.cpp @@ -222,7 +222,7 @@ Store::add_object(SharedPtr object) // one (with precedence to the new values). Objects::iterator existing = _objects.find(object->path()); if (existing != _objects.end()) { - existing->second->set(object); + PtrCast(existing->second)->set(object); } else { if (object->path() != "/") { @@ -253,7 +253,11 @@ Store::add_object(SharedPtr object) } - //cout << "[Store] Added " << object->path() << endl; + /*cout << "[Store] Added " << object->path() << " {" << endl; + for (Objects::iterator i = _objects.begin(); i != _objects.end(); ++i) { + cout << "\t" << i->first << endl; + } + cout << "}" << endl;*/ } @@ -264,10 +268,11 @@ Store::remove_object(const Path& path) if (i != _objects.end()) { assert((*i).second->path() == path); - SharedPtr result = (*i).second; + SharedPtr result = PtrCast((*i).second); + assert(result); //_objects.erase(i); Objects::iterator descendants_end = _objects.find_descendants_end(i); - Table > removed = _objects.yank(i, descendants_end); + Table > 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; @@ -317,8 +322,10 @@ Store::object(const Path& path) if (i == _objects.end()) { return SharedPtr(); } else { - assert(i->second->path() == "/" || i->second->parent()); - return i->second; + SharedPtr model = PtrCast(i->second); + assert(model); + assert(model->path() == "/" || model->parent()); + return model; } } @@ -358,11 +365,11 @@ Store::rename_event(const Path& old_path, const Path& new_path) Objects::iterator descendants_end = _objects.find_descendants_end(parent); - Table > removed = _objects.yank(parent, descendants_end); + Table > removed = _objects.yank(parent, descendants_end); assert(removed.size() > 0); - for (Table >::iterator i = removed.begin(); i != removed.end(); ++i) { + for (Table >::iterator i = removed.begin(); i != removed.end(); ++i) { const Path& child_old_path = i->first; assert(Path::descendant_comparator(old_path, child_old_path)); @@ -373,7 +380,7 @@ Store::rename_event(const Path& old_path, const Path& new_path) child_new_path = new_path.base() + child_old_path.substr(old_path.length()+1); cerr << "[Store] Renamed " << child_old_path << " -> " << child_new_path << endl; - i->second->set_path(child_new_path); + PtrCast(i->second)->set_path(child_new_path); i->first = child_new_path; } diff --git a/src/libs/client/Store.hpp b/src/libs/client/Store.hpp index 26aac803..dad403d0 100644 --- a/src/libs/client/Store.hpp +++ b/src/libs/client/Store.hpp @@ -34,6 +34,9 @@ using Raul::Path; using Raul::Atom; namespace Ingen { + +namespace Shared { class GraphObject; } + namespace Client { class SigClientInterface; @@ -63,10 +66,11 @@ public: typedef Raul::Table > Plugins; const Plugins& plugins() const { return _plugins; } - typedef Raul::PathTable > Objects; + typedef Raul::PathTable< SharedPtr > Objects; const Objects& objects() const { return _objects; } sigc::signal > signal_new_object; + private: void add_object(SharedPtr object); diff --git a/src/libs/engine/AudioDriver.hpp b/src/libs/engine/AudioDriver.hpp index cb4c4150..6b5ea8dc 100644 --- a/src/libs/engine/AudioDriver.hpp +++ b/src/libs/engine/AudioDriver.hpp @@ -26,7 +26,7 @@ namespace Ingen { -class Patch; +class PatchImpl; class AudioDriver; class PortImpl; class ProcessContext; @@ -41,8 +41,8 @@ class AudioDriver : public Driver public: AudioDriver() : Driver(DataType::AUDIO) {} - virtual void set_root_patch(Patch* patch) = 0; - virtual Patch* root_patch() = 0; + virtual void set_root_patch(PatchImpl* patch) = 0; + virtual PatchImpl* root_patch() = 0; virtual void add_port(DriverPort* port) = 0; virtual DriverPort* remove_port(const Raul::Path& path) = 0; diff --git a/src/libs/engine/ClientBroadcaster.cpp b/src/libs/engine/ClientBroadcaster.cpp index 18025939..2360dd09 100644 --- a/src/libs/engine/ClientBroadcaster.cpp +++ b/src/libs/engine/ClientBroadcaster.cpp @@ -23,7 +23,7 @@ #include "ObjectStore.hpp" #include "NodeFactory.hpp" #include "util.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "NodeImpl.hpp" #include "PluginImpl.hpp" #include "PortImpl.hpp" @@ -256,7 +256,7 @@ ClientBroadcaster::send_program_remove(const string& node_path, int bank, int pr * Sends all objects underneath Patch - contained Nodes, etc. */ void -ClientBroadcaster::send_patch(const Patch* const p, bool recursive) +ClientBroadcaster::send_patch(const PatchImpl* p, bool recursive) { for (Clients::const_iterator i = _clients.begin(); i != _clients.end(); ++i) ObjectSender::send_patch((*i).second, p, recursive); diff --git a/src/libs/engine/ClientBroadcaster.hpp b/src/libs/engine/ClientBroadcaster.hpp index f4a97397..d7621555 100644 --- a/src/libs/engine/ClientBroadcaster.hpp +++ b/src/libs/engine/ClientBroadcaster.hpp @@ -34,7 +34,7 @@ namespace Ingen { class NodeImpl; class PortImpl; class PluginImpl; -class Patch; +class PatchImpl; class ConnectionImpl; using Shared::ClientInterface; @@ -63,8 +63,8 @@ public: void send_error(const string& msg); void send_plugins(const std::list& plugin_list); - void send_patch(const Patch* const p, bool recursive); - void send_node(const NodeImpl* const node, bool recursive); + void send_patch(const PatchImpl* p, bool recursive); + void send_node(const NodeImpl* node, bool recursive); void send_port(const PortImpl* port); void send_destroyed(const string& path); void send_polyphonic(const string& path, bool polyphonic); diff --git a/src/libs/engine/ConnectionImpl.cpp b/src/libs/engine/ConnectionImpl.cpp index 49e8f7f7..4114e7ae 100644 --- a/src/libs/engine/ConnectionImpl.cpp +++ b/src/libs/engine/ConnectionImpl.cpp @@ -47,6 +47,8 @@ ConnectionImpl::ConnectionImpl(PortImpl* src_port, PortImpl* dst_port) { assert(src_port); assert(dst_port); + assert(src_port != dst_port); + assert(src_port->path() != dst_port->path()); assert(src_port->type() == dst_port->type()); /*assert((src_port->parent_node()->poly() == dst_port->parent_node()->poly()) diff --git a/src/libs/engine/ConnectionImpl.hpp b/src/libs/engine/ConnectionImpl.hpp index 87b9f7e7..b3da1b54 100644 --- a/src/libs/engine/ConnectionImpl.hpp +++ b/src/libs/engine/ConnectionImpl.hpp @@ -52,7 +52,7 @@ public: PortImpl* dst_port() const { return _dst_port; } const Raul::Path src_port_path() const { return _src_port->path(); } - const Raul::Path dst_port_path() const { return _src_port->path(); } + const Raul::Path dst_port_path() const { return _dst_port->path(); } /** Used by some (recursive) events to prevent double disconnections */ bool pending_disconnection() { return _pending_disconnection; } diff --git a/src/libs/engine/Engine.cpp b/src/libs/engine/Engine.cpp index b5e14eb0..44cac86c 100644 --- a/src/libs/engine/Engine.cpp +++ b/src/libs/engine/Engine.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include "Engine.hpp" #include CONFIG_H_PATH #include "tuning.hpp" @@ -28,7 +29,7 @@ #include "JackAudioDriver.hpp" #include "NodeFactory.hpp" #include "ClientBroadcaster.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "ObjectStore.hpp" #include "MidiDriver.hpp" #include "OSCDriver.hpp" @@ -76,10 +77,10 @@ Engine::~Engine() { deactivate(); - for (ObjectStore::Objects::const_iterator i = _object_store->objects().begin(); + for (ObjectStore::Objects::iterator i = _object_store->objects().begin(); i != _object_store->objects().end(); ++i) { - if ( ! i->second->parent()) - delete i->second; + if ( ! PtrCast(i->second)->parent() ) + i->second.reset(); } delete _object_store; @@ -215,7 +216,7 @@ Engine::activate(size_t parallelism) // Create root patch - Patch* root_patch = new Patch(*this, "", 1, NULL, + PatchImpl* root_patch = new PatchImpl(*this, "", 1, NULL, _audio_driver->sample_rate(), _audio_driver->buffer_size(), 1); root_patch->activate(); _object_store->add(root_patch); diff --git a/src/libs/engine/Engine.hpp b/src/libs/engine/Engine.hpp index f7e82c06..355d8c4d 100644 --- a/src/libs/engine/Engine.hpp +++ b/src/libs/engine/Engine.hpp @@ -37,7 +37,7 @@ class MidiDriver; class OSCDriver; class NodeFactory; class ClientBroadcaster; -class Patch; +class PatchImpl; class ObjectStore; class EventSource; class PostProcessor; diff --git a/src/libs/engine/GraphObjectImpl.cpp b/src/libs/engine/GraphObjectImpl.cpp index d0820f61..62474bfc 100644 --- a/src/libs/engine/GraphObjectImpl.cpp +++ b/src/libs/engine/GraphObjectImpl.cpp @@ -16,16 +16,37 @@ */ #include "GraphObjectImpl.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "ObjectStore.hpp" namespace Ingen { -Patch* +PatchImpl* GraphObjectImpl::parent_patch() const { - return dynamic_cast((NodeImpl*)_parent); + return dynamic_cast((NodeImpl*)_parent); +} + + +GraphObjectImpl::const_iterator +GraphObjectImpl::children_begin() const +{ + throw; +} + + +GraphObjectImpl::const_iterator +GraphObjectImpl::children_end() const +{ + throw; +} + + +SharedPtr +GraphObjectImpl::find_child(const string& name) const +{ + throw; } diff --git a/src/libs/engine/GraphObjectImpl.hpp b/src/libs/engine/GraphObjectImpl.hpp index ccfc0319..1793366e 100644 --- a/src/libs/engine/GraphObjectImpl.hpp +++ b/src/libs/engine/GraphObjectImpl.hpp @@ -35,7 +35,7 @@ namespace Raul { class Maid; } namespace Ingen { -class Patch; +class PatchImpl; class ProcessContext; @@ -79,7 +79,7 @@ public: const MetadataMap& metadata() const { return _metadata; } /** The Patch this object is a child of. */ - virtual Patch* parent_patch() const; + virtual PatchImpl* parent_patch() const; /** Path is dynamically generated from parent to ease renaming */ const Path path() const { @@ -90,6 +90,10 @@ public: else return Path(_parent->path() +"/"+ _name); } + + const_iterator children_begin() const; + const_iterator children_end() const; + SharedPtr find_child(const string& name) const; protected: GraphObjectImpl(GraphObjectImpl* parent, const string& name, bool polyphonic=false) diff --git a/src/libs/engine/JackAudioDriver.cpp b/src/libs/engine/JackAudioDriver.cpp index a99a6112..0c824935 100644 --- a/src/libs/engine/JackAudioDriver.cpp +++ b/src/libs/engine/JackAudioDriver.cpp @@ -29,7 +29,7 @@ #include "EventSource.hpp" #include "PostProcessor.hpp" #include "NodeImpl.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "PortImpl.hpp" #include "MidiDriver.hpp" #include "DuplexPort.hpp" diff --git a/src/libs/engine/JackAudioDriver.hpp b/src/libs/engine/JackAudioDriver.hpp index ea955d05..82d07f16 100644 --- a/src/libs/engine/JackAudioDriver.hpp +++ b/src/libs/engine/JackAudioDriver.hpp @@ -30,7 +30,7 @@ namespace Ingen { class Engine; -class Patch; +class PatchImpl; class PortImpl; class DuplexPort; class JackAudioDriver; @@ -91,8 +91,8 @@ public: DriverPort* driver_port(const Raul::Path& path); - Patch* root_patch() { return _root_patch; } - void set_root_patch(Patch* patch) { _root_patch = patch; } + PatchImpl* root_patch() { return _root_patch; } + void set_root_patch(PatchImpl* patch) { _root_patch = patch; } ProcessContext& context() { return _process_context; } @@ -141,7 +141,7 @@ private: Raul::List _ports; ProcessContext _process_context; - Patch* _root_patch; + PatchImpl* _root_patch; }; diff --git a/src/libs/engine/LADSPANode.cpp b/src/libs/engine/LADSPANode.cpp index 9c2da41e..ce61eb5d 100644 --- a/src/libs/engine/LADSPANode.cpp +++ b/src/libs/engine/LADSPANode.cpp @@ -36,7 +36,7 @@ namespace Ingen { * Object is not usable until instantiate() is called with success. * (It _will_ crash!) */ -LADSPANode::LADSPANode(const PluginImpl* plugin, const string& path, bool polyphonic, Patch* parent, const LADSPA_Descriptor* descriptor, SampleRate srate, size_t buffer_size) +LADSPANode::LADSPANode(const PluginImpl* plugin, const string& path, bool polyphonic, PatchImpl* parent, const LADSPA_Descriptor* descriptor, SampleRate srate, size_t buffer_size) : NodeBase(plugin, path, polyphonic, parent, srate, buffer_size), _descriptor(descriptor), _instances(NULL) diff --git a/src/libs/engine/LADSPANode.hpp b/src/libs/engine/LADSPANode.hpp index 493645a5..8675a6fd 100644 --- a/src/libs/engine/LADSPANode.hpp +++ b/src/libs/engine/LADSPANode.hpp @@ -37,7 +37,7 @@ public: LADSPANode(const PluginImpl* plugin, const string& name, bool polyphonic, - Patch* parent, + PatchImpl* parent, const LADSPA_Descriptor* descriptor, SampleRate srate, size_t buffer_size); diff --git a/src/libs/engine/LV2Node.cpp b/src/libs/engine/LV2Node.cpp index ed330d6d..e3b6c06b 100644 --- a/src/libs/engine/LV2Node.cpp +++ b/src/libs/engine/LV2Node.cpp @@ -43,7 +43,7 @@ namespace Ingen { LV2Node::LV2Node(const PluginImpl* plugin, const string& name, bool polyphonic, - Patch* parent, + PatchImpl* parent, SampleRate srate, size_t buffer_size) : NodeBase(plugin, name, polyphonic, parent, srate, buffer_size) diff --git a/src/libs/engine/LV2Node.hpp b/src/libs/engine/LV2Node.hpp index 9e303be9..7fd9bf6d 100644 --- a/src/libs/engine/LV2Node.hpp +++ b/src/libs/engine/LV2Node.hpp @@ -37,7 +37,7 @@ public: LV2Node(const PluginImpl* plugin, const string& name, bool polyphonic, - Patch* parent, + PatchImpl* parent, SampleRate srate, size_t buffer_size); diff --git a/src/libs/engine/Makefile.am b/src/libs/engine/Makefile.am index a98a1e48..68f9739a 100644 --- a/src/libs/engine/Makefile.am +++ b/src/libs/engine/Makefile.am @@ -77,8 +77,8 @@ libingen_engine_la_SOURCES = \ ObjectStore.hpp \ OutputPort.cpp \ OutputPort.hpp \ - Patch.cpp \ - Patch.hpp \ + PatchImpl.cpp \ + PatchImpl.hpp \ PluginImpl.cpp \ PluginImpl.hpp \ PortImpl.cpp \ diff --git a/src/libs/engine/MidiControlNode.cpp b/src/libs/engine/MidiControlNode.cpp index 5bc14182..27047263 100644 --- a/src/libs/engine/MidiControlNode.cpp +++ b/src/libs/engine/MidiControlNode.cpp @@ -30,7 +30,7 @@ namespace Ingen { -MidiControlNode::MidiControlNode(const string& path, bool polyphonic, Patch* parent, SampleRate srate, size_t buffer_size) +MidiControlNode::MidiControlNode(const string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size) : NodeBase(new PluginImpl(Plugin::Internal, "ingen:control_node"), path, false, parent, srate, buffer_size), _learning(false) { diff --git a/src/libs/engine/MidiControlNode.hpp b/src/libs/engine/MidiControlNode.hpp index 0bee3db9..ab377248 100644 --- a/src/libs/engine/MidiControlNode.hpp +++ b/src/libs/engine/MidiControlNode.hpp @@ -39,7 +39,7 @@ class OutputPort; class MidiControlNode : public NodeBase { public: - MidiControlNode(const std::string& path, bool polyphonic, Patch* parent, SampleRate srate, size_t buffer_size); + MidiControlNode(const std::string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size); void process(ProcessContext& context); diff --git a/src/libs/engine/MidiNoteNode.cpp b/src/libs/engine/MidiNoteNode.cpp index 146a0978..7337ade5 100644 --- a/src/libs/engine/MidiNoteNode.cpp +++ b/src/libs/engine/MidiNoteNode.cpp @@ -27,7 +27,7 @@ #include "OutputPort.hpp" #include "PluginImpl.hpp" #include "AudioDriver.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "ProcessContext.hpp" #include "util.hpp" @@ -37,7 +37,7 @@ using std::cerr; using std::cout; using std::endl; namespace Ingen { -MidiNoteNode::MidiNoteNode(const string& path, bool polyphonic, Patch* parent, SampleRate srate, size_t buffer_size) +MidiNoteNode::MidiNoteNode(const string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size) : NodeBase(new PluginImpl(Plugin::Internal, "ingen:note_node"), path, polyphonic, parent, srate, buffer_size), _voices(new Raul::Array(_polyphony)), _prepared_voices(NULL), diff --git a/src/libs/engine/MidiNoteNode.hpp b/src/libs/engine/MidiNoteNode.hpp index 1030bec5..ee708afd 100644 --- a/src/libs/engine/MidiNoteNode.hpp +++ b/src/libs/engine/MidiNoteNode.hpp @@ -39,7 +39,7 @@ class OutputPort; class MidiNoteNode : public NodeBase { public: - MidiNoteNode(const std::string& path, bool polyphonic, Patch* parent, SampleRate srate, size_t buffer_size); + MidiNoteNode(const std::string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size); ~MidiNoteNode(); bool prepare_poly(uint32_t poly); diff --git a/src/libs/engine/MidiTriggerNode.cpp b/src/libs/engine/MidiTriggerNode.cpp index 6d7da38a..f5009a80 100644 --- a/src/libs/engine/MidiTriggerNode.cpp +++ b/src/libs/engine/MidiTriggerNode.cpp @@ -28,7 +28,7 @@ namespace Ingen { -MidiTriggerNode::MidiTriggerNode(const string& path, bool polyphonic, Patch* parent, SampleRate srate, size_t buffer_size) +MidiTriggerNode::MidiTriggerNode(const string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size) : NodeBase(new PluginImpl(Plugin::Internal, "ingen:trigger_node"), path, false, parent, srate, buffer_size) { _ports = new Raul::Array(5); diff --git a/src/libs/engine/MidiTriggerNode.hpp b/src/libs/engine/MidiTriggerNode.hpp index 46bd4c6d..308f4a9e 100644 --- a/src/libs/engine/MidiTriggerNode.hpp +++ b/src/libs/engine/MidiTriggerNode.hpp @@ -41,7 +41,7 @@ class OutputPort; class MidiTriggerNode : public NodeBase { public: - MidiTriggerNode(const std::string& path, bool polyphonic, Patch* parent, SampleRate srate, size_t buffer_size); + MidiTriggerNode(const std::string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size); void process(ProcessContext& context); diff --git a/src/libs/engine/NodeBase.cpp b/src/libs/engine/NodeBase.cpp index d5e75970..2d0adabc 100644 --- a/src/libs/engine/NodeBase.cpp +++ b/src/libs/engine/NodeBase.cpp @@ -25,7 +25,7 @@ #include "PluginImpl.hpp" #include "ClientBroadcaster.hpp" #include "PortImpl.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "ObjectStore.hpp" using namespace std; @@ -33,10 +33,10 @@ using namespace std; namespace Ingen { -NodeBase::NodeBase(const PluginImpl* plugin, const string& name, bool polyphonic, Patch* parent, SampleRate srate, size_t buffer_size) +NodeBase::NodeBase(const PluginImpl* plugin, const string& name, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size) : NodeImpl(parent, name, polyphonic), _plugin(plugin), - _polyphony((polyphonic && parent) ? parent->internal_poly() : 1), + _polyphony((polyphonic && parent) ? parent->internal_polyphony() : 1), _srate(srate), _buffer_size(buffer_size), _activated(false), @@ -50,7 +50,7 @@ NodeBase::NodeBase(const PluginImpl* plugin, const string& name, bool polyphonic { assert(_plugin); assert(_polyphony > 0); - assert(_parent == NULL || (_polyphony == parent->internal_poly() || _polyphony == 1)); + assert(_parent == NULL || (_polyphony == parent->internal_polyphony() || _polyphony == 1)); } diff --git a/src/libs/engine/NodeBase.hpp b/src/libs/engine/NodeBase.hpp index 9aa26310..5838614d 100644 --- a/src/libs/engine/NodeBase.hpp +++ b/src/libs/engine/NodeBase.hpp @@ -31,7 +31,7 @@ using std::string; namespace Ingen { class PluginImpl; -class Patch; +class PatchImpl; class ObjectStore; namespace Shared { @@ -51,7 +51,7 @@ public: NodeBase(const PluginImpl* plugin, const string& name, bool poly, - Patch* parent, + PatchImpl* parent, SampleRate rate, size_t buffer_size); @@ -103,7 +103,7 @@ public: virtual void plugin(const PluginImpl* pi) { _plugin = pi; } /** A node's parent is always a patch, so static cast should be safe */ - inline Patch* parent_patch() const { return (Patch*)_parent; } + inline PatchImpl* parent_patch() const { return (PatchImpl*)_parent; } protected: virtual void signal_input_ready(); diff --git a/src/libs/engine/NodeFactory.cpp b/src/libs/engine/NodeFactory.cpp index cef8e9a4..09d69e18 100644 --- a/src/libs/engine/NodeFactory.cpp +++ b/src/libs/engine/NodeFactory.cpp @@ -28,7 +28,7 @@ #include "MidiControlNode.hpp" #include "TransportNode.hpp" #include "PluginImpl.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #ifdef HAVE_SLV2 #include "LV2Node.hpp" #include @@ -55,7 +55,7 @@ NodeFactory::NodeFactory(Ingen::Shared::World* world) // Add builtin plugin types to _internal_plugins list // FIXME: ewwww, definitely a better way to do this! - Patch* parent = new Patch(*world->local_engine, "dummy", 1, NULL, 1, 1, 1); + PatchImpl* parent = new PatchImpl(*world->local_engine, "dummy", 1, NULL, 1, 1, 1); NodeImpl* n = NULL; n = new MidiNoteNode("foo", 1, parent, 1, 1); @@ -173,7 +173,7 @@ NodeImpl* NodeFactory::load_plugin(const PluginImpl* a_plugin, const string& name, bool polyphonic, - Patch* parent) + PatchImpl* parent) { assert(parent != NULL); assert(a_plugin); @@ -244,7 +244,7 @@ NodeImpl* NodeFactory::load_internal_plugin(const string& uri, const string& name, bool polyphonic, - Patch* parent, + PatchImpl* parent, SampleRate srate, size_t buffer_size) { @@ -319,7 +319,7 @@ NodeImpl* NodeFactory::load_lv2_plugin(const string& plug_uri, const string& node_name, bool polyphonic, - Patch* parent, + PatchImpl* parent, SampleRate srate, size_t buffer_size) { @@ -456,7 +456,7 @@ NodeImpl* NodeFactory::load_ladspa_plugin(const string& uri, const string& name, bool polyphonic, - Patch* parent, + PatchImpl* parent, SampleRate srate, size_t buffer_size) { diff --git a/src/libs/engine/NodeFactory.hpp b/src/libs/engine/NodeFactory.hpp index 47bd4993..2dacc82a 100644 --- a/src/libs/engine/NodeFactory.hpp +++ b/src/libs/engine/NodeFactory.hpp @@ -37,7 +37,7 @@ using std::string; using std::list; namespace Ingen { class NodeImpl; -class Patch; +class PatchImpl; class PluginImpl; @@ -58,7 +58,7 @@ public: ~NodeFactory(); void load_plugins(); - NodeImpl* load_plugin(const PluginImpl* info, const string& name, bool polyphonic, Patch* parent); + NodeImpl* load_plugin(const PluginImpl* info, const string& name, bool polyphonic, PatchImpl* parent); const list& plugins() { return _plugins; } @@ -68,15 +68,15 @@ public: private: #ifdef HAVE_LADSPA void load_ladspa_plugins(); - NodeImpl* load_ladspa_plugin(const string& plugin_uri, const string& name, bool polyphonic, Patch* parent, SampleRate srate, size_t buffer_size); + NodeImpl* load_ladspa_plugin(const string& plugin_uri, const string& name, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size); #endif #ifdef HAVE_SLV2 void load_lv2_plugins(); - NodeImpl* load_lv2_plugin(const string& plugin_uri, const string& name, bool polyphonic, Patch* parent, SampleRate srate, size_t buffer_size); + NodeImpl* load_lv2_plugin(const string& plugin_uri, const string& name, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size); #endif - NodeImpl* load_internal_plugin(const string& plug_label, const string& name, bool polyphonic, Patch* parent, SampleRate srate, size_t buffer_size); + NodeImpl* load_internal_plugin(const string& plug_label, const string& name, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size); Glib::Module* library(const string& path); diff --git a/src/libs/engine/NodeImpl.hpp b/src/libs/engine/NodeImpl.hpp index f139cde0..39692cc9 100644 --- a/src/libs/engine/NodeImpl.hpp +++ b/src/libs/engine/NodeImpl.hpp @@ -34,7 +34,7 @@ using namespace Shared; class Buffer; class PluginImpl; -class Patch; +class PatchImpl; class PortImpl; @@ -49,7 +49,7 @@ class PortImpl; * * \ingroup engine */ -class NodeImpl : public GraphObjectImpl, public Ingen::Shared::Node +class NodeImpl : public GraphObjectImpl, virtual public Ingen::Shared::Node { public: NodeImpl(GraphObjectImpl* parent, const std::string& name, bool poly) @@ -144,7 +144,7 @@ public: virtual void dependants(Raul::List* l) = 0; /** The Patch this Node belongs to. */ - virtual Patch* parent_patch() const = 0; + virtual PatchImpl* parent_patch() const = 0; /** Information about the Plugin this Node is an instance of. * Not the best name - not all nodes come from plugins (ie Patch) diff --git a/src/libs/engine/OSCClientSender.cpp b/src/libs/engine/OSCClientSender.cpp index 2f63621c..45c0e804 100644 --- a/src/libs/engine/OSCClientSender.cpp +++ b/src/libs/engine/OSCClientSender.cpp @@ -23,7 +23,7 @@ #include "ObjectStore.hpp" #include "NodeFactory.hpp" #include "util.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "NodeImpl.hpp" #include "PluginImpl.hpp" #include "PortImpl.hpp" diff --git a/src/libs/engine/OSCEngineReceiver.hpp b/src/libs/engine/OSCEngineReceiver.hpp index 918c15e2..bdc346d6 100644 --- a/src/libs/engine/OSCEngineReceiver.hpp +++ b/src/libs/engine/OSCEngineReceiver.hpp @@ -31,7 +31,7 @@ namespace Ingen { class JackDriver; class NodeFactory; -class Patch; +class PatchImpl; /* Some boilerplate killing macros... */ diff --git a/src/libs/engine/ObjectSender.cpp b/src/libs/engine/ObjectSender.cpp index 208e1333..87f35b2c 100644 --- a/src/libs/engine/ObjectSender.cpp +++ b/src/libs/engine/ObjectSender.cpp @@ -18,7 +18,7 @@ #include "ObjectSender.hpp" #include "interface/ClientInterface.hpp" #include "ObjectStore.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "NodeImpl.hpp" #include "PortImpl.hpp" #include "PortImpl.hpp" @@ -31,9 +31,9 @@ namespace Ingen { void -ObjectSender::send_patch(ClientInterface* client, const Patch* patch, bool recursive) +ObjectSender::send_patch(ClientInterface* client, const PatchImpl* patch, bool recursive) { - client->new_patch(patch->path(), patch->internal_poly()); + client->new_patch(patch->path(), patch->internal_polyphony()); if (recursive) { @@ -54,7 +54,7 @@ ObjectSender::send_patch(ClientInterface* client, const Patch* patch, bool recur } // Send connections - for (Patch::Connections::const_iterator j = patch->connections().begin(); + for (PatchImpl::Connections::const_iterator j = patch->connections().begin(); j != patch->connections().end(); ++j) client->connection((*j)->src_port_path(), (*j)->dst_port_path()); @@ -79,7 +79,7 @@ ObjectSender::send_node(ClientInterface* client, const NodeImpl* node, bool recu assert(node->path().length() > 0); if (plugin->type() == Plugin::Patch) { - send_patch(client, (Patch*)node, recursive); + send_patch(client, (PatchImpl*)node, recursive); return; } diff --git a/src/libs/engine/ObjectSender.hpp b/src/libs/engine/ObjectSender.hpp index e1274708..7176dcaa 100644 --- a/src/libs/engine/ObjectSender.hpp +++ b/src/libs/engine/ObjectSender.hpp @@ -26,7 +26,7 @@ namespace Shared { class ClientInterface; } using Shared::ClientInterface; -class Patch; +class PatchImpl; class NodeImpl; class PortImpl; class PluginImpl; @@ -46,7 +46,7 @@ public: // FIXME: Make all object parameters const - static void send_patch(ClientInterface* client, const Patch* patch, bool recursive); + static void send_patch(ClientInterface* client, const PatchImpl* patch, bool recursive); static void send_node(ClientInterface* client, const NodeImpl* node, bool recursive); static void send_port(ClientInterface* client, const PortImpl* port); }; diff --git a/src/libs/engine/ObjectStore.cpp b/src/libs/engine/ObjectStore.cpp index 719770ed..7b9f29fe 100644 --- a/src/libs/engine/ObjectStore.cpp +++ b/src/libs/engine/ObjectStore.cpp @@ -21,7 +21,7 @@ #include #include #include "ObjectStore.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "NodeImpl.hpp" #include "PortImpl.hpp" #include "ThreadManager.hpp" @@ -34,11 +34,11 @@ namespace Ingen { /** Find the Patch at the given path. */ -Patch* +PatchImpl* ObjectStore::find_patch(const Path& path) { GraphObjectImpl* const object = find_object(path); - return dynamic_cast(object); + return dynamic_cast(object); } @@ -68,7 +68,7 @@ GraphObjectImpl* ObjectStore::find_object(const Path& path) { Objects::iterator i = _objects.find(path); - return ((i == _objects.end()) ? NULL : i->second); + return ((i == _objects.end()) ? NULL : dynamic_cast(i->second.get())); } @@ -94,7 +94,7 @@ ObjectStore::add(GraphObjectImpl* o) /** Add a family of objects to the store. Not realtime safe. */ void -ObjectStore::add(const Table& table) +ObjectStore::add(const Table >& table) { assert(ThreadManager::current_thread_id() == THREAD_PRE_PROCESS); @@ -102,7 +102,7 @@ ObjectStore::add(const Table& table) _objects.cram(table); cerr << "[ObjectStore] Adding Table:" << endl; - for (Table::const_iterator i = table.begin(); i != table.end(); ++i) { + for (Objects::const_iterator i = table.begin(); i != table.end(); ++i) { cerr << i->first << " = " << i->second->path() << endl; } } @@ -113,7 +113,7 @@ ObjectStore::add(const Table& table) * Returned is a vector containing all descendants of the object removed * including the object itself, in lexicographically sorted order by Path. */ -Table +Table > ObjectStore::remove(const Path& path) { return remove(_objects.find(path)); @@ -125,7 +125,7 @@ ObjectStore::remove(const Path& path) * Returned is a vector containing all descendants of the object removed * including the object itself, in lexicographically sorted order by Path. */ -Table +Table > ObjectStore::remove(Objects::iterator object) { assert(ThreadManager::current_thread_id() == THREAD_PRE_PROCESS); @@ -133,8 +133,8 @@ ObjectStore::remove(Objects::iterator object) if (object != _objects.end()) { Objects::iterator descendants_end = _objects.find_descendants_end(object); cout << "[ObjectStore] Removing " << object->first << " {" << endl; - Table removed = _objects.yank(object, descendants_end); - for (Table::iterator i = removed.begin(); i != removed.end(); ++i) { + Table > removed = _objects.yank(object, descendants_end); + for (Objects::iterator i = removed.begin(); i != removed.end(); ++i) { cout << "\t" << i->first << endl; } cout << "}" << endl; @@ -143,7 +143,7 @@ ObjectStore::remove(Objects::iterator object) } else { cerr << "[ObjectStore] WARNING: Removing " << object->first << " failed." << endl; - return Table(); + return Objects(); } } diff --git a/src/libs/engine/ObjectStore.hpp b/src/libs/engine/ObjectStore.hpp index 66d182ba..cc83d85a 100644 --- a/src/libs/engine/ObjectStore.hpp +++ b/src/libs/engine/ObjectStore.hpp @@ -20,13 +20,16 @@ #include #include +#include using std::string; using namespace Raul; namespace Ingen { -class Patch; +namespace Shared { class GraphObject; } + +class PatchImpl; class NodeImpl; class PortImpl; class GraphObjectImpl; @@ -44,9 +47,9 @@ class GraphObjectImpl; class ObjectStore { public: - typedef Raul::PathTable Objects; + typedef Raul::PathTable< SharedPtr > Objects; - Patch* find_patch(const Path& path); + PatchImpl* find_patch(const Path& path); NodeImpl* find_node(const Path& path); PortImpl* find_port(const Path& path); GraphObjectImpl* find_object(const Path& path); @@ -54,11 +57,11 @@ public: Objects::iterator find(const Path& path) { return _objects.find(path); } void add(GraphObjectImpl* o); - void add(const Table& family); + void add(const Table >& family); //void add(TreeNode* o); - Table remove(const Path& path); - Table remove(Objects::iterator i); + Table > remove(const Path& path); + Table > remove(Objects::iterator i); const Objects& objects() const { return _objects; } Objects& objects() { return _objects; } diff --git a/src/libs/engine/Patch.cpp b/src/libs/engine/Patch.cpp deleted file mode 100644 index 8256f0c5..00000000 --- a/src/libs/engine/Patch.cpp +++ /dev/null @@ -1,445 +0,0 @@ -/* This file is part of Ingen. - * Copyright (C) 2007 Dave Robillard - * - * 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 -#include -#include -#include "ThreadManager.hpp" -#include "NodeImpl.hpp" -#include "Patch.hpp" -#include "PluginImpl.hpp" -#include "PortImpl.hpp" -#include "ConnectionImpl.hpp" -#include "DuplexPort.hpp" -#include "Engine.hpp" -#include "ProcessSlave.hpp" - -using namespace std; - -namespace Ingen { - - -Patch::Patch(Engine& engine, const string& path, uint32_t poly, Patch* parent, SampleRate srate, size_t buffer_size, uint32_t internal_poly) -: NodeBase(new PluginImpl(Plugin::Patch, "ingen:patch"), path, poly, parent, srate, buffer_size), - _engine(engine), - _internal_poly(internal_poly), - _compiled_patch(NULL), - _process(false) -{ - assert(internal_poly >= 1); - - //_plugin->plug_label("om_patch"); - //_plugin->name("Ingen Patch"); - - //std::cerr << "Creating patch " << _name << ", poly = " << poly - // << ", internal poly = " << internal_poly << std::endl; -} - - -Patch::~Patch() -{ - assert(!_activated); - - for (Connections::iterator i = _connections.begin(); i != _connections.end(); ++i) { - (*i).reset(); - delete _connections.erase(i); - } - - for (List::iterator i = _nodes.begin(); i != _nodes.end(); ++i) { - assert(!(*i)->activated()); - delete (*i); - delete _nodes.erase(i); - } - - delete _compiled_patch; -} - - -void -Patch::activate() -{ - NodeBase::activate(); - - for (List::iterator i = _nodes.begin(); i != _nodes.end(); ++i) - (*i)->activate(); - - assert(_activated); -} - - -void -Patch::deactivate() -{ - if (_activated) { - - NodeBase::deactivate(); - - for (List::iterator i = _nodes.begin(); i != _nodes.end(); ++i) { - if ((*i)->activated()) - (*i)->deactivate(); - assert(!(*i)->activated()); - } - } - assert(!_activated); -} - - -void -Patch::disable() -{ - _process = false; - - for (List::iterator i = _output_ports.begin(); i != _output_ports.end(); ++i) - (*i)->clear_buffers(); -} - - -bool -Patch::prepare_internal_poly(uint32_t poly) -{ - /* TODO: ports? internal/external poly? */ - - for (List::iterator i = _nodes.begin(); i != _nodes.end(); ++i) - (*i)->prepare_poly(poly); - - for (Connections::iterator i = _connections.begin(); i != _connections.end(); ++i) - ((ConnectionImpl*)i->get())->prepare_poly(poly); - - /* FIXME: Deal with failure */ - - return true; -} - - -bool -Patch::apply_internal_poly(Raul::Maid& maid, uint32_t poly) -{ - /* TODO: ports? internal/external poly? */ - - for (List::iterator i = _nodes.begin(); i != _nodes.end(); ++i) - (*i)->apply_poly(maid, poly); - - for (Connections::iterator i = _connections.begin(); i != _connections.end(); ++i) - PtrCast(*i)->apply_poly(maid, poly); - - _internal_poly = poly; - - return true; -} - - -/** Run the patch for the specified number of frames. - * - * Calls all Nodes in (roughly, if parallel) the order _compiled_patch specifies. - */ -void -Patch::process(ProcessContext& context) -{ - if (_compiled_patch == NULL || _compiled_patch->size() == 0 || !_process) - return; - - NodeBase::pre_process(context); - - /* Run */ - if (_engine.process_slaves().size() > 0) - process_parallel(context); - else - process_single(context); - - NodeBase::post_process(context); -} - - -void -Patch::process_parallel(ProcessContext& context) -{ - size_t n_slaves = _engine.process_slaves().size(); - - CompiledPatch* const cp = _compiled_patch; - - /* Start p-1 slaves */ - - if (n_slaves >= cp->size()) - n_slaves = cp->size()-1; - - if (n_slaves > 0) { - for (size_t i=0; i < cp->size(); ++i) - (*cp)[i].node()->reset_input_ready(); - - for (size_t i=0; i < n_slaves; ++i) - _engine.process_slaves()[i]->whip(cp, i+1, context); - } - - - /* Process ourself until everything is done - * This is analogous to ProcessSlave::_whipped(), but this is the master - * (i.e. what the main Jack process thread calls). Where ProcessSlave - * waits on input, this just skips the node and tries the next, to avoid - * waiting in the Jack thread which pisses Jack off. - */ - - size_t index = 0; - size_t num_finished = 0; // Number of consecutive finished nodes hit - - while (num_finished < cp->size()) { - - CompiledNode& n = (*cp)[index]; - - if (n.node()->process_lock()) { - if (n.node()->n_inputs_ready() == n.n_providers()) { - n.node()->process(context); - - /* Signal dependants their input is ready */ - for (size_t i=0; i < n.dependants().size(); ++i) - n.dependants()[i]->signal_input_ready(); - - ++num_finished; - } else { - n.node()->process_unlock(); - num_finished = 0; - } - } else { - if (n.node()->n_inputs_ready() == n.n_providers()) - ++num_finished; - else - num_finished = 0; - } - - index = (index + 1) % cp->size(); - } - - /* Tell slaves we're done in case we beat them, and pray they're - * really done by the start of next cycle. - * FIXME: This probably breaks (race) at extremely small nframes where - * ingen is the majority of the DSP load. - */ - for (size_t i=0; i < n_slaves; ++i) - _engine.process_slaves()[i]->finish(); -} - - -void -Patch::process_single(ProcessContext& context) -{ - CompiledPatch* const cp = _compiled_patch; - - for (size_t i=0; i < cp->size(); ++i) - (*cp)[i].node()->process(context); -} - - -void -Patch::set_buffer_size(size_t size) -{ - NodeBase::set_buffer_size(size); - assert(_buffer_size == size); - - for (List::iterator j = _nodes.begin(); j != _nodes.end(); ++j) - (*j)->set_buffer_size(size); -} - - -// Patch specific stuff - - -void -Patch::add_node(List::Node* ln) -{ - assert(ln != NULL); - assert(ln->elem() != NULL); - assert(ln->elem()->parent_patch() == this); - //assert(ln->elem()->polyphony() == _internal_poly); - - _nodes.push_back(ln); -} - - -/** Remove a node. - * Realtime Safe. Preprocessing thread. - */ -Patch::Nodes::Node* -Patch::remove_node(const string& name) -{ - for (List::iterator i = _nodes.begin(); i != _nodes.end(); ++i) - if ((*i)->name() == name) - return _nodes.erase(i); - - return NULL; -} - - -/** Remove a connection. Realtime safe. - */ -Patch::Connections::Node* -Patch::remove_connection(const PortImpl* src_port, const PortImpl* dst_port) -{ - bool found = false; - Connections::Node* connection = NULL; - for (Connections::iterator i = _connections.begin(); i != _connections.end(); ++i) { - ConnectionImpl* const c = (ConnectionImpl*)i->get(); - if (c->src_port() == src_port && c->dst_port() == dst_port) { - connection = _connections.erase(i); - found = true; - break; - } - } - - if ( ! found) - cerr << "WARNING: [Patch::remove_connection] Connection not found !" << endl; - - return connection; -} - - -uint32_t -Patch::num_ports() const -{ - ThreadID context = ThreadManager::current_thread_id(); - - if (context == THREAD_PROCESS) - return NodeBase::num_ports(); - else - return _input_ports.size() + _output_ports.size(); -} - - -/** Create a port. Not realtime safe. - */ -PortImpl* -Patch::create_port(const string& name, DataType type, size_t buffer_size, bool is_output) -{ - if (type == DataType::UNKNOWN) { - cerr << "[Patch::create_port] Unknown port type " << type.uri() << endl; - return NULL; - } - - assert( !(type == DataType::UNKNOWN) ); - - return new DuplexPort(this, name, 0, _polyphony, type, buffer_size, is_output); -} - - -/** Remove port from ports list used in pre-processing thread. - * - * Port is not removed from ports array for process thread (which could be - * simultaneously running). - * - * Realtime safe. Preprocessing thread only. - */ -List::Node* -Patch::remove_port(const string& name) -{ - assert(ThreadManager::current_thread_id() == THREAD_PRE_PROCESS); - - bool found = false; - List::Node* ret = NULL; - for (List::iterator i = _input_ports.begin(); i != _input_ports.end(); ++i) { - if ((*i)->name() == name) { - ret = _input_ports.erase(i); - found = true; - } - } - - if (!found) - for (List::iterator i = _output_ports.begin(); i != _output_ports.end(); ++i) { - if ((*i)->name() == name) { - ret = _output_ports.erase(i); - found = true; - } - } - - if ( ! found) - cerr << "WARNING: [Patch::remove_port] Port not found !" << endl; - - return ret; -} - - -Raul::Array* -Patch::build_ports_array() const -{ - assert(ThreadManager::current_thread_id() == THREAD_PRE_PROCESS); - - Raul::Array* const result = new Raul::Array(_input_ports.size() + _output_ports.size()); - - size_t i = 0; - - for (List::const_iterator p = _input_ports.begin(); p != _input_ports.end(); ++p,++i) - result->at(i) = *p; - - for (List::const_iterator p = _output_ports.begin(); p != _output_ports.end(); ++p,++i) - result->at(i) = *p; - - return result; -} - - -/** Find the process order for this Patch. - * - * The process order is a flat list that the patch will execute in order - * when it's run() method is called. Return value is a newly allocated list - * which the caller is reponsible to delete. Note that this function does - * NOT actually set the process order, it is returned so it can be inserted - * at the beginning of an audio cycle (by various Events). - * - * Not realtime safe. - */ -CompiledPatch* -Patch::compile() const -{ - assert(ThreadManager::current_thread_id() == THREAD_PRE_PROCESS); - - //cerr << "*********** Building process order for " << path() << endl; - - CompiledPatch* const compiled_patch = new CompiledPatch();//_nodes.size()); - - for (Nodes::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i) - (*i)->traversed(false); - - for (Nodes::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i) { - NodeImpl* const node = (*i); - // Either a sink or connected to our output ports: - if ( ( ! node->traversed()) && node->dependants()->size() == 0) - compile_recursive(node, compiled_patch); - } - - // Traverse any nodes we didn't hit yet - for (Nodes::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i) { - NodeImpl* const node = (*i); - if ( ! node->traversed()) - compile_recursive(node, compiled_patch); - } - - /*cerr << "----------------------------------------\n"; - for (size_t i=0; i < process_order->size(); ++i) { - assert(process_order->at(i)); - cerr << process_order->at(i)->path() << endl; - } - cerr << "----------------------------------------\n";*/ - - assert(compiled_patch->size() == _nodes.size()); - -#ifndef NDEBUG - for (size_t i=0; i < compiled_patch->size(); ++i) - assert(compiled_patch->at(i).node()); -#endif - - return compiled_patch; -} - - -} // namespace Ingen diff --git a/src/libs/engine/Patch.hpp b/src/libs/engine/Patch.hpp deleted file mode 100644 index 8b9f9ad7..00000000 --- a/src/libs/engine/Patch.hpp +++ /dev/null @@ -1,165 +0,0 @@ -/* This file is part of Ingen. - * Copyright (C) 2007 Dave Robillard - * - * 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 PATCH_H -#define PATCH_H - -#include -#include -#include -#include -#include "NodeBase.hpp" -#include "PluginImpl.hpp" -#include "interface/DataType.hpp" -#include "CompiledPatch.hpp" - -using std::string; - -template class Array; -using Raul::List; - -namespace Ingen { - -namespace Shared { class Connection; } - -class ConnectionImpl; -class Engine; -class CompiledPatch; - - -/** A group of nodes in a graph, possibly polyphonic. - * - * Note that this is also a Node, just one which contains Nodes. - * Therefore infinite subpatching is possible, of polyphonic - * patches of polyphonic nodes etc. etc. - * - * \ingroup engine - */ -class Patch : public NodeBase -{ -public: - Patch(Engine& engine, - const string& name, - uint32_t poly, - Patch* parent, - SampleRate srate, - size_t buffer_size, - uint32_t local_poly); - - virtual ~Patch(); - - void activate(); - void deactivate(); - - void process(ProcessContext& context); - - void set_buffer_size(size_t size); - - /** Prepare for a new (internal) polyphony value. - * - * Preprocessor thread, poly is actually applied by apply_internal_poly. - * \return true on success. - */ - bool prepare_internal_poly(uint32_t poly); - - /** Apply a new (internal) polyphony value. - * - * Audio thread. - * - * \param poly Must be < the most recent value passed to prepare_internal_poly. - * \param maid Any objects no longer needed will be pushed to this - */ - bool apply_internal_poly(Raul::Maid& maid, uint32_t poly); - - // Patch specific stuff not inherited from Node - - typedef List< SharedPtr > Connections; - typedef List Nodes; - - void add_node(Nodes::Node* tn); - Nodes::Node* remove_node(const string& name); - - Nodes& nodes() { return _nodes; } - Connections& connections() { return _connections; } - - const Nodes& nodes() const { return _nodes; } - const Connections& connections() const { return _connections; } - - uint32_t num_ports() const; - - PortImpl* create_port(const string& name, DataType type, size_t buffer_size, bool is_output); - void add_input(List::Node* port) { _input_ports.push_back(port); } ///< Preprocesser thread - void add_output(List::Node* port) { _output_ports.push_back(port); } ///< Preprocessor thread - List::Node* remove_port(const string& name); - - void add_connection(Connections::Node* c) { _connections.push_back(c); } - Connections::Node* remove_connection(const PortImpl* src_port, const PortImpl* dst_port); - - CompiledPatch* compiled_patch() { return _compiled_patch; } - void compiled_patch(CompiledPatch* cp) { _compiled_patch = cp; } - - Raul::Array* external_ports() { return _ports; } - void external_ports(Raul::Array* pa) { _ports = pa; } - - CompiledPatch* compile() const; - Raul::Array* build_ports_array() const; - - /** Whether to run this patch's DSP bits in the audio thread */ - bool enabled() const { return _process; } - void enable() { _process = true; } - void disable(); - - uint32_t internal_poly() const { return _internal_poly; } - -private: - inline void compile_recursive(NodeImpl* n, CompiledPatch* output) const; - void process_parallel(ProcessContext& context); - void process_single(ProcessContext& context); - - Engine& _engine; - uint32_t _internal_poly; - CompiledPatch* _compiled_patch; ///< Accessed in audio thread only - Connections _connections; ///< Accessed in audio thread only - List _input_ports; ///< Accessed in preprocessing thread only - List _output_ports; ///< Accessed in preprocessing thread only - Nodes _nodes; ///< Accessed in preprocessing thread only - bool _process; -}; - - - -/** Private helper for compile */ -inline void -Patch::compile_recursive(NodeImpl* n, CompiledPatch* output) const -{ - if (n == NULL || n->traversed()) - return; - - n->traversed(true); - assert(output != NULL); - - for (List::iterator i = n->providers()->begin(); i != n->providers()->end(); ++i) - if ( ! (*i)->traversed() ) - compile_recursive((*i), output); - - output->push_back(CompiledNode(n, n->providers()->size(), n->dependants())); -} - - -} // namespace Ingen - -#endif // PATCH_H diff --git a/src/libs/engine/PatchImpl.cpp b/src/libs/engine/PatchImpl.cpp new file mode 100644 index 00000000..3e4c78c7 --- /dev/null +++ b/src/libs/engine/PatchImpl.cpp @@ -0,0 +1,445 @@ +/* This file is part of Ingen. + * Copyright (C) 2007 Dave Robillard + * + * 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 +#include +#include +#include "ThreadManager.hpp" +#include "NodeImpl.hpp" +#include "PatchImpl.hpp" +#include "PluginImpl.hpp" +#include "PortImpl.hpp" +#include "ConnectionImpl.hpp" +#include "DuplexPort.hpp" +#include "Engine.hpp" +#include "ProcessSlave.hpp" + +using namespace std; + +namespace Ingen { + + +PatchImpl::PatchImpl(Engine& engine, const string& path, uint32_t poly, PatchImpl* parent, SampleRate srate, size_t buffer_size, uint32_t internal_poly) +: NodeBase(new PluginImpl(Plugin::Patch, "ingen:patch"), path, poly, parent, srate, buffer_size), + _engine(engine), + _internal_poly(internal_poly), + _compiled_patch(NULL), + _process(false) +{ + assert(internal_poly >= 1); + + //_plugin->plug_label("om_patch"); + //_plugin->name("Ingen Patch"); + + //std::cerr << "Creating patch " << _name << ", poly = " << poly + // << ", internal poly = " << internal_poly << std::endl; +} + + +PatchImpl::~PatchImpl() +{ + assert(!_activated); + + for (Connections::iterator i = _connections.begin(); i != _connections.end(); ++i) { + (*i).reset(); + delete _connections.erase(i); + } + + for (List::iterator i = _nodes.begin(); i != _nodes.end(); ++i) { + assert(!(*i)->activated()); + delete (*i); + delete _nodes.erase(i); + } + + delete _compiled_patch; +} + + +void +PatchImpl::activate() +{ + NodeBase::activate(); + + for (List::iterator i = _nodes.begin(); i != _nodes.end(); ++i) + (*i)->activate(); + + assert(_activated); +} + + +void +PatchImpl::deactivate() +{ + if (_activated) { + + NodeBase::deactivate(); + + for (List::iterator i = _nodes.begin(); i != _nodes.end(); ++i) { + if ((*i)->activated()) + (*i)->deactivate(); + assert(!(*i)->activated()); + } + } + assert(!_activated); +} + + +void +PatchImpl::disable() +{ + _process = false; + + for (List::iterator i = _output_ports.begin(); i != _output_ports.end(); ++i) + (*i)->clear_buffers(); +} + + +bool +PatchImpl::prepare_internal_poly(uint32_t poly) +{ + /* TODO: ports? internal/external poly? */ + + for (List::iterator i = _nodes.begin(); i != _nodes.end(); ++i) + (*i)->prepare_poly(poly); + + for (Connections::iterator i = _connections.begin(); i != _connections.end(); ++i) + ((ConnectionImpl*)i->get())->prepare_poly(poly); + + /* FIXME: Deal with failure */ + + return true; +} + + +bool +PatchImpl::apply_internal_poly(Raul::Maid& maid, uint32_t poly) +{ + /* TODO: ports? internal/external poly? */ + + for (List::iterator i = _nodes.begin(); i != _nodes.end(); ++i) + (*i)->apply_poly(maid, poly); + + for (Connections::iterator i = _connections.begin(); i != _connections.end(); ++i) + PtrCast(*i)->apply_poly(maid, poly); + + _internal_poly = poly; + + return true; +} + + +/** Run the patch for the specified number of frames. + * + * Calls all Nodes in (roughly, if parallel) the order _compiled_patch specifies. + */ +void +PatchImpl::process(ProcessContext& context) +{ + if (_compiled_patch == NULL || _compiled_patch->size() == 0 || !_process) + return; + + NodeBase::pre_process(context); + + /* Run */ + if (_engine.process_slaves().size() > 0) + process_parallel(context); + else + process_single(context); + + NodeBase::post_process(context); +} + + +void +PatchImpl::process_parallel(ProcessContext& context) +{ + size_t n_slaves = _engine.process_slaves().size(); + + CompiledPatch* const cp = _compiled_patch; + + /* Start p-1 slaves */ + + if (n_slaves >= cp->size()) + n_slaves = cp->size()-1; + + if (n_slaves > 0) { + for (size_t i=0; i < cp->size(); ++i) + (*cp)[i].node()->reset_input_ready(); + + for (size_t i=0; i < n_slaves; ++i) + _engine.process_slaves()[i]->whip(cp, i+1, context); + } + + + /* Process ourself until everything is done + * This is analogous to ProcessSlave::_whipped(), but this is the master + * (i.e. what the main Jack process thread calls). Where ProcessSlave + * waits on input, this just skips the node and tries the next, to avoid + * waiting in the Jack thread which pisses Jack off. + */ + + size_t index = 0; + size_t num_finished = 0; // Number of consecutive finished nodes hit + + while (num_finished < cp->size()) { + + CompiledNode& n = (*cp)[index]; + + if (n.node()->process_lock()) { + if (n.node()->n_inputs_ready() == n.n_providers()) { + n.node()->process(context); + + /* Signal dependants their input is ready */ + for (size_t i=0; i < n.dependants().size(); ++i) + n.dependants()[i]->signal_input_ready(); + + ++num_finished; + } else { + n.node()->process_unlock(); + num_finished = 0; + } + } else { + if (n.node()->n_inputs_ready() == n.n_providers()) + ++num_finished; + else + num_finished = 0; + } + + index = (index + 1) % cp->size(); + } + + /* Tell slaves we're done in case we beat them, and pray they're + * really done by the start of next cycle. + * FIXME: This probably breaks (race) at extremely small nframes where + * ingen is the majority of the DSP load. + */ + for (size_t i=0; i < n_slaves; ++i) + _engine.process_slaves()[i]->finish(); +} + + +void +PatchImpl::process_single(ProcessContext& context) +{ + CompiledPatch* const cp = _compiled_patch; + + for (size_t i=0; i < cp->size(); ++i) + (*cp)[i].node()->process(context); +} + + +void +PatchImpl::set_buffer_size(size_t size) +{ + NodeBase::set_buffer_size(size); + assert(_buffer_size == size); + + for (List::iterator j = _nodes.begin(); j != _nodes.end(); ++j) + (*j)->set_buffer_size(size); +} + + +// Patch specific stuff + + +void +PatchImpl::add_node(List::Node* ln) +{ + assert(ln != NULL); + assert(ln->elem() != NULL); + assert(ln->elem()->parent_patch() == this); + //assert(ln->elem()->polyphony() == _internal_poly); + + _nodes.push_back(ln); +} + + +/** Remove a node. + * Realtime Safe. Preprocessing thread. + */ +PatchImpl::Nodes::Node* +PatchImpl::remove_node(const string& name) +{ + for (List::iterator i = _nodes.begin(); i != _nodes.end(); ++i) + if ((*i)->name() == name) + return _nodes.erase(i); + + return NULL; +} + + +/** Remove a connection. Realtime safe. + */ +PatchImpl::Connections::Node* +PatchImpl::remove_connection(const PortImpl* src_port, const PortImpl* dst_port) +{ + bool found = false; + Connections::Node* connection = NULL; + for (Connections::iterator i = _connections.begin(); i != _connections.end(); ++i) { + ConnectionImpl* const c = (ConnectionImpl*)i->get(); + if (c->src_port() == src_port && c->dst_port() == dst_port) { + connection = _connections.erase(i); + found = true; + break; + } + } + + if ( ! found) + cerr << "WARNING: [PatchImpl::remove_connection] Connection not found !" << endl; + + return connection; +} + + +uint32_t +PatchImpl::num_ports() const +{ + ThreadID context = ThreadManager::current_thread_id(); + + if (context == THREAD_PROCESS) + return NodeBase::num_ports(); + else + return _input_ports.size() + _output_ports.size(); +} + + +/** Create a port. Not realtime safe. + */ +PortImpl* +PatchImpl::create_port(const string& name, DataType type, size_t buffer_size, bool is_output) +{ + if (type == DataType::UNKNOWN) { + cerr << "[PatchImpl::create_port] Unknown port type " << type.uri() << endl; + return NULL; + } + + assert( !(type == DataType::UNKNOWN) ); + + return new DuplexPort(this, name, 0, _polyphony, type, buffer_size, is_output); +} + + +/** Remove port from ports list used in pre-processing thread. + * + * Port is not removed from ports array for process thread (which could be + * simultaneously running). + * + * Realtime safe. Preprocessing thread only. + */ +List::Node* +PatchImpl::remove_port(const string& name) +{ + assert(ThreadManager::current_thread_id() == THREAD_PRE_PROCESS); + + bool found = false; + List::Node* ret = NULL; + for (List::iterator i = _input_ports.begin(); i != _input_ports.end(); ++i) { + if ((*i)->name() == name) { + ret = _input_ports.erase(i); + found = true; + } + } + + if (!found) + for (List::iterator i = _output_ports.begin(); i != _output_ports.end(); ++i) { + if ((*i)->name() == name) { + ret = _output_ports.erase(i); + found = true; + } + } + + if ( ! found) + cerr << "WARNING: [PatchImpl::remove_port] Port not found !" << endl; + + return ret; +} + + +Raul::Array* +PatchImpl::build_ports_array() const +{ + assert(ThreadManager::current_thread_id() == THREAD_PRE_PROCESS); + + Raul::Array* const result = new Raul::Array(_input_ports.size() + _output_ports.size()); + + size_t i = 0; + + for (List::const_iterator p = _input_ports.begin(); p != _input_ports.end(); ++p,++i) + result->at(i) = *p; + + for (List::const_iterator p = _output_ports.begin(); p != _output_ports.end(); ++p,++i) + result->at(i) = *p; + + return result; +} + + +/** Find the process order for this Patch. + * + * The process order is a flat list that the patch will execute in order + * when it's run() method is called. Return value is a newly allocated list + * which the caller is reponsible to delete. Note that this function does + * NOT actually set the process order, it is returned so it can be inserted + * at the beginning of an audio cycle (by various Events). + * + * Not realtime safe. + */ +CompiledPatch* +PatchImpl::compile() const +{ + assert(ThreadManager::current_thread_id() == THREAD_PRE_PROCESS); + + //cerr << "*********** Building process order for " << path() << endl; + + CompiledPatch* const compiled_patch = new CompiledPatch();//_nodes.size()); + + for (Nodes::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i) + (*i)->traversed(false); + + for (Nodes::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i) { + NodeImpl* const node = (*i); + // Either a sink or connected to our output ports: + if ( ( ! node->traversed()) && node->dependants()->size() == 0) + compile_recursive(node, compiled_patch); + } + + // Traverse any nodes we didn't hit yet + for (Nodes::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i) { + NodeImpl* const node = (*i); + if ( ! node->traversed()) + compile_recursive(node, compiled_patch); + } + + /*cerr << "----------------------------------------\n"; + for (size_t i=0; i < process_order->size(); ++i) { + assert(process_order->at(i)); + cerr << process_order->at(i)->path() << endl; + } + cerr << "----------------------------------------\n";*/ + + assert(compiled_patch->size() == _nodes.size()); + +#ifndef NDEBUG + for (size_t i=0; i < compiled_patch->size(); ++i) + assert(compiled_patch->at(i).node()); +#endif + + return compiled_patch; +} + + +} // namespace Ingen diff --git a/src/libs/engine/PatchImpl.hpp b/src/libs/engine/PatchImpl.hpp new file mode 100644 index 00000000..94a9ebf3 --- /dev/null +++ b/src/libs/engine/PatchImpl.hpp @@ -0,0 +1,165 @@ +/* This file is part of Ingen. + * Copyright (C) 2007 Dave Robillard + * + * 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 PATCHIMPL_H +#define PATCHIMPL_H + +#include +#include +#include +#include +#include "interface/DataType.hpp" +#include "interface/Patch.hpp" +#include "NodeBase.hpp" +#include "PluginImpl.hpp" +#include "CompiledPatch.hpp" + +using std::string; + +template class Array; +using Raul::List; + +namespace Ingen { + +namespace Shared { class Connection; } + +class ConnectionImpl; +class Engine; +class CompiledPatch; + + +/** A group of nodes in a graph, possibly polyphonic. + * + * Note that this is also a Node, just one which contains Nodes. + * Therefore infinite subpatching is possible, of polyphonic + * patches of polyphonic nodes etc. etc. + * + * \ingroup engine + */ +class PatchImpl : public NodeBase, public Ingen::Shared::Patch +{ +public: + PatchImpl(Engine& engine, + const string& name, + uint32_t poly, + PatchImpl* parent, + SampleRate srate, + size_t buffer_size, + uint32_t local_poly); + + virtual ~PatchImpl(); + + void activate(); + void deactivate(); + + void process(ProcessContext& context); + + void set_buffer_size(size_t size); + + /** Prepare for a new (internal) polyphony value. + * + * Preprocessor thread, poly is actually applied by apply_internal_poly. + * \return true on success. + */ + bool prepare_internal_poly(uint32_t poly); + + /** Apply a new (internal) polyphony value. + * + * Audio thread. + * + * \param poly Must be < the most recent value passed to prepare_internal_poly. + * \param maid Any objects no longer needed will be pushed to this + */ + bool apply_internal_poly(Raul::Maid& maid, uint32_t poly); + + // Patch specific stuff not inherited from Node + + typedef List Nodes; + + void add_node(Nodes::Node* tn); + Nodes::Node* remove_node(const string& name); + + Nodes& nodes() { return _nodes; } + Connections& connections() { return _connections; } + + const Nodes& nodes() const { return _nodes; } + const Connections& connections() const { return _connections; } + + uint32_t num_ports() const; + + PortImpl* create_port(const string& name, DataType type, size_t buffer_size, bool is_output); + void add_input(List::Node* port) { _input_ports.push_back(port); } ///< Preprocesser thread + void add_output(List::Node* port) { _output_ports.push_back(port); } ///< Preprocessor thread + List::Node* remove_port(const string& name); + + void add_connection(Connections::Node* c) { _connections.push_back(c); } + Connections::Node* remove_connection(const PortImpl* src_port, const PortImpl* dst_port); + + CompiledPatch* compiled_patch() { return _compiled_patch; } + void compiled_patch(CompiledPatch* cp) { _compiled_patch = cp; } + + Raul::Array* external_ports() { return _ports; } + void external_ports(Raul::Array* pa) { _ports = pa; } + + CompiledPatch* compile() const; + Raul::Array* build_ports_array() const; + + /** Whether to run this patch's DSP bits in the audio thread */ + bool enabled() const { return _process; } + void enable() { _process = true; } + void disable(); + + uint32_t internal_polyphony() const { return _internal_poly; } + +private: + inline void compile_recursive(NodeImpl* n, CompiledPatch* output) const; + void process_parallel(ProcessContext& context); + void process_single(ProcessContext& context); + + Engine& _engine; + uint32_t _internal_poly; + CompiledPatch* _compiled_patch; ///< Accessed in audio thread only + Connections _connections; ///< Accessed in audio thread only + List _input_ports; ///< Accessed in preprocessing thread only + List _output_ports; ///< Accessed in preprocessing thread only + Nodes _nodes; ///< Accessed in preprocessing thread only + bool _process; +}; + + + +/** Private helper for compile */ +inline void +PatchImpl::compile_recursive(NodeImpl* n, CompiledPatch* output) const +{ + if (n == NULL || n->traversed()) + return; + + n->traversed(true); + assert(output != NULL); + + for (List::iterator i = n->providers()->begin(); i != n->providers()->end(); ++i) + if ( ! (*i)->traversed() ) + compile_recursive((*i), output); + + output->push_back(CompiledNode(n, n->providers()->size(), n->dependants())); +} + + +} // namespace Ingen + +#endif // PATCHIMPL_H diff --git a/src/libs/engine/PluginImpl.cpp b/src/libs/engine/PluginImpl.cpp index 710c6385..e8b090ef 100644 --- a/src/libs/engine/PluginImpl.cpp +++ b/src/libs/engine/PluginImpl.cpp @@ -24,7 +24,7 @@ namespace Ingen { NodeImpl* -PluginImpl::instantiate(const string& name, bool polyphonic, Ingen::Patch* parent, SampleRate srate, size_t buffer_size) +PluginImpl::instantiate(const string& name, bool polyphonic, Ingen::PatchImpl* parent, SampleRate srate, size_t buffer_size) { assert(_type == Internal); diff --git a/src/libs/engine/PluginImpl.hpp b/src/libs/engine/PluginImpl.hpp index 13f17ca6..86d3cc5b 100644 --- a/src/libs/engine/PluginImpl.hpp +++ b/src/libs/engine/PluginImpl.hpp @@ -36,7 +36,7 @@ using Ingen::Shared::Plugin; namespace Ingen { -class Patch; +class PatchImpl; class NodeImpl; @@ -117,7 +117,7 @@ public: void slv2_plugin(SLV2Plugin p) { _slv2_plugin = p; } #endif - NodeImpl* instantiate(const string& name, bool polyphonic, Ingen::Patch* parent, SampleRate srate, size_t buffer_size); + NodeImpl* instantiate(const string& name, bool polyphonic, Ingen::PatchImpl* parent, SampleRate srate, size_t buffer_size); private: Plugin::Type _type; diff --git a/src/libs/engine/TransportNode.cpp b/src/libs/engine/TransportNode.cpp index dca8eecb..6a9fa73d 100644 --- a/src/libs/engine/TransportNode.cpp +++ b/src/libs/engine/TransportNode.cpp @@ -27,7 +27,7 @@ namespace Ingen { -TransportNode::TransportNode(const string& path, bool polyphonic, Patch* parent, SampleRate srate, size_t buffer_size) +TransportNode::TransportNode(const string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size) : NodeBase(new PluginImpl(Plugin::Internal, "ingen:transport_node"), path, false, parent, srate, buffer_size) { #if 0 diff --git a/src/libs/engine/TransportNode.hpp b/src/libs/engine/TransportNode.hpp index e79d5737..af0ed207 100644 --- a/src/libs/engine/TransportNode.hpp +++ b/src/libs/engine/TransportNode.hpp @@ -34,7 +34,7 @@ namespace Ingen { class TransportNode : public NodeBase { public: - TransportNode(const std::string& path, bool polyphonic, Patch* parent, SampleRate srate, size_t buffer_size); + TransportNode(const std::string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size); virtual void process(ProcessContext& context); }; diff --git a/src/libs/engine/events/AllNotesOffEvent.cpp b/src/libs/engine/events/AllNotesOffEvent.cpp index f3491dac..2e1f45fa 100644 --- a/src/libs/engine/events/AllNotesOffEvent.cpp +++ b/src/libs/engine/events/AllNotesOffEvent.cpp @@ -25,7 +25,7 @@ namespace Ingen { /** Note off with patch explicitly passed - triggered by MIDI. */ -AllNotesOffEvent::AllNotesOffEvent(Engine& engine, SharedPtr responder, SampleCount timestamp, Patch* patch) +AllNotesOffEvent::AllNotesOffEvent(Engine& engine, SharedPtr responder, SampleCount timestamp, PatchImpl* patch) : Event(engine, responder, timestamp), _patch(patch) { @@ -36,8 +36,8 @@ AllNotesOffEvent::AllNotesOffEvent(Engine& engine, SharedPtr responde */ AllNotesOffEvent::AllNotesOffEvent(Engine& engine, SharedPtr responder, SampleCount timestamp, const string& patch_path) : Event(engine, responder, timestamp), - _patch(NULL), - _patch_path(patch_path) + _patch_path(patch_path), + _patch(NULL) { } diff --git a/src/libs/engine/events/AllNotesOffEvent.hpp b/src/libs/engine/events/AllNotesOffEvent.hpp index 4c2a9309..3e4d56b3 100644 --- a/src/libs/engine/events/AllNotesOffEvent.hpp +++ b/src/libs/engine/events/AllNotesOffEvent.hpp @@ -24,7 +24,7 @@ using std::string; namespace Ingen { -class Patch; +class PatchImpl; /** A note off event for all active voices. @@ -34,15 +34,15 @@ class Patch; class AllNotesOffEvent : public Event { public: - AllNotesOffEvent(Engine& engine, SharedPtr responder, SampleCount timestamp, Patch* patch); + AllNotesOffEvent(Engine& engine, SharedPtr responder, SampleCount timestamp, PatchImpl* patch); AllNotesOffEvent(Engine& engine, SharedPtr responder, SampleCount timestamp, const string& patch_path); void execute(ProcessContext& context); void post_process(); private: - Patch* _patch; - string _patch_path; + const string _patch_path; + PatchImpl* _patch; }; diff --git a/src/libs/engine/events/ClearPatchEvent.cpp b/src/libs/engine/events/ClearPatchEvent.cpp index 0d76724a..211ca79e 100644 --- a/src/libs/engine/events/ClearPatchEvent.cpp +++ b/src/libs/engine/events/ClearPatchEvent.cpp @@ -19,7 +19,7 @@ #include "ClearPatchEvent.hpp" #include "Responder.hpp" #include "Engine.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "ClientBroadcaster.hpp" #include "util.hpp" #include "ObjectStore.hpp" @@ -92,7 +92,7 @@ ClearPatchEvent::post_process() _patch->nodes().clear(); // Delete all connections - for (Patch::Connections::iterator i = _patch->connections().begin(); i != _patch->connections().end(); ++i) + for (PatchImpl::Connections::iterator i = _patch->connections().begin(); i != _patch->connections().end(); ++i) (*i).reset(); _patch->connections().clear(); diff --git a/src/libs/engine/events/ClearPatchEvent.hpp b/src/libs/engine/events/ClearPatchEvent.hpp index b1174c04..afe66eed 100644 --- a/src/libs/engine/events/ClearPatchEvent.hpp +++ b/src/libs/engine/events/ClearPatchEvent.hpp @@ -26,7 +26,7 @@ using std::string; namespace Ingen { -class Patch; +class PatchImpl; /** Delete all nodes from a patch. @@ -43,9 +43,9 @@ public: void post_process(); private: - string _patch_path; - Patch* _patch; - bool _process; + const string _patch_path; + PatchImpl* _patch; + bool _process; }; diff --git a/src/libs/engine/events/ConnectionEvent.cpp b/src/libs/engine/events/ConnectionEvent.cpp index 3a954781..ee2c1694 100644 --- a/src/libs/engine/events/ConnectionEvent.cpp +++ b/src/libs/engine/events/ConnectionEvent.cpp @@ -25,7 +25,7 @@ #include "ConnectionImpl.hpp" #include "InputPort.hpp" #include "OutputPort.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "ClientBroadcaster.hpp" #include "PortImpl.hpp" #include "ObjectStore.hpp" @@ -98,13 +98,13 @@ ConnectionEvent::pre_process() assert(src_node->parent() == dst_node || dst_node->parent() == src_node); if (src_node->parent() == dst_node) - _patch = dynamic_cast(dst_node); + _patch = dynamic_cast(dst_node); else - _patch = dynamic_cast(src_node); + _patch = dynamic_cast(src_node); // Connection from a patch input to a patch output (pass through) - } else if (src_node == dst_node && dynamic_cast(src_node)) { - _patch = dynamic_cast(src_node); + } else if (src_node == dst_node && dynamic_cast(src_node)) { + _patch = dynamic_cast(src_node); // Normal connection between nodes with the same parent } else { @@ -126,7 +126,7 @@ ConnectionEvent::pre_process() } _connection = SharedPtr(new ConnectionImpl(_src_port, _dst_port)); - _patch_listnode = new Patch::Connections::Node(_connection); + _patch_listnode = new PatchImpl::Connections::Node(_connection); _port_listnode = new InputPort::Connections::Node(_connection); // Need to be careful about patch port connections here and adding a node's diff --git a/src/libs/engine/events/ConnectionEvent.hpp b/src/libs/engine/events/ConnectionEvent.hpp index 1d46be6f..89407957 100644 --- a/src/libs/engine/events/ConnectionEvent.hpp +++ b/src/libs/engine/events/ConnectionEvent.hpp @@ -21,7 +21,7 @@ #include #include #include "QueuedEvent.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "InputPort.hpp" #include "types.hpp" using std::string; @@ -33,7 +33,7 @@ namespace Raul { namespace Ingen { -class Patch; +class PatchImpl; class NodeImpl; class ConnectionImpl; class MidiMessage; @@ -71,7 +71,7 @@ private: Raul::Path _src_port_path; Raul::Path _dst_port_path; - Patch* _patch; + PatchImpl* _patch; PortImpl* _src_port; PortImpl* _dst_port; OutputPort* _src_output_port; @@ -80,7 +80,7 @@ private: CompiledPatch* _compiled_patch; ///< New process order for Patch SharedPtr _connection; - Patch::Connections::Node* _patch_listnode; + PatchImpl::Connections::Node* _patch_listnode; InputPort::Connections::Node* _port_listnode; ErrorType _error; diff --git a/src/libs/engine/events/CreateNodeEvent.cpp b/src/libs/engine/events/CreateNodeEvent.cpp index a863e008..a0a8d08f 100644 --- a/src/libs/engine/events/CreateNodeEvent.cpp +++ b/src/libs/engine/events/CreateNodeEvent.cpp @@ -20,11 +20,11 @@ #include #include "CreateNodeEvent.hpp" #include "Responder.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "NodeImpl.hpp" #include "PluginImpl.hpp" #include "Engine.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "NodeFactory.hpp" #include "ClientBroadcaster.hpp" #include "ObjectStore.hpp" @@ -91,7 +91,7 @@ CreateNodeEvent::pre_process() // This can be done here because the audio thread doesn't touch the // node tree - just the process order array - _patch->add_node(new Patch::Nodes::Node(_node)); + _patch->add_node(new PatchImpl::Nodes::Node(_node)); //_node->add_to_store(_engine.object_store()); _engine.object_store()->add(_node); diff --git a/src/libs/engine/events/CreateNodeEvent.hpp b/src/libs/engine/events/CreateNodeEvent.hpp index 75dfe3d7..6c3f2a94 100644 --- a/src/libs/engine/events/CreateNodeEvent.hpp +++ b/src/libs/engine/events/CreateNodeEvent.hpp @@ -28,7 +28,7 @@ template class TreeNode; namespace Ingen { -class Patch; +class PatchImpl; class NodeImpl; class CompiledPatch; @@ -69,7 +69,7 @@ private: string _plugin_lib; string _plugin_label; bool _poly; - Patch* _patch; + PatchImpl* _patch; NodeImpl* _node; CompiledPatch* _compiled_patch; ///< Patch's new process order bool _node_already_exists; diff --git a/src/libs/engine/events/CreatePatchEvent.cpp b/src/libs/engine/events/CreatePatchEvent.cpp index 3d08a44b..8642dc1d 100644 --- a/src/libs/engine/events/CreatePatchEvent.cpp +++ b/src/libs/engine/events/CreatePatchEvent.cpp @@ -19,7 +19,7 @@ #include #include "CreatePatchEvent.hpp" #include "Responder.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "NodeImpl.hpp" #include "PluginImpl.hpp" #include "Engine.hpp" @@ -65,13 +65,13 @@ CreatePatchEvent::pre_process() } uint32_t poly = 1; - if (_parent != NULL && _poly > 1 && _poly == static_cast(_parent->internal_poly())) + if (_parent != NULL && _poly > 1 && _poly == static_cast(_parent->internal_polyphony())) poly = _poly; - _patch = new Patch(_engine, _path.name(), poly, _parent, _engine.audio_driver()->sample_rate(), _engine.audio_driver()->buffer_size(), _poly); + _patch = new PatchImpl(_engine, _path.name(), poly, _parent, _engine.audio_driver()->sample_rate(), _engine.audio_driver()->buffer_size(), _poly); if (_parent != NULL) { - _parent->add_node(new Patch::Nodes::Node(_patch)); + _parent->add_node(new PatchImpl::Nodes::Node(_patch)); if (_parent->enabled()) _compiled_patch = _parent->compile(); diff --git a/src/libs/engine/events/CreatePatchEvent.hpp b/src/libs/engine/events/CreatePatchEvent.hpp index 15b67ffb..bcbcf35b 100644 --- a/src/libs/engine/events/CreatePatchEvent.hpp +++ b/src/libs/engine/events/CreatePatchEvent.hpp @@ -29,7 +29,7 @@ template class TreeNode; namespace Ingen { -class Patch; +class PatchImpl; class CompiledPatch; @@ -49,12 +49,12 @@ public: private: enum ErrorType { NO_ERROR, OBJECT_EXISTS, PARENT_NOT_FOUND, INVALID_POLY }; - Raul::Path _path; - Patch* _patch; - Patch* _parent; - CompiledPatch* _compiled_patch; - int _poly; - ErrorType _error; + Raul::Path _path; + PatchImpl* _patch; + PatchImpl* _parent; + CompiledPatch* _compiled_patch; + int _poly; + ErrorType _error; }; diff --git a/src/libs/engine/events/CreatePortEvent.cpp b/src/libs/engine/events/CreatePortEvent.cpp index cba4dd77..27dcf7bc 100644 --- a/src/libs/engine/events/CreatePortEvent.cpp +++ b/src/libs/engine/events/CreatePortEvent.cpp @@ -21,10 +21,10 @@ #include #include "Responder.hpp" #include "CreatePortEvent.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "PluginImpl.hpp" #include "Engine.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "QueuedEventSource.hpp" #include "ObjectStore.hpp" #include "ClientBroadcaster.hpp" diff --git a/src/libs/engine/events/CreatePortEvent.hpp b/src/libs/engine/events/CreatePortEvent.hpp index d7835a25..5ddd8aa3 100644 --- a/src/libs/engine/events/CreatePortEvent.hpp +++ b/src/libs/engine/events/CreatePortEvent.hpp @@ -29,7 +29,7 @@ template class Array; namespace Ingen { -class Patch; +class PatchImpl; class PortImpl; class DriverPort; @@ -59,7 +59,7 @@ private: string _type; bool _is_output; DataType _data_type; - Patch* _patch; + PatchImpl* _patch; PortImpl* _patch_port; Raul::Array* _ports_array; ///< New (external) ports array for Patch DriverPort* _driver_port; ///< Driver (eg Jack) port if this is a toplevel port diff --git a/src/libs/engine/events/DestroyEvent.cpp b/src/libs/engine/events/DestroyEvent.cpp index 7fdda39f..cf250f2f 100644 --- a/src/libs/engine/events/DestroyEvent.cpp +++ b/src/libs/engine/events/DestroyEvent.cpp @@ -20,7 +20,7 @@ #include "DestroyEvent.hpp" #include "Responder.hpp" #include "Engine.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "NodeBase.hpp" #include "PluginImpl.hpp" #include "AudioDriver.hpp" @@ -40,8 +40,6 @@ DestroyEvent::DestroyEvent(Engine& engine, SharedPtr responder, Frame _path(path), _store_iterator(engine.object_store()->objects().end()), _removed_table(NULL), - _node(NULL), - _port(NULL), _driver_port(NULL), _patch_node_listnode(NULL), _patch_port_listnode(NULL), @@ -67,10 +65,10 @@ DestroyEvent::pre_process() _store_iterator = _engine.object_store()->find(_path); if (_store_iterator != _engine.object_store()->objects().end()) { - _node = dynamic_cast(_store_iterator->second); + _node = PtrCast(_store_iterator->second); if (!_node) - _port = dynamic_cast(_store_iterator->second); + _port = PtrCast(_store_iterator->second); } if (_store_iterator != _engine.object_store()->objects().end()) { @@ -81,9 +79,9 @@ DestroyEvent::pre_process() assert(_node->parent_patch()); _patch_node_listnode = _node->parent_patch()->remove_node(_path.name()); if (_patch_node_listnode) { - assert(_patch_node_listnode->elem() == _node); + assert(_patch_node_listnode->elem() == _node.get()); - _disconnect_node_event = new DisconnectNodeEvent(_engine, _node); + _disconnect_node_event = new DisconnectNodeEvent(_engine, _node.get()); _disconnect_node_event->pre_process(); if (_node->parent_patch()->enabled()) { @@ -92,7 +90,7 @@ DestroyEvent::pre_process() #ifndef NDEBUG // Be sure node is removed from process order, so it can be destroyed for (size_t i=0; i < _compiled_patch->size(); ++i) { - assert(_compiled_patch->at(i).node() != _node); + assert(_compiled_patch->at(i).node() != _node.get()); // FIXME: check providers/dependants too } #endif @@ -102,11 +100,11 @@ DestroyEvent::pre_process() assert(_port->parent_patch()); _patch_port_listnode = _port->parent_patch()->remove_port(_path.name()); if (_patch_port_listnode) { - assert(_patch_port_listnode->elem() == _port); + assert(_patch_port_listnode->elem() == _port.get()); //_port->remove_from_store(); - _disconnect_port_event = new DisconnectPortEvent(_engine, _port->parent_patch(), _port); + _disconnect_port_event = new DisconnectPortEvent(_engine, _port->parent_patch(), _port.get()); _disconnect_port_event->pre_process(); if (_port->parent_patch()->enabled()) { @@ -187,7 +185,8 @@ DestroyEvent::post_process() _disconnect_node_event->post_process(); _engine.broadcaster()->send_destroyed(_path); _engine.maid()->push(_patch_node_listnode); - _engine.maid()->push(_node); + //_engine.maid()->push(_node); + _node.reset(); } else if (_patch_port_listnode) { assert(_port); _responder->respond_ok(); @@ -195,7 +194,8 @@ DestroyEvent::post_process() _disconnect_port_event->post_process(); _engine.broadcaster()->send_destroyed(_path); _engine.maid()->push(_patch_port_listnode); - _engine.maid()->push(_port); + //_engine.maid()->push(_port); + _port.reset(); } else { _responder->respond_error("Unable to destroy object"); } diff --git a/src/libs/engine/events/DestroyEvent.hpp b/src/libs/engine/events/DestroyEvent.hpp index e253167f..10e59751 100644 --- a/src/libs/engine/events/DestroyEvent.hpp +++ b/src/libs/engine/events/DestroyEvent.hpp @@ -22,7 +22,7 @@ #include #include "QueuedEvent.hpp" #include "ObjectStore.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" using std::string; @@ -58,18 +58,18 @@ public: void post_process(); private: - Path _path; - ObjectStore::Objects::iterator _store_iterator; - Table _removed_table; - NodeImpl* _node; ///< Same as _object if it is a Node, otherwise NULL - PortImpl* _port; ///< Same as _object if it is a Port, otherwise NULL - DriverPort* _driver_port; - Patch::Nodes::Node* _patch_node_listnode; - Raul::List::Node* _patch_port_listnode; - Raul::Array* _ports_array; ///< New (external) ports array for Patch - CompiledPatch* _compiled_patch; ///< Patch's new process order - DisconnectNodeEvent* _disconnect_node_event; - DisconnectPortEvent* _disconnect_port_event; + Path _path; + ObjectStore::Objects::iterator _store_iterator; + Table > _removed_table; + SharedPtr _node; ///< Non-NULL iff a node + SharedPtr _port; ///< Non-NULL iff a port + DriverPort* _driver_port; + PatchImpl::Nodes::Node* _patch_node_listnode; + Raul::List::Node* _patch_port_listnode; + Raul::Array* _ports_array; ///< New (external) ports for Patch + CompiledPatch* _compiled_patch; ///< Patch's new process order + DisconnectNodeEvent* _disconnect_node_event; + DisconnectPortEvent* _disconnect_port_event; }; diff --git a/src/libs/engine/events/DisconnectNodeEvent.cpp b/src/libs/engine/events/DisconnectNodeEvent.cpp index f085e974..4fa92af0 100644 --- a/src/libs/engine/events/DisconnectNodeEvent.cpp +++ b/src/libs/engine/events/DisconnectNodeEvent.cpp @@ -28,7 +28,7 @@ #include "NodeImpl.hpp" #include "ObjectStore.hpp" #include "OutputPort.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "PortImpl.hpp" #include "Responder.hpp" #include "util.hpp" @@ -88,7 +88,7 @@ DisconnectNodeEvent::pre_process() } } - for (Patch::Connections::const_iterator i = _patch->connections().begin(); i != _patch->connections().end(); ++i) { + for (PatchImpl::Connections::const_iterator i = _patch->connections().begin(); i != _patch->connections().end(); ++i) { ConnectionImpl* c = (ConnectionImpl*)i->get(); if ((c->src_port()->parent_node() == _node || c->dst_port()->parent_node() == _node) && !c->pending_disconnection()) { DisconnectionEvent* ev = new DisconnectionEvent(_engine, SharedPtr(new Responder()), _time, diff --git a/src/libs/engine/events/DisconnectNodeEvent.hpp b/src/libs/engine/events/DisconnectNodeEvent.hpp index cefe5a25..6d38c768 100644 --- a/src/libs/engine/events/DisconnectNodeEvent.hpp +++ b/src/libs/engine/events/DisconnectNodeEvent.hpp @@ -28,7 +28,7 @@ using std::string; namespace Ingen { class DisconnectionEvent; -class Patch; +class PatchImpl; class NodeImpl; class Connection; class PortImpl; @@ -53,7 +53,7 @@ public: private: Raul::Path _node_path; - Patch* _patch; + PatchImpl* _patch; NodeImpl* _node; Raul::List _disconnection_events; diff --git a/src/libs/engine/events/DisconnectPortEvent.cpp b/src/libs/engine/events/DisconnectPortEvent.cpp index 9aaf5c45..617d86a2 100644 --- a/src/libs/engine/events/DisconnectPortEvent.cpp +++ b/src/libs/engine/events/DisconnectPortEvent.cpp @@ -28,7 +28,7 @@ #include "PortImpl.hpp" #include "InputPort.hpp" #include "OutputPort.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "ClientBroadcaster.hpp" #include "util.hpp" #include "ObjectStore.hpp" @@ -51,7 +51,7 @@ DisconnectPortEvent::DisconnectPortEvent(Engine& engine, SharedPtr re } -DisconnectPortEvent::DisconnectPortEvent(Engine& engine, Patch* patch, Port* port) +DisconnectPortEvent::DisconnectPortEvent(Engine& engine, PatchImpl* patch, Port* port) : QueuedEvent(engine), _port_path(port->path()), _patch(patch), @@ -103,7 +103,7 @@ DisconnectPortEvent::pre_process() return; } - for (Patch::Connections::const_iterator i = _patch->connections().begin(); + for (PatchImpl::Connections::const_iterator i = _patch->connections().begin(); i != _patch->connections().end(); ++i) { ConnectionImpl* c = (ConnectionImpl*)i->get(); if ((c->src_port() == _port || c->dst_port() == _port) && !c->pending_disconnection()) { diff --git a/src/libs/engine/events/DisconnectPortEvent.hpp b/src/libs/engine/events/DisconnectPortEvent.hpp index b30151ed..de75ddf2 100644 --- a/src/libs/engine/events/DisconnectPortEvent.hpp +++ b/src/libs/engine/events/DisconnectPortEvent.hpp @@ -28,7 +28,7 @@ namespace Raul { template class Array; } namespace Ingen { -class Patch; +class PatchImpl; class NodeImpl; class Connection; class PortImpl; @@ -45,7 +45,7 @@ class DisconnectPortEvent : public QueuedEvent { public: DisconnectPortEvent(Engine& engine, SharedPtr responder, SampleCount timestamp, const string& port_path); - DisconnectPortEvent(Engine& engine, Patch* patch, Port* port); + DisconnectPortEvent(Engine& engine, PatchImpl* patch, Port* port); ~DisconnectPortEvent(); void pre_process(); @@ -54,7 +54,7 @@ public: private: Path _port_path; - Patch* _patch; + PatchImpl* _patch; Port* _port; Raul::List _disconnection_events; diff --git a/src/libs/engine/events/DisconnectionEvent.cpp b/src/libs/engine/events/DisconnectionEvent.cpp index 6e69c3ba..e85b4fcf 100644 --- a/src/libs/engine/events/DisconnectionEvent.cpp +++ b/src/libs/engine/events/DisconnectionEvent.cpp @@ -24,7 +24,7 @@ #include "ConnectionImpl.hpp" #include "InputPort.hpp" #include "OutputPort.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "ClientBroadcaster.hpp" #include "PortImpl.hpp" #include "ObjectStore.hpp" @@ -111,13 +111,13 @@ DisconnectionEvent::pre_process() assert(src_node->parent() == dst_node || dst_node->parent() == src_node); if (src_node->parent() == dst_node) - _patch = dynamic_cast(dst_node); + _patch = dynamic_cast(dst_node); else - _patch = dynamic_cast(src_node); + _patch = dynamic_cast(src_node); // Connection from a patch input to a patch output (pass through) - } else if (src_node == dst_node && dynamic_cast(src_node)) { - _patch = dynamic_cast(src_node); + } else if (src_node == dst_node && dynamic_cast(src_node)) { + _patch = dynamic_cast(src_node); // Normal connection between nodes with the same parent } else { @@ -161,7 +161,7 @@ DisconnectionEvent::execute(ProcessContext& context) = _dst_input_port->remove_connection(_src_output_port); if (port_connection != NULL) { - Patch::Connections::Node* const patch_connection + PatchImpl::Connections::Node* const patch_connection = _patch->remove_connection(_src_port, _dst_port); assert(patch_connection); diff --git a/src/libs/engine/events/DisconnectionEvent.hpp b/src/libs/engine/events/DisconnectionEvent.hpp index 603eaf47..ea4dbbda 100644 --- a/src/libs/engine/events/DisconnectionEvent.hpp +++ b/src/libs/engine/events/DisconnectionEvent.hpp @@ -31,7 +31,7 @@ namespace Raul { namespace Ingen { -class Patch; +class PatchImpl; class NodeImpl; class ConnectionImpl; class MidiMessage; @@ -70,7 +70,7 @@ private: Raul::Path _src_port_path; Raul::Path _dst_port_path; - Patch* _patch; + PatchImpl* _patch; PortImpl* _src_port; PortImpl* _dst_port; OutputPort* _src_output_port; diff --git a/src/libs/engine/events/EnablePatchEvent.cpp b/src/libs/engine/events/EnablePatchEvent.cpp index e380340f..b1cda98a 100644 --- a/src/libs/engine/events/EnablePatchEvent.cpp +++ b/src/libs/engine/events/EnablePatchEvent.cpp @@ -18,7 +18,7 @@ #include "EnablePatchEvent.hpp" #include "Responder.hpp" #include "Engine.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "util.hpp" #include "ClientBroadcaster.hpp" #include "ObjectStore.hpp" diff --git a/src/libs/engine/events/EnablePatchEvent.hpp b/src/libs/engine/events/EnablePatchEvent.hpp index fa36aae4..dad1803a 100644 --- a/src/libs/engine/events/EnablePatchEvent.hpp +++ b/src/libs/engine/events/EnablePatchEvent.hpp @@ -27,7 +27,7 @@ namespace Raul { template class Array; } namespace Ingen { -class Patch; +class PatchImpl; class NodeImpl; class CompiledPatch; @@ -51,7 +51,7 @@ public: private: string _patch_path; - Patch* _patch; + PatchImpl* _patch; CompiledPatch* _compiled_patch; // Patch's new process order bool _enable; }; diff --git a/src/libs/engine/events/RenameEvent.cpp b/src/libs/engine/events/RenameEvent.cpp index 72e27ec9..d0ef532a 100644 --- a/src/libs/engine/events/RenameEvent.cpp +++ b/src/libs/engine/events/RenameEvent.cpp @@ -20,7 +20,7 @@ #include "Engine.hpp" #include "NodeImpl.hpp" #include "ObjectStore.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "RenameEvent.hpp" #include "Responder.hpp" #include "AudioDriver.hpp" @@ -77,10 +77,10 @@ RenameEvent::pre_process() return; } - Table removed = _engine.object_store()->remove(_store_iterator); + Table > removed = _engine.object_store()->remove(_store_iterator); assert(removed.size() > 0); - for (Table::iterator i = removed.begin(); i != removed.end(); ++i) { + for (Table >::iterator i = removed.begin(); i != removed.end(); ++i) { const Path& child_old_path = i->first; assert(Path::descendant_comparator(_old_path, child_old_path)); @@ -90,7 +90,7 @@ RenameEvent::pre_process() else child_new_path = _new_path.base() + child_old_path.substr(_old_path.length()+1); - i->second->set_path(child_new_path); + PtrCast(i->second)->set_path(child_new_path); i->first = child_new_path; } @@ -105,7 +105,7 @@ RenameEvent::execute(ProcessContext& context) { QueuedEvent::execute(context); - PortImpl* port = dynamic_cast(_store_iterator->second); + SharedPtr port = PtrCast(_store_iterator->second); if (port && port->parent()->parent() == NULL) { DriverPort* driver_port = NULL; diff --git a/src/libs/engine/events/RenameEvent.hpp b/src/libs/engine/events/RenameEvent.hpp index 1a68173f..fae3a060 100644 --- a/src/libs/engine/events/RenameEvent.hpp +++ b/src/libs/engine/events/RenameEvent.hpp @@ -31,7 +31,7 @@ template class ListNode; namespace Ingen { class GraphObjectImpl; -class Patch; +class PatchImpl; class NodeImpl; class Plugin; class DisconnectNodeEvent; @@ -58,7 +58,7 @@ private: Path _old_path; string _name; Path _new_path; - Patch* _parent_patch; + PatchImpl* _parent_patch; ObjectStore::Objects::iterator _store_iterator; ErrorType _error; }; diff --git a/src/libs/engine/events/RequestAllObjectsEvent.cpp b/src/libs/engine/events/RequestAllObjectsEvent.cpp index e4d0f083..7865cd9b 100644 --- a/src/libs/engine/events/RequestAllObjectsEvent.cpp +++ b/src/libs/engine/events/RequestAllObjectsEvent.cpp @@ -45,7 +45,7 @@ RequestAllObjectsEvent::post_process() _responder->respond_ok(); // Everything is a child of the root patch, so this sends it all - Patch* root = _engine.object_store()->find_patch("/"); + PatchImpl* root = _engine.object_store()->find_patch("/"); if (root && _responder->client()) ObjectSender::send_patch(_responder->client(), root, true); diff --git a/src/libs/engine/events/RequestObjectEvent.cpp b/src/libs/engine/events/RequestObjectEvent.cpp index 13ad936e..34c04889 100644 --- a/src/libs/engine/events/RequestObjectEvent.cpp +++ b/src/libs/engine/events/RequestObjectEvent.cpp @@ -22,7 +22,7 @@ #include "Engine.hpp" #include "ObjectStore.hpp" #include "ClientBroadcaster.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "NodeImpl.hpp" #include "PortImpl.hpp" #include "ObjectSender.hpp" @@ -65,7 +65,7 @@ RequestObjectEvent::post_process() _responder->respond_error("Unable to find object requested."); } else if (_responder->client()) { - Patch* const patch = dynamic_cast(_object); + PatchImpl* const patch = dynamic_cast(_object); if (patch) { _responder->respond_ok(); ObjectSender::send_patch(_responder->client(), patch, true); diff --git a/src/libs/engine/events/SetPolyphonicEvent.cpp b/src/libs/engine/events/SetPolyphonicEvent.cpp index 51ab2dc8..ebaf9a22 100644 --- a/src/libs/engine/events/SetPolyphonicEvent.cpp +++ b/src/libs/engine/events/SetPolyphonicEvent.cpp @@ -19,7 +19,7 @@ #include "SetPolyphonicEvent.hpp" #include "Responder.hpp" #include "Engine.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "ClientBroadcaster.hpp" #include "util.hpp" #include "ObjectStore.hpp" diff --git a/src/libs/engine/events/SetPolyphonyEvent.cpp b/src/libs/engine/events/SetPolyphonyEvent.cpp index 56e95486..7efa7386 100644 --- a/src/libs/engine/events/SetPolyphonyEvent.cpp +++ b/src/libs/engine/events/SetPolyphonyEvent.cpp @@ -19,7 +19,7 @@ #include "SetPolyphonyEvent.hpp" #include "Responder.hpp" #include "Engine.hpp" -#include "Patch.hpp" +#include "PatchImpl.hpp" #include "ClientBroadcaster.hpp" #include "util.hpp" #include "ObjectStore.hpp" @@ -44,7 +44,7 @@ void SetPolyphonyEvent::pre_process() { _patch = _engine.object_store()->find_patch(_patch_path); - if (_patch && _poly > _patch->internal_poly()) + if (_patch && _poly > _patch->internal_polyphony()) _patch->prepare_internal_poly(_poly); QueuedEvent::pre_process(); diff --git a/src/libs/engine/events/SetPolyphonyEvent.hpp b/src/libs/engine/events/SetPolyphonyEvent.hpp index a2ac1862..8aba997a 100644 --- a/src/libs/engine/events/SetPolyphonyEvent.hpp +++ b/src/libs/engine/events/SetPolyphonyEvent.hpp @@ -26,7 +26,7 @@ using std::string; namespace Ingen { -class Patch; +class PatchImpl; /** Delete all nodes from a patch. @@ -43,9 +43,10 @@ public: void post_process(); private: - string _patch_path; - Patch* _patch; - uint32_t _poly; + const string _patch_path; + PatchImpl* _patch; + const uint32_t _poly; + }; diff --git a/src/libs/gui/PatchCanvas.cpp b/src/libs/gui/PatchCanvas.cpp index ac86b3fb..7cd31cb3 100644 --- a/src/libs/gui/PatchCanvas.cpp +++ b/src/libs/gui/PatchCanvas.cpp @@ -209,9 +209,9 @@ PatchCanvas::build() } // Create connections - for (list >::const_iterator i = _patch->connections().begin(); + for (PatchModel::Connections::const_iterator i = _patch->connections().begin(); i != _patch->connections().end(); ++i) { - connection(*i); + connection(PtrCast(*i)); } } @@ -306,15 +306,18 @@ PatchCanvas::get_port_view(SharedPtr port) void PatchCanvas::connection(SharedPtr cm) { + assert(cm); + const SharedPtr src = get_port_view(cm->src_port()); const SharedPtr dst = get_port_view(cm->dst_port()); - if (src && dst) + if (src && dst) { add_connection(boost::shared_ptr(new GUI::Connection(shared_from_this(), cm, src, dst, src->color() + 0x22222200))); - else + } else { cerr << "[PatchCanvas] ERROR: Unable to find ports to connect " << cm->src_port_path() << " -> " << cm->dst_port_path() << endl; + } } -- cgit v1.2.1