diff options
31 files changed, 259 insertions, 203 deletions
diff --git a/src/libs/client/ConnectionModel.cpp b/src/libs/client/ConnectionModel.cpp index 1c7541b9..18b6fbd7 100644 --- a/src/libs/client/ConnectionModel.cpp +++ b/src/libs/client/ConnectionModel.cpp @@ -27,8 +27,8 @@ ConnectionModel::ConnectionModel(const Path& src_port, const Path& dst_port) m_dst_port(NULL) { // Be sure connection is within one patch - assert(m_src_port_path.parent().parent() - == m_dst_port_path.parent().parent()); + //assert(m_src_port_path.parent().parent() + // == m_dst_port_path.parent().parent()); } @@ -51,4 +51,24 @@ ConnectionModel::dst_port_path() const return m_dst_port->path(); } +const Path +ConnectionModel::patch_path() const +{ + const Path& src_node = m_src_port_path.parent(); + const Path& dst_node = m_dst_port_path.parent(); + Path patch_path = src_node.parent(); + + if (src_node.parent() != dst_node.parent()) { + // Connection to a patch port from inside the patch + assert(src_node.parent() == dst_node || dst_node.parent() == src_node); + if (src_node.parent() == dst_node) + patch_path = dst_node; + else + patch_path = src_node; + } + + return patch_path; +} + + } // namespace LibOmClient diff --git a/src/libs/client/ConnectionModel.h b/src/libs/client/ConnectionModel.h index ef909850..427c5858 100644 --- a/src/libs/client/ConnectionModel.h +++ b/src/libs/client/ConnectionModel.h @@ -55,7 +55,7 @@ public: const Path& src_port_path() const; const Path& dst_port_path() const; - const Path patch_path() const { return src_port_path().parent().parent(); } + const Path patch_path() const; private: Path m_src_port_path; ///< Only used if m_src_port == NULL diff --git a/src/libs/client/PatchModel.cpp b/src/libs/client/PatchModel.cpp index 7d786301..265a17d8 100644 --- a/src/libs/client/PatchModel.cpp +++ b/src/libs/client/PatchModel.cpp @@ -163,19 +163,23 @@ void PatchModel::add_connection(CountedPtr<ConnectionModel> cm) { assert(cm); - assert(cm->src_port_path().parent().parent() == m_path); - assert(cm->dst_port_path().parent().parent() == m_path); + //assert(cm->src_port_path().parent().parent() == m_path); + //assert(cm->dst_port_path().parent().parent() == m_path); assert(cm->patch_path() == path()); + cerr << "PatchModel::add_connection: " << cm->src_port_path() << " -> " << cm->dst_port_path() << endl; + CountedPtr<ConnectionModel> existing = get_connection(cm->src_port_path(), cm->dst_port_path()); if (existing) { return; } - NodeModel* src_node = get_node(cm->src_port_path().parent().name()).get(); + NodeModel* src_node = (cm->src_port_path().parent() == path()) + ? this : get_node(cm->src_port_path().parent().name()).get(); PortModel* src_port = (src_node == NULL) ? NULL : src_node->get_port(cm->src_port_path().name()).get(); - NodeModel* dst_node = get_node(cm->dst_port_path().parent().name()).get(); + NodeModel* dst_node = (cm->dst_port_path().parent() == path()) + ? this : get_node(cm->dst_port_path().parent().name()).get(); PortModel* dst_port = (dst_node == NULL) ? NULL : dst_node->get_port(cm->dst_port_path().name()).get(); assert(src_port != NULL); diff --git a/src/libs/client/Store.cpp b/src/libs/client/Store.cpp index 542c1bc5..15f91786 100644 --- a/src/libs/client/Store.cpp +++ b/src/libs/client/Store.cpp @@ -311,24 +311,22 @@ Store::metadata_update_event(const string& subject_path, const string& predicate void -Store::connection_event(const string& src_port_path, const string& dst_port_path) +Store::connection_event(const Path& src_port_path, const Path& dst_port_path) { - const Path& src = src_port_path; - const Path& dst = dst_port_path; - - assert(src.parent().parent() == dst.parent().parent()); - const Path& patch_path = src.parent().parent(); + // ConnectionModel has the clever patch-path-figuring-out stuff in it, so + // just make one right away to get at that + ConnectionModel* cm = new ConnectionModel(src_port_path, dst_port_path); - CountedPtr<PatchModel> patch = this->patch(patch_path); + CountedPtr<PatchModel> patch = this->patch(cm->patch_path()); if (patch) - patch->add_connection(new ConnectionModel(src, dst)); + patch->add_connection(cm); else cerr << "ERROR: connection in nonexistant patch" << endl; } void -Store::disconnection_event(const string& src_port_path, const string& dst_port_path) +Store::disconnection_event(const Path& src_port_path, const Path& dst_port_path) { const Path& src = src_port_path; const Path& dst = dst_port_path; diff --git a/src/libs/client/Store.h b/src/libs/client/Store.h index 0b84d418..0e47168d 100644 --- a/src/libs/client/Store.h +++ b/src/libs/client/Store.h @@ -22,7 +22,9 @@ #include <map> #include "util/CountedPtr.h" #include <sigc++/sigc++.h> +#include "util/Path.h" using std::string; using std::map; +using Om::Path; namespace LibOmClient { @@ -71,8 +73,8 @@ private: void new_node_event(const string& plugin_type, const string& plugin_uri, const string& node_path, bool is_polyphonic, uint32_t num_ports); void new_port_event(const string& path, const string& data_type, bool is_output); void metadata_update_event(const string& subject_path, const string& predicate, const string& value); - void connection_event(const string& src_port_path, const string& dst_port_path); - void disconnection_event(const string& src_port_path, const string& dst_port_path); + void connection_event(const Path& src_port_path, const Path& dst_port_path); + void disconnection_event(const Path& src_port_path, const Path& dst_port_path); map<string, CountedPtr<ObjectModel> > m_objects; ///< Keyed by Om path map<string, CountedPtr<PluginModel> > m_plugins; ///< Keyed by URI diff --git a/src/libs/engine/Buffer.cpp b/src/libs/engine/Buffer.cpp index 963b14a5..4e94a943 100644 --- a/src/libs/engine/Buffer.cpp +++ b/src/libs/engine/Buffer.cpp @@ -39,6 +39,7 @@ Buffer<T>::Buffer(size_t size) { assert(m_size > 0); allocate(); + assert(m_data); } template Buffer<sample>::Buffer(size_t size); template Buffer<MidiMessage>::Buffer(size_t size); diff --git a/src/libs/engine/Driver.h b/src/libs/engine/Driver.h index ade50a71..11060c04 100644 --- a/src/libs/engine/Driver.h +++ b/src/libs/engine/Driver.h @@ -22,7 +22,7 @@ using std::string; namespace Om { -template <typename T> class TypedPort; +template <typename T> class DuplexPort; /** Representation of a system (outside Om, ie hardware) audio port. @@ -77,7 +77,7 @@ public: * * May return NULL if the Driver can not drive the port for some reason. */ - virtual DriverPort* create_port(TypedPort<T>* patch_port) = 0; + virtual DriverPort* create_port(DuplexPort<T>* patch_port) = 0; }; diff --git a/src/libs/engine/InputPort.cpp b/src/libs/engine/InputPort.cpp index 0e7a349d..752efde4 100644 --- a/src/libs/engine/InputPort.cpp +++ b/src/libs/engine/InputPort.cpp @@ -18,7 +18,7 @@ #include <iostream> #include <cstdlib> #include <cassert> -#include "ConnectionBase.h" +#include "TypedConnection.h" #include "OutputPort.h" #include "Node.h" #include "Om.h" @@ -46,21 +46,21 @@ template InputPort<MidiMessage>::InputPort(Node* parent, const string& name, siz */ template<typename T> void -InputPort<T>::add_connection(ListNode<ConnectionBase<T>*>* const c) +InputPort<T>::add_connection(ListNode<TypedConnection<T>*>* const c) { m_connections.push_back(c); bool modify_buffers = !m_fixed_buffers; - if (modify_buffers && m_is_tied) - modify_buffers = !m_tied_port->fixed_buffers(); + //if (modify_buffers && m_is_tied) + // modify_buffers = !m_tied_port->fixed_buffers(); if (modify_buffers) { if (m_connections.size() == 1) { // Use buffer directly to avoid copying for (size_t i=0; i < _poly; ++i) { m_buffers.at(i)->join(c->elem()->buffer(i)); - if (m_is_tied) - m_tied_port->buffer(i)->join(m_buffers.at(i)); + //if (m_is_tied) + // m_tied_port->buffer(i)->join(m_buffers.at(i)); assert(m_buffers.at(i)->data() == c->elem()->buffer(i)->data()); } } else if (m_connections.size() == 2) { @@ -68,34 +68,34 @@ InputPort<T>::add_connection(ListNode<ConnectionBase<T>*>* const c) // so have to use local ones again and mix down for (size_t i=0; i < _poly; ++i) { m_buffers.at(i)->unjoin(); - if (m_is_tied) - m_tied_port->buffer(i)->join(m_buffers.at(i)); + //if (m_is_tied) + // m_tied_port->buffer(i)->join(m_buffers.at(i)); } } update_buffers(); } - assert( ! m_is_tied || m_tied_port != NULL); - assert( ! m_is_tied || m_buffers.at(0)->data() == m_tied_port->buffer(0)->data()); + //assert( ! m_is_tied || m_tied_port != NULL); + //assert( ! m_is_tied || m_buffers.at(0)->data() == m_tied_port->buffer(0)->data()); } -template void InputPort<sample>::add_connection(ListNode<ConnectionBase<sample>*>* const c); -template void InputPort<MidiMessage>::add_connection(ListNode<ConnectionBase<MidiMessage>*>* const c); +template void InputPort<sample>::add_connection(ListNode<TypedConnection<sample>*>* const c); +template void InputPort<MidiMessage>::add_connection(ListNode<TypedConnection<MidiMessage>*>* const c); /** Remove a connection. Realtime safe. */ template <typename T> -ListNode<ConnectionBase<T>*>* +ListNode<TypedConnection<T>*>* InputPort<T>::remove_connection(const OutputPort<T>* const src_port) { bool modify_buffers = !m_fixed_buffers; - if (modify_buffers && m_is_tied) - modify_buffers = !m_tied_port->fixed_buffers(); + //if (modify_buffers && m_is_tied) + // modify_buffers = !m_tied_port->fixed_buffers(); - typedef typename List<ConnectionBase<T>*>::iterator ConnectionBaseListIterator; + typedef typename List<TypedConnection<T>*>::iterator TypedConnectionListIterator; bool found = false; - ListNode<ConnectionBase<T>*>* connection = NULL; - for (ConnectionBaseListIterator i = m_connections.begin(); i != m_connections.end(); ++i) { + ListNode<TypedConnection<T>*>* connection = NULL; + for (TypedConnectionListIterator i = m_connections.begin(); i != m_connections.end(); ++i) { if ((*i)->src_port()->path() == src_port->path()) { connection = m_connections.remove(i); found = true; @@ -112,15 +112,15 @@ InputPort<T>::remove_connection(const OutputPort<T>* const src_port) if (modify_buffers && m_buffers.at(i)->is_joined()) m_buffers.at(i)->unjoin(); m_buffers.at(i)->clear(); // Write silence - if (m_is_tied) - m_tied_port->buffer(i)->join(m_buffers.at(i)); + //if (m_is_tied) + //m_tied_port->buffer(i)->join(m_buffers.at(i)); } } else if (modify_buffers && m_connections.size() == 1) { // Share a buffer for (size_t i=0; i < _poly; ++i) { m_buffers.at(i)->join((*m_connections.begin())->buffer(i)); - if (m_is_tied) - m_tied_port->buffer(i)->join(m_buffers.at(i)); + //if (m_is_tied) + // m_tied_port->buffer(i)->join(m_buffers.at(i)); } } } @@ -128,14 +128,14 @@ InputPort<T>::remove_connection(const OutputPort<T>* const src_port) if (modify_buffers) update_buffers(); - assert( ! m_is_tied || m_tied_port != NULL); - assert( ! m_is_tied || m_buffers.at(0)->data() == m_tied_port->buffer(0)->data()); + //assert( ! m_is_tied || m_tied_port != NULL); + //assert( ! m_is_tied || m_buffers.at(0)->data() == m_tied_port->buffer(0)->data()); return connection; } -template ListNode<ConnectionBase<sample>*>* +template ListNode<TypedConnection<sample>*>* InputPort<sample>::remove_connection(const OutputPort<sample>* const src_port); -template ListNode<ConnectionBase<MidiMessage>*>* +template ListNode<TypedConnection<MidiMessage>*>* InputPort<MidiMessage>::remove_connection(const OutputPort<MidiMessage>* const src_port); @@ -161,8 +161,8 @@ template <typename T> bool InputPort<T>::is_connected_to(const OutputPort<T>* const port) const { - typedef typename List<ConnectionBase<T>*>::const_iterator ConnectionBaseListIterator; - for (ConnectionBaseListIterator i = m_connections.begin(); i != m_connections.end(); ++i) + typedef typename List<TypedConnection<T>*>::const_iterator TypedConnectionListIterator; + for (TypedConnectionListIterator i = m_connections.begin(); i != m_connections.end(); ++i) if ((*i)->src_port() == port) return true; @@ -177,6 +177,7 @@ template bool InputPort<MidiMessage>::is_connected_to(const OutputPort<MidiMessa * This is used by OutputNode and InputNode to provide two different ports * (internal and external) that share a buffer. */ +/* template <typename T> void InputPort<T>::tie(OutputPort<T>* const port) @@ -202,7 +203,7 @@ InputPort<T>::tie(OutputPort<T>* const port) } template void InputPort<sample>::tie(OutputPort<sample>* const port); template void InputPort<MidiMessage>::tie(OutputPort<MidiMessage>* const port); - +*/ /** Prepare buffer for access, mixing if necessary. Realtime safe. * FIXME: nframes parameter not used, @@ -211,21 +212,21 @@ template<> void InputPort<sample>::prepare_buffers(size_t nframes) { - assert(!m_is_tied || m_tied_port != NULL); + //assert(!m_is_tied || m_tied_port != NULL); - typedef List<ConnectionBase<sample>*>::iterator ConnectionBaseListIterator; + typedef List<TypedConnection<sample>*>::iterator TypedConnectionListIterator; bool do_mixdown = true; if (m_connections.size() == 0) return; - for (ConnectionBaseListIterator c = m_connections.begin(); c != m_connections.end(); ++c) + for (TypedConnectionListIterator c = m_connections.begin(); c != m_connections.end(); ++c) (*c)->prepare_buffers(); // If only one connection, buffer is (maybe) used directly (no copying) if (m_connections.size() == 1) { // Buffer changed since connection if (m_buffers.at(0)->data() != (*m_connections.begin())->buffer(0)->data()) { - if (m_fixed_buffers || (m_is_tied && m_tied_port->fixed_buffers())) { + if (m_fixed_buffers) { // || (m_is_tied && m_tied_port->fixed_buffers())) { // can't change buffer, must copy do_mixdown = true; } else { @@ -245,15 +246,15 @@ InputPort<sample>::prepare_buffers(size_t nframes) return; } - assert(!m_is_tied || m_tied_port != NULL); - assert(!m_is_tied || m_buffers.at(0)->data() == m_tied_port->buffer(0)->data()); + /*assert(!m_is_tied || m_tied_port != NULL); + assert(!m_is_tied || m_buffers.at(0)->data() == m_tied_port->buffer(0)->data());*/ for (size_t voice=0; voice < _poly; ++voice) { m_buffers.at(voice)->copy((*m_connections.begin())->buffer(voice), 0, _buffer_size-1); if (m_connections.size() > 1) { // Copy first connection - ConnectionBaseListIterator c = m_connections.begin(); + TypedConnectionListIterator c = m_connections.begin(); // Add all other connections for (++c; c != m_connections.end(); ++c) @@ -271,17 +272,17 @@ template <> void InputPort<MidiMessage>::prepare_buffers(size_t nframes) { - assert(!m_is_tied || m_tied_port != NULL); + //assert(!m_is_tied || m_tied_port != NULL); const size_t num_ins = m_connections.size(); bool do_mixdown = true; assert(num_ins == 0 || num_ins == 1); - typedef List<ConnectionBase<MidiMessage>*>::iterator ConnectionBaseListIterator; + typedef List<TypedConnection<MidiMessage>*>::iterator TypedConnectionListIterator; assert(_poly == 1); - for (ConnectionBaseListIterator c = m_connections.begin(); c != m_connections.end(); ++c) + for (TypedConnectionListIterator c = m_connections.begin(); c != m_connections.end(); ++c) (*c)->prepare_buffers(); @@ -289,24 +290,24 @@ InputPort<MidiMessage>::prepare_buffers(size_t nframes) if (num_ins == 1) { // Buffer changed since connection if (m_buffers.at(0) != (*m_connections.begin())->buffer(0)) { - if (m_fixed_buffers || (m_is_tied && m_tied_port->fixed_buffers())) { + if (m_fixed_buffers) { // || (m_is_tied && m_tied_port->fixed_buffers())) { // can't change buffer, must copy do_mixdown = true; } else { // zero-copy assert(m_buffers.at(0)->is_joined()); m_buffers.at(0)->join((*m_connections.begin())->buffer(0)); - if (m_is_tied) - m_tied_port->buffer(0)->join(m_buffers.at(0)); + //if (m_is_tied) + // m_tied_port->buffer(0)->join(m_buffers.at(0)); do_mixdown = false; } update_buffers(); } else { do_mixdown = false; } - assert(!m_is_tied || m_tied_port != NULL); - assert(!m_is_tied || m_buffers.at(0)->data() == m_tied_port->buffer(0)->data()); - assert(!m_is_tied || m_buffers.at(0)->filled_size() == m_tied_port->buffer(0)->filled_size()); + //assert(!m_is_tied || m_tied_port != NULL); + //assert(!m_is_tied || m_buffers.at(0)->data() == m_tied_port->buffer(0)->data()); + //assert(!m_is_tied || m_buffers.at(0)->filled_size() == m_tied_port->buffer(0)->filled_size()); assert(do_mixdown || m_buffers.at(0)->filled_size() == (*m_connections.begin())->src_port()->buffer(0)->filled_size()); } @@ -318,8 +319,8 @@ InputPort<MidiMessage>::prepare_buffers(size_t nframes) m_buffers.at(0)->filled_size( (*m_connections.begin())->src_port()->buffer(0)->filled_size()); - if (m_is_tied) - m_tied_port->buffer(0)->filled_size(m_buffers.at(0)->filled_size()); + //if (m_is_tied) + // m_tied_port->buffer(0)->filled_size(m_buffers.at(0)->filled_size()); assert(m_buffers.at(0)->filled_size() == (*m_connections.begin())->src_port()->buffer(0)->filled_size()); @@ -329,7 +330,7 @@ InputPort<MidiMessage>::prepare_buffers(size_t nframes) } } - assert(!m_is_tied || m_buffers.at(0)->data() == m_tied_port->buffer(0)->data()); + //assert(!m_is_tied || m_buffers.at(0)->data() == m_tied_port->buffer(0)->data()); if (!do_mixdown || m_buffers.at(0)->filled_size() == 0 || num_ins == 0) return; @@ -337,8 +338,8 @@ InputPort<MidiMessage>::prepare_buffers(size_t nframes) //cerr << path() << " - Copying MIDI buffer" << endl; // Be sure buffers are the same as tied port's, if joined - assert(!m_is_tied || m_tied_port != NULL); - assert(!m_is_tied || m_buffers.at(0)->data() == m_tied_port->buffer(0)->data()); + //assert(!m_is_tied || m_tied_port != NULL); + //assert(!m_is_tied || m_buffers.at(0)->data() == m_tied_port->buffer(0)->data()); if (num_ins > 0) for (size_t i=0; i < m_buffers.at(0)->filled_size(); ++i) diff --git a/src/libs/engine/InputPort.h b/src/libs/engine/InputPort.h index 8c677b26..60e96167 100644 --- a/src/libs/engine/InputPort.h +++ b/src/libs/engine/InputPort.h @@ -27,7 +27,7 @@ using std::string; namespace Om { -template <typename T> class ConnectionBase; +template <typename T> class TypedConnection; template <typename T> class OutputPort; class Node; @@ -44,16 +44,16 @@ class Node; * \ingroup engine */ template <typename T> -class InputPort : public TypedPort<T> +class InputPort : virtual public TypedPort<T> { public: InputPort(Node* parent, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size); virtual ~InputPort() {} - void add_connection(ListNode<ConnectionBase<T>*>* const c); - ListNode<ConnectionBase<T>*>* remove_connection(const OutputPort<T>* const src_port); + void add_connection(ListNode<TypedConnection<T>*>* const c); + ListNode<TypedConnection<T>*>* remove_connection(const OutputPort<T>* const src_port); - const List<ConnectionBase<T>*>& connections() { return m_connections; } + const List<TypedConnection<T>*>& connections() { return m_connections; } void prepare_buffers(size_t nframes); @@ -72,11 +72,11 @@ private: void update_buffers(); - List<ConnectionBase<T>*> m_connections; + List<TypedConnection<T>*> m_connections; // This is just stupid... - using TypedPort<T>::m_is_tied; - using TypedPort<T>::m_tied_port; + //using TypedPort<T>::m_is_tied; + //using TypedPort<T>::m_tied_port; using TypedPort<T>::m_buffers; using TypedPort<T>::_poly; using TypedPort<T>::_index; diff --git a/src/libs/engine/JackAudioDriver.cpp b/src/libs/engine/JackAudioDriver.cpp index e6ef502e..5fc786f2 100644 --- a/src/libs/engine/JackAudioDriver.cpp +++ b/src/libs/engine/JackAudioDriver.cpp @@ -32,7 +32,7 @@ #include "Port.h" #include "MidiDriver.h" #include "List.h" -#include "TypedPort.h" +#include "DuplexPort.h" #ifdef HAVE_LASH #include "LashDriver.h" #endif @@ -45,7 +45,7 @@ namespace Om { //// JackAudioPort //// -JackAudioPort::JackAudioPort(JackAudioDriver* driver, TypedPort<sample>* patch_port) +JackAudioPort::JackAudioPort(JackAudioDriver* driver, DuplexPort<sample>* patch_port) : DriverPort(), ListNode<JackAudioPort*>(this), m_driver(driver), @@ -53,7 +53,7 @@ JackAudioPort::JackAudioPort(JackAudioDriver* driver, TypedPort<sample>* patch_p m_jack_buffer(NULL), m_patch_port(patch_port) { - assert(patch_port->tied_port() != NULL); + //assert(patch_port->tied_port() != NULL); assert(patch_port->poly() == 1); m_jack_port = jack_port_register(m_driver->jack_client(), @@ -93,17 +93,17 @@ JackAudioPort::prepare_buffer(jack_nframes_t nframes) m_jack_buffer->set_data((jack_default_audio_sample_t*) jack_port_get_buffer(m_jack_port, nframes)); - assert(m_patch_port->tied_port() != NULL); + //assert(m_patch_port->tied_port() != NULL); // FIXME: fixed_buffers switch on/off thing can be removed once this shit // gets figured out and assertions can go away m_patch_port->fixed_buffers(false); m_patch_port->buffer(0)->join(m_jack_buffer); - m_patch_port->tied_port()->buffer(0)->join(m_jack_buffer); + //m_patch_port->tied_port()->buffer(0)->join(m_jack_buffer); m_patch_port->fixed_buffers(true); - assert(m_patch_port->buffer(0)->data() == m_patch_port->tied_port()->buffer(0)->data()); + //assert(m_patch_port->buffer(0)->data() == m_patch_port->tied_port()->buffer(0)->data()); assert(m_patch_port->buffer(0)->data() == m_jack_buffer->data()); } @@ -241,7 +241,7 @@ JackAudioDriver::remove_port(JackAudioPort* port) DriverPort* -JackAudioDriver::create_port(TypedPort<sample>* patch_port) +JackAudioDriver::create_port(DuplexPort<sample>* patch_port) { if (patch_port->buffer_size() == m_buffer_size) return new JackAudioPort(this, patch_port); diff --git a/src/libs/engine/JackAudioDriver.h b/src/libs/engine/JackAudioDriver.h index a01624ed..abb74825 100644 --- a/src/libs/engine/JackAudioDriver.h +++ b/src/libs/engine/JackAudioDriver.h @@ -27,7 +27,7 @@ namespace Om { class Patch; class Port; -template <typename T> class TypedPort; +template <typename T> class DuplexPort; class JackAudioDriver; typedef jack_default_audio_sample_t jack_sample_t; @@ -39,7 +39,7 @@ typedef jack_default_audio_sample_t jack_sample_t; class JackAudioPort : public DriverPort, public ListNode<JackAudioPort*> { public: - JackAudioPort(JackAudioDriver* driver, TypedPort<sample>* patch_port); + JackAudioPort(JackAudioDriver* driver, DuplexPort<sample>* patch_port); ~JackAudioPort(); void add_to_driver(); @@ -51,7 +51,7 @@ public: jack_port_t* jack_port() const { return m_jack_port; } DriverBuffer<sample>* buffer() const { return m_jack_buffer; } void jack_buffer(jack_sample_t* s) { m_jack_buffer->set_data(s); } - TypedPort<sample>* patch_port() const { return m_patch_port; } + DuplexPort<sample>* patch_port() const { return m_patch_port; } private: // Prevent copies (undefined) @@ -61,7 +61,7 @@ private: JackAudioDriver* m_driver; jack_port_t* m_jack_port; DriverBuffer<sample>* m_jack_buffer; - TypedPort<sample>* m_patch_port; + DuplexPort<sample>* m_patch_port; }; @@ -88,7 +88,7 @@ public: void process_events(jack_nframes_t block_start, jack_nframes_t block_end); - DriverPort* create_port(TypedPort<sample>* patch_port); + DriverPort* create_port(DuplexPort<sample>* patch_port); Patch* root_patch() { return m_root_patch; } void set_root_patch(Patch* patch) { m_root_patch = patch; } diff --git a/src/libs/engine/JackMidiDriver.cpp b/src/libs/engine/JackMidiDriver.cpp index f55f0422..7c9ca9f4 100644 --- a/src/libs/engine/JackMidiDriver.cpp +++ b/src/libs/engine/JackMidiDriver.cpp @@ -26,7 +26,7 @@ #include "Maid.h" #include "AudioDriver.h" #include "MidiMessage.h" -#include "TypedPort.h" +#include "DuplexPort.h" #ifdef HAVE_LASH #include "LashDriver.h" #endif @@ -37,7 +37,7 @@ namespace Om { //// JackMidiPort //// -JackMidiPort::JackMidiPort(JackMidiDriver* driver, TypedPort<MidiMessage>* patch_port) +JackMidiPort::JackMidiPort(JackMidiDriver* driver, DuplexPort<MidiMessage>* patch_port) : DriverPort(), ListNode<JackMidiPort*>(this), m_driver(driver), @@ -115,7 +115,7 @@ JackMidiPort::prepare_block(const samplecount block_start, const samplecount blo //cerr << "Jack MIDI got " << event_count << " events." << endl; m_patch_port->buffer(0)->filled_size(event_count); - m_patch_port->tied_port()->buffer(0)->filled_size(event_count); + //m_patch_port->tied_port()->buffer(0)->filled_size(event_count); } diff --git a/src/libs/engine/JackMidiDriver.h b/src/libs/engine/JackMidiDriver.h index 33b4a0e1..f080833c 100644 --- a/src/libs/engine/JackMidiDriver.h +++ b/src/libs/engine/JackMidiDriver.h @@ -29,7 +29,7 @@ namespace Om { class Node; class SetPortValueEvent; class JackMidiDriver; -template <typename T> class TypedPort; +template <typename T> class DuplexPort; /** Representation of an JACK MIDI port. @@ -39,7 +39,7 @@ template <typename T> class TypedPort; class JackMidiPort : public DriverPort, public ListNode<JackMidiPort*> { public: - JackMidiPort(JackMidiDriver* driver, TypedPort<MidiMessage>* port); + JackMidiPort(JackMidiDriver* driver, DuplexPort<MidiMessage>* port); virtual ~JackMidiPort(); void prepare_block(const samplecount block_start, const samplecount block_end); @@ -48,16 +48,16 @@ public: void remove_from_driver(); void set_name(const string& name) { jack_port_set_name(m_jack_port, name.c_str()); }; - TypedPort<MidiMessage>* patch_port() const { return m_patch_port; } + DuplexPort<MidiMessage>* patch_port() const { return m_patch_port; } private: // Prevent copies (undefined) JackMidiPort(const JackMidiPort&); JackMidiPort& operator=(const JackMidiPort&); - JackMidiDriver* m_driver; - jack_port_t* m_jack_port; - TypedPort<MidiMessage>* m_patch_port; + JackMidiDriver* m_driver; + jack_port_t* m_jack_port; + DuplexPort<MidiMessage>* m_patch_port; }; @@ -84,7 +84,7 @@ public: void prepare_block(const samplecount block_start, const samplecount block_end); - JackMidiPort* create_port(TypedPort<MidiMessage>* patch_port) + JackMidiPort* create_port(DuplexPort<MidiMessage>* patch_port) { return new JackMidiPort(this, patch_port); } jack_client_t* jack_client() { return m_client; } diff --git a/src/libs/engine/Makefile.am b/src/libs/engine/Makefile.am index 09098e10..56b7724c 100644 --- a/src/libs/engine/Makefile.am +++ b/src/libs/engine/Makefile.am @@ -47,6 +47,8 @@ libom_la_SOURCES = \ InputPort.cpp \ OutputPort.h \ OutputPort.cpp \ + DuplexPort.h \ + DuplexPort.cpp \ MidiMessage.h \ MidiNoteNode.h \ MidiNoteNode.cpp \ @@ -76,8 +78,8 @@ libom_la_SOURCES = \ PostProcessor.cpp \ Connection.h \ Connection.cpp \ - ConnectionBase.h \ - ConnectionBase.cpp \ + TypedConnection.h \ + TypedConnection.cpp \ ObjectStore.h \ ObjectStore.cpp \ TransportNode.h \ diff --git a/src/libs/engine/MidiDriver.h b/src/libs/engine/MidiDriver.h index ed9d6e18..b037d52b 100644 --- a/src/libs/engine/MidiDriver.h +++ b/src/libs/engine/MidiDriver.h @@ -66,7 +66,7 @@ public: void enable() {} void disable() {} - DriverPort* create_port(TypedPort<MidiMessage>* patch_port) { return NULL; } + DriverPort* create_port(DuplexPort<MidiMessage>* patch_port) { return NULL; } void prepare_block(const samplecount block_start, const samplecount block_end) {} }; diff --git a/src/libs/engine/ObjectSender.cpp b/src/libs/engine/ObjectSender.cpp index 567beabe..354820f7 100644 --- a/src/libs/engine/ObjectSender.cpp +++ b/src/libs/engine/ObjectSender.cpp @@ -72,7 +72,7 @@ ObjectSender::send_patch(ClientInterface* client, const Patch* patch) // Control port, send value if (port->type() == DataType::FLOAT && port->buffer_size() == 1) - client->control_change(port->path(), ((TypedPort<sample>*)port)->buffer(0)->value_at(0)); + client->control_change(port->path(), dynamic_cast<TypedPort<sample>*>(port)->buffer(0)->value_at(0)); } // Send metadata diff --git a/src/libs/engine/OutputPort.cpp b/src/libs/engine/OutputPort.cpp index 35cb84b4..d713726a 100644 --- a/src/libs/engine/OutputPort.cpp +++ b/src/libs/engine/OutputPort.cpp @@ -28,22 +28,22 @@ OutputPort<T>::OutputPort(Node* parent, const string& name, size_t index, size_t template OutputPort<sample>::OutputPort(Node* parent, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size); template OutputPort<MidiMessage>::OutputPort(Node* parent, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size); - +#if 0 template<typename T> void OutputPort<T>::set_tied_port(InputPort<T>* port) { - assert(!m_is_tied); - assert(m_tied_port == NULL); + //assert(!m_is_tied); + //assert(m_tied_port == NULL); assert(static_cast<TypedPort<T>*>(port) != static_cast<TypedPort<T>*>(this)); assert(port != NULL); - m_is_tied = true; - m_tied_port = (TypedPort<T>*)port; + //m_is_tied = true; + //m_tied_port = (TypedPort<T>*)port; } template void OutputPort<sample>::set_tied_port(InputPort<sample>* port); template void OutputPort<MidiMessage>::set_tied_port(InputPort<MidiMessage>* port); - +#endif } // namespace Om diff --git a/src/libs/engine/OutputPort.h b/src/libs/engine/OutputPort.h index 269a4524..25a03325 100644 --- a/src/libs/engine/OutputPort.h +++ b/src/libs/engine/OutputPort.h @@ -39,7 +39,7 @@ template <typename T> class InputPort; * \ingroup engine */ template <typename T> -class OutputPort : public TypedPort<T> +class OutputPort : virtual public TypedPort<T> { public: OutputPort(Node* parent, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size); @@ -55,8 +55,8 @@ private: OutputPort(const OutputPort& copy); OutputPort<T>& operator=(const OutputPort<T>&); - using TypedPort<T>::m_is_tied; - using TypedPort<T>::m_tied_port; + //using TypedPort<T>::m_is_tied; + //using TypedPort<T>::m_tied_port; }; diff --git a/src/libs/engine/Patch.cpp b/src/libs/engine/Patch.cpp index b24377e0..7d22c673 100644 --- a/src/libs/engine/Patch.cpp +++ b/src/libs/engine/Patch.cpp @@ -30,6 +30,7 @@ #include "ObjectStore.h" #include "InputPort.h" #include "OutputPort.h" +#include "DuplexPort.h" #include "interface/ClientInterface.h" using std::cerr; using std::cout; using std::endl; @@ -45,8 +46,8 @@ Patch::Patch(const string& path, size_t poly, Patch* parent, samplerate srate, s { assert(internal_poly >= 1); - _plugin.plug_label("om_patch"); - _plugin.name("Om Patch"); + //_plugin->plug_label("om_patch"); + //_plugin->name("Om Patch"); //std::cerr << "Creating patch " << _name << ", poly = " << poly // << ", internal poly = " << internal_poly << std::endl; @@ -110,10 +111,8 @@ Patch::process(bool p) assert((*i)->as_port() != NULL); if ((*i)->as_port()->port_info()->is_output()) (*i)->as_port()->clear_buffers();*/ - for (List<Port*>::iterator i = _patch_ports.begin(); i != _patch_ports.end(); ++i) { - if ((*i)->is_output()) - (*i)->clear_buffers(); - } + for (List<Port*>::iterator i = _output_ports.begin(); i != _output_ports.end(); ++i) + (*i)->clear_buffers(); } _process = p; } @@ -132,9 +131,8 @@ Patch::run(size_t nframes) // FIXME: This is far too slow, too much checking every cycle // Prepare input ports for nodes to consume - for (List<Port*>::iterator i = _patch_ports.begin(); i != _patch_ports.end(); ++i) - if ((*i)->is_input()) - (*i)->prepare_buffers(nframes); + for (List<Port*>::iterator i = _input_ports.begin(); i != _input_ports.end(); ++i) + (*i)->prepare_buffers(nframes); // Run all nodes (consume input ports) for (size_t i=0; i < _process_order->size(); ++i) { @@ -145,7 +143,7 @@ Patch::run(size_t nframes) } // Prepare output ports (for caller to consume) - for (List<Port*>::iterator i = _patch_ports.begin(); i != _patch_ports.end(); ++i) + for (List<Port*>::iterator i = _output_ports.begin(); i != _output_ports.end(); ++i) if ((*i)->is_output()) (*i)->prepare_buffers(nframes); } @@ -299,10 +297,11 @@ Patch::create_port(const string& name, DataType type, size_t buffer_size, bool i assert( !(type == DataType::UNKNOWN) ); - if (is_output) - return new OutputPort<MidiMessage>(this, name, 0, _poly, type, buffer_size); - else - return new InputPort<MidiMessage>(this, name, 0, _poly, type, buffer_size); + // FIXME: is it possible to just "pass" the type directly as the template parameter somehow? + if (type == DataType::FLOAT) + return new DuplexPort<sample>(this, name, 0, _poly, type, buffer_size, is_output); + else if (type == DataType::MIDI) + return new DuplexPort<MidiMessage>(this, name, 0, _poly, type, buffer_size, is_output); } @@ -313,9 +312,17 @@ Patch::remove_port(const Port* port) { bool found = false; ListNode<Port*>* ret = NULL; - for (List<Port*>::iterator i = _patch_ports.begin(); i != _patch_ports.end(); ++i) { + for (List<Port*>::iterator i = _input_ports.begin(); i != _input_ports.end(); ++i) { + if ((*i) == port) { + ret = _input_ports.remove(i); + found = true; + } + } + + if (!found) + for (List<Port*>::iterator i = _output_ports.begin(); i != _output_ports.end(); ++i) { if ((*i) == port) { - ret = _patch_ports.remove(i); + ret = _output_ports.remove(i); found = true; } } @@ -347,7 +354,7 @@ Patch::build_process_order() const (*i)->traversed(false); // Traverse backwards starting at outputs - for (List<Port*>::const_iterator p = _patch_ports.begin(); p != _patch_ports.end(); ++p) { + for (List<Port*>::const_iterator p = _output_ports.begin(); p != _output_ports.end(); ++p) { /*const Port* const port = (*p); if (port->port_info()->is_output()) { for (List<Connection*>::const_iterator c = port->connections().begin(); diff --git a/src/libs/engine/Patch.h b/src/libs/engine/Patch.h index edde636e..f0e06368 100644 --- a/src/libs/engine/Patch.h +++ b/src/libs/engine/Patch.h @@ -74,10 +74,9 @@ public: const List<Node*>& nodes() const { return _nodes; } const List<Connection*>& connections() const { return _connections; } - //void add_bridge_node(ListNode<InternalNode*>* n) { _bridge_nodes.push_back(n); } - //ListNode<InternalNode*>* remove_bridge_node(const InternalNode* n); Port* create_port(const string& name, DataType type, size_t buffer_size, bool is_output); - void add_port(ListNode<Port*>* port) { _patch_ports.push_back(port); } + void add_input(ListNode<Port*>* port) { _input_ports.push_back(port); } ///< Preprocesser thread + void add_output(ListNode<Port*>* port) { _output_ports.push_back(port); } ///< Preprocessor thread ListNode<Port*>* remove_port(const Port* p); void add_connection(ListNode<Connection*>* c) { _connections.push_back(c); } @@ -96,8 +95,6 @@ public: void process(bool p); size_t internal_poly() const { return _internal_poly; } - - const Plugin* plugin() const { return &_plugin; } private: // Prevent copies (undefined) @@ -109,11 +106,10 @@ private: size_t _internal_poly; Array<Node*>* _process_order; ///< Accessed in audio thread only List<Connection*> _connections; ///< Accessed in audio thread only - List<Port*> _patch_ports; ///< Accessed in preprocessing thread only + List<Port*> _input_ports; ///< Accessed in preprocessing thread only + List<Port*> _output_ports; ///< Accessed in preprocessing thread only List<Node*> _nodes; ///< Accessed in preprocessing thread only bool _process; - - Plugin _plugin; }; diff --git a/src/libs/engine/ConnectionBase.cpp b/src/libs/engine/TypedConnection.cpp index c8936818..ccfd36a1 100644 --- a/src/libs/engine/ConnectionBase.cpp +++ b/src/libs/engine/TypedConnection.cpp @@ -14,7 +14,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "ConnectionBase.h" +#include "TypedConnection.h" #include "util.h" #include "InputPort.h" #include "OutputPort.h" @@ -31,7 +31,7 @@ namespace Om { * user (InputPort). */ template <typename T> -ConnectionBase<T>::ConnectionBase(OutputPort<T>* const src_port, InputPort<T>* const dst_port) +TypedConnection<T>::TypedConnection(OutputPort<T>* const src_port, InputPort<T>* const dst_port) : Connection(src_port, dst_port), m_local_buffer(NULL), m_is_poly_to_mono( (src_port->parent_node()->poly() > dst_port->parent_node()->poly()) ), @@ -44,22 +44,22 @@ ConnectionBase<T>::ConnectionBase(OutputPort<T>* const src_port, InputPort<T>* c if (m_is_poly_to_mono) // Poly -> Mono connection, need a buffer to mix in to m_local_buffer = new Buffer<T>(m_buffer_size); } -template ConnectionBase<sample>::ConnectionBase(OutputPort<sample>* const src_port, InputPort<sample>* const dst_port); -template ConnectionBase<MidiMessage>::ConnectionBase(OutputPort<MidiMessage>* const src_port, InputPort<MidiMessage>* const dst_port); +template TypedConnection<sample>::TypedConnection(OutputPort<sample>* const src_port, InputPort<sample>* const dst_port); +template TypedConnection<MidiMessage>::TypedConnection(OutputPort<MidiMessage>* const src_port, InputPort<MidiMessage>* const dst_port); template <typename T> -ConnectionBase<T>::~ConnectionBase() +TypedConnection<T>::~TypedConnection() { delete m_local_buffer; } -template ConnectionBase<sample>::~ConnectionBase(); -template ConnectionBase<MidiMessage>::~ConnectionBase(); +template TypedConnection<sample>::~TypedConnection(); +template TypedConnection<MidiMessage>::~TypedConnection(); template <typename sample> void -ConnectionBase<sample>::prepare_buffers() +TypedConnection<sample>::prepare_buffers() { /* Thought: A poly output port can be connected to multiple mono input * ports, which means this mix down would have to happen many times. @@ -81,13 +81,13 @@ ConnectionBase<sample>::prepare_buffers() m_local_buffer->scale(1.0f/(float)src_port()->poly(), 0, m_buffer_size-1); } } -template void ConnectionBase<sample>::prepare_buffers(); +template void TypedConnection<sample>::prepare_buffers(); // FIXME: MIDI mixing not implemented template <> void -ConnectionBase<MidiMessage>::prepare_buffers() +TypedConnection<MidiMessage>::prepare_buffers() { } diff --git a/src/libs/engine/ConnectionBase.h b/src/libs/engine/TypedConnection.h index 80d7bd84..953c77e9 100644 --- a/src/libs/engine/ConnectionBase.h +++ b/src/libs/engine/TypedConnection.h @@ -14,8 +14,8 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef CONNECTIONBASE_H -#define CONNECTIONBASE_H +#ifndef TYPEDCONNECTION_H +#define TYPEDCONNECTION_H #include "types.h" #include "OutputPort.h" @@ -33,23 +33,23 @@ template <typename T> class InputPort; * \ingroup engine */ template <typename T> -class ConnectionBase : public Connection +class TypedConnection : public Connection { public: - ConnectionBase(OutputPort<T>* const src_port, InputPort<T>* const dst_port); - virtual ~ConnectionBase(); + TypedConnection(OutputPort<T>* const src_port, InputPort<T>* const dst_port); + virtual ~TypedConnection(); void prepare_buffers(); - inline OutputPort<T>* src_port() const { return (OutputPort<T>*)m_src_port; } - inline InputPort<T>* dst_port() const { return (InputPort<T>*)m_dst_port; } + inline OutputPort<T>* src_port() const { return dynamic_cast<OutputPort<T>*>(m_src_port); } + inline InputPort<T>* dst_port() const { return dynamic_cast<InputPort<T>*>(m_dst_port); } /** Used by some (recursive) events to prevent double disconnections */ bool pending_disconnection() { return m_pending_disconnection; } void pending_disconnection(bool b) { m_pending_disconnection = b; } /** Get the buffer for a particular voice. - * A ConnectionBase is smart - it knows the destination port respondering the + * A TypedConnection is smart - it knows the destination port respondering the * buffer, and will return accordingly (ie the same buffer for every voice * in a mono->poly connection). */ @@ -57,8 +57,8 @@ public: private: // Disallow copies (undefined) - ConnectionBase(const ConnectionBase& copy); - ConnectionBase& operator=(const ConnectionBase&); + TypedConnection(const TypedConnection& copy); + TypedConnection& operator=(const TypedConnection&); Buffer<T>* m_local_buffer; ///< Only used for poly->mono connections bool m_is_poly_to_mono; @@ -69,7 +69,7 @@ private: template <> inline Buffer<sample>* -ConnectionBase<sample>::buffer(size_t voice) const +TypedConnection<sample>::buffer(size_t voice) const { TypedPort<sample>* const src_port = (TypedPort<sample>*)m_src_port; @@ -86,7 +86,7 @@ ConnectionBase<sample>::buffer(size_t voice) const template <> inline Buffer<MidiMessage>* -ConnectionBase<MidiMessage>::buffer(size_t voice) const +TypedConnection<MidiMessage>::buffer(size_t voice) const { // No such thing as polyphonic MIDI ports assert(m_src_port->poly() == 1); @@ -97,9 +97,9 @@ ConnectionBase<MidiMessage>::buffer(size_t voice) const } -template class ConnectionBase<sample>; -template class ConnectionBase<MidiMessage>; +template class TypedConnection<sample>; +template class TypedConnection<MidiMessage>; } // namespace Om -#endif // CONNECTIONBASE_H +#endif // TYPEDCONNECTION_H diff --git a/src/libs/engine/TypedPort.cpp b/src/libs/engine/TypedPort.cpp index 0ebb05eb..4fb1dfa7 100644 --- a/src/libs/engine/TypedPort.cpp +++ b/src/libs/engine/TypedPort.cpp @@ -31,10 +31,10 @@ namespace Om { */ template <typename T> TypedPort<T>::TypedPort(Node* parent, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size) -: Port(parent, name, index, poly, type, buffer_size), - m_fixed_buffers(false), - m_is_tied(false), - m_tied_port(NULL) +: Port(parent, name, index, poly, type, buffer_size) +, m_fixed_buffers(false) +/*, m_is_tied(false) +, m_tied_port(NULL)*/ { allocate_buffers(); clear_buffers(); diff --git a/src/libs/engine/TypedPort.h b/src/libs/engine/TypedPort.h index e2ccaff4..332741a6 100644 --- a/src/libs/engine/TypedPort.h +++ b/src/libs/engine/TypedPort.h @@ -14,8 +14,8 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef PORTBASE_H -#define PORTBASE_H +#ifndef TYPEDPORT_H +#define TYPEDPORT_H #include <string> #include "types.h" @@ -52,8 +52,8 @@ public: virtual void prepare_buffers(size_t nframes); virtual void clear_buffers(); - TypedPort* tied_port() const { return m_tied_port; } - void untie() { m_is_tied = false; m_tied_port = NULL; } + //TypedPort* tied_port() const { return m_tied_port; } + //void untie() { m_is_tied = false; m_tied_port = NULL; } /** Used by drivers to prevent port from changing buffers */ void fixed_buffers(bool b) { m_fixed_buffers = b; } @@ -68,9 +68,9 @@ protected: void allocate_buffers(); - bool m_fixed_buffers; - bool m_is_tied; - TypedPort* m_tied_port; + bool m_fixed_buffers; + //bool m_is_tied; + //TypedPort* m_tied_port; Array<Buffer<T>*> m_buffers; }; @@ -81,4 +81,4 @@ template class TypedPort<MidiMessage>; } // namespace Om -#endif // PORTBASE_H +#endif // TYPEDPORT_H diff --git a/src/libs/engine/events/ConnectionEvent.cpp b/src/libs/engine/events/ConnectionEvent.cpp index fcfa3bbc..1d5b3ba1 100644 --- a/src/libs/engine/events/ConnectionEvent.cpp +++ b/src/libs/engine/events/ConnectionEvent.cpp @@ -19,7 +19,7 @@ #include "Responder.h" #include "Om.h" #include "OmApp.h" -#include "ConnectionBase.h" +#include "TypedConnection.h" #include "InputPort.h" #include "OutputPort.h" #include "Patch.h" @@ -58,7 +58,9 @@ ConnectionEvent::~ConnectionEvent() void ConnectionEvent::pre_process() { - if (m_src_port_path.parent().parent() != m_dst_port_path.parent().parent()) { + if (m_src_port_path.parent().parent() != m_dst_port_path.parent().parent() + && m_src_port_path.parent() != m_dst_port_path.parent().parent() + && m_src_port_path.parent().parent() != m_dst_port_path.parent()) { m_error = PARENT_PATCH_DIFFERENT; QueuedEvent::pre_process(); return; @@ -72,22 +74,22 @@ ConnectionEvent::pre_process() return; }*/ - Port* port1 = om->object_store()->find_port(m_src_port_path); - Port* port2 = om->object_store()->find_port(m_dst_port_path); + m_src_port = om->object_store()->find_port(m_src_port_path); + m_dst_port = om->object_store()->find_port(m_dst_port_path); - if (port1 == NULL || port2 == NULL) { + if (m_src_port == NULL || m_dst_port == NULL) { m_error = PORT_NOT_FOUND; QueuedEvent::pre_process(); return; } - if (port1->type() != port2->type()) { + if (m_src_port->type() != m_dst_port->type() || m_src_port->buffer_size() != m_dst_port->buffer_size()) { m_error = TYPE_MISMATCH; QueuedEvent::pre_process(); return; } - if (port1->is_output() && port2->is_input()) { + /*if (port1->is_output() && port2->is_input()) { m_src_port = port1; m_dst_port = port2; } else if (port2->is_output() && port1->is_input()) { @@ -97,16 +99,16 @@ ConnectionEvent::pre_process() m_error = TYPE_MISMATCH; QueuedEvent::pre_process(); return; - } + }*/ // Create the typed event to actually do the work - const DataType type = port1->type(); + const DataType type = m_src_port->type(); if (type == DataType::FLOAT) { m_typed_event = new TypedConnectionEvent<sample>(m_responder, - (OutputPort<sample>*)m_src_port, (InputPort<sample>*)m_dst_port); + dynamic_cast<OutputPort<sample>*>(m_src_port), dynamic_cast<InputPort<sample>*>(m_dst_port)); } else if (type == DataType::MIDI) { m_typed_event = new TypedConnectionEvent<MidiMessage>(m_responder, - (OutputPort<MidiMessage>*)m_src_port, (InputPort<MidiMessage>*)m_dst_port); + dynamic_cast<OutputPort<MidiMessage>*>(m_src_port), dynamic_cast<InputPort<MidiMessage>*>(m_dst_port)); } else { m_error = TYPE_MISMATCH; QueuedEvent::pre_process(); @@ -177,23 +179,37 @@ TypedConnectionEvent<T>::pre_process() { Node* const src_node = m_src_port->parent_node(); Node* const dst_node = m_dst_port->parent_node(); - - m_patch = src_node->parent_patch(); + + if (src_node->parent_patch() != dst_node->parent_patch()) { + // Connection to a patch port from inside the patch + assert(src_node->parent() == dst_node || dst_node->parent() == src_node); + if (src_node->parent() == dst_node) + m_patch = dynamic_cast<Patch*>(dst_node); + else + m_patch = dynamic_cast<Patch*>(src_node); + } else { + // Normal connection between nodes with the same parent + m_patch = src_node->parent_patch(); + } + + assert(m_patch); if (src_node == NULL || dst_node == NULL) { + cerr << "ERR 1\n"; m_succeeded = false; QueuedEvent::pre_process(); return; } - if (src_node->parent() != m_patch || dst_node->parent() != m_patch) { + if (src_node->parent() != m_patch && dst_node->parent() != m_patch) { + cerr << "ERR 2\n"; m_succeeded = false; QueuedEvent::pre_process(); return; } - m_connection = new ConnectionBase<T>(m_src_port, m_dst_port); - m_port_listnode = new ListNode<ConnectionBase<T>*>(m_connection); + m_connection = new TypedConnection<T>(m_src_port, m_dst_port); + m_port_listnode = new ListNode<TypedConnection<T>*>(m_connection); m_patch_listnode = new ListNode<Connection*>(m_connection); dst_node->providers()->push_back(new ListNode<Node*>(src_node)); diff --git a/src/libs/engine/events/ConnectionEvent.h b/src/libs/engine/events/ConnectionEvent.h index 369a3903..e2a50d53 100644 --- a/src/libs/engine/events/ConnectionEvent.h +++ b/src/libs/engine/events/ConnectionEvent.h @@ -33,7 +33,7 @@ class Node; class Connection; class MidiMessage; class Port; -template <typename T> class ConnectionBase; +template <typename T> class TypedConnection; template <typename T> class InputPort; template <typename T> class OutputPort; template <typename T> class TypedConnectionEvent; // helper, defined below @@ -93,9 +93,9 @@ private: Patch* m_patch; Array<Node*>* m_process_order; ///< New process order for Patch - ConnectionBase<T>* m_connection; + TypedConnection<T>* m_connection; ListNode<Connection*>* m_patch_listnode; - ListNode<ConnectionBase<T>*>* m_port_listnode; + ListNode<TypedConnection<T>*>* m_port_listnode; bool m_succeeded; }; diff --git a/src/libs/engine/events/DisconnectNodeEvent.cpp b/src/libs/engine/events/DisconnectNodeEvent.cpp index 4c4e19a7..e430acc5 100644 --- a/src/libs/engine/events/DisconnectNodeEvent.cpp +++ b/src/libs/engine/events/DisconnectNodeEvent.cpp @@ -22,7 +22,7 @@ #include "Maid.h" #include "List.h" #include "Node.h" -#include "ConnectionBase.h" +#include "TypedConnection.h" #include "DisconnectionEvent.h" #include "Port.h" #include "Array.h" diff --git a/src/libs/engine/events/DisconnectNodeEvent.h b/src/libs/engine/events/DisconnectNodeEvent.h index a82fbaec..4bcbdf94 100644 --- a/src/libs/engine/events/DisconnectNodeEvent.h +++ b/src/libs/engine/events/DisconnectNodeEvent.h @@ -29,7 +29,7 @@ class DisconnectionEvent; class Patch; class Node; class Connection; -template <typename T> class ConnectionBase; +template <typename T> class TypedConnection; class Port; template <typename T> class InputPort; template <typename T> class OutputPort; diff --git a/src/libs/engine/events/DisconnectionEvent.cpp b/src/libs/engine/events/DisconnectionEvent.cpp index 0a3a4f7b..34570537 100644 --- a/src/libs/engine/events/DisconnectionEvent.cpp +++ b/src/libs/engine/events/DisconnectionEvent.cpp @@ -19,7 +19,7 @@ #include "Responder.h" #include "Om.h" #include "OmApp.h" -#include "ConnectionBase.h" +#include "TypedConnection.h" #include "InputPort.h" #include "OutputPort.h" #include "Patch.h" @@ -124,10 +124,10 @@ DisconnectionEvent::pre_process() const DataType type = m_src_port->type(); if (type == DataType::FLOAT) { m_typed_event = new TypedDisconnectionEvent<sample>(m_responder, - (OutputPort<sample>*)m_src_port, (InputPort<sample>*)m_dst_port); + dynamic_cast<OutputPort<sample>*>(m_src_port), dynamic_cast<InputPort<sample>*>(m_dst_port)); } else if (type == DataType::MIDI) { m_typed_event = new TypedDisconnectionEvent<MidiMessage>(m_responder, - (OutputPort<MidiMessage>*)m_src_port, (InputPort<MidiMessage>*)m_dst_port); + dynamic_cast<OutputPort<MidiMessage>*>(m_src_port), dynamic_cast<InputPort<MidiMessage>*>(m_dst_port)); } else { m_error = TYPE_MISMATCH; QueuedEvent::pre_process(); @@ -250,7 +250,7 @@ TypedDisconnectionEvent<T>::execute(samplecount offset) { if (m_succeeded) { - ListNode<ConnectionBase<T>*>* const port_connection + ListNode<TypedConnection<T>*>* const port_connection = m_dst_port->remove_connection(m_src_port); if (port_connection != NULL) { diff --git a/src/libs/engine/events/DisconnectionEvent.h b/src/libs/engine/events/DisconnectionEvent.h index 77d4aabe..445815dd 100644 --- a/src/libs/engine/events/DisconnectionEvent.h +++ b/src/libs/engine/events/DisconnectionEvent.h @@ -33,7 +33,7 @@ class Node; class Connection; class MidiMessage; class Port; -template <typename T> class ConnectionBase; +template <typename T> class TypedConnection; template <typename T> class InputPort; template <typename T> class OutputPort; template <typename T> class TypedDisconnectionEvent; // helper, defined below diff --git a/src/progs/gtk/PatchController.cpp b/src/progs/gtk/PatchController.cpp index d9b22e35..ae604bae 100644 --- a/src/progs/gtk/PatchController.cpp +++ b/src/progs/gtk/PatchController.cpp @@ -390,10 +390,19 @@ PatchController::show_properties_window() void PatchController::create_connection(CountedPtr<ConnectionModel> cm) { + // Deal with messy anonymous nodes for this patch's own ports... + const Path& src_parent_path = cm->src_port_path().parent(); + const Path& dst_parent_path = cm->dst_port_path().parent(); + + const string& src_parent_name = + (src_parent_path == path()) ? "" : src_parent_path.name(); + const string& dst_parent_name = + (dst_parent_path == path()) ? "" : dst_parent_path.name(); + m_patch_view->canvas()->add_connection( - cm->src_port_path().parent().name(), + src_parent_name, cm->src_port_path().name(), - cm->dst_port_path().parent().name(), + dst_parent_name, cm->dst_port_path().name()); // Disable control slider from destination node control window |