diff options
Diffstat (limited to 'src/engine')
-rw-r--r-- | src/engine/LADSPANode.cpp | 16 | ||||
-rw-r--r-- | src/engine/LADSPANode.hpp | 4 | ||||
-rw-r--r-- | src/engine/LV2Node.cpp | 16 | ||||
-rw-r--r-- | src/engine/LV2Node.hpp | 4 | ||||
-rw-r--r-- | src/engine/MessageContext.cpp | 1 | ||||
-rw-r--r-- | src/engine/NodeBase.cpp | 280 | ||||
-rw-r--r-- | src/engine/NodeBase.hpp | 151 | ||||
-rw-r--r-- | src/engine/NodeImpl.hpp | 145 | ||||
-rw-r--r-- | src/engine/PatchImpl.cpp | 14 | ||||
-rw-r--r-- | src/engine/PatchImpl.hpp | 4 | ||||
-rw-r--r-- | src/engine/events/CreatePort.cpp | 2 | ||||
-rw-r--r-- | src/engine/events/Delete.cpp | 2 | ||||
-rw-r--r-- | src/engine/events/SetMetadata.cpp | 4 | ||||
-rw-r--r-- | src/engine/internals/Controller.cpp | 6 | ||||
-rw-r--r-- | src/engine/internals/Controller.hpp | 4 | ||||
-rw-r--r-- | src/engine/internals/Delay.cpp | 8 | ||||
-rw-r--r-- | src/engine/internals/Delay.hpp | 4 | ||||
-rw-r--r-- | src/engine/internals/Note.cpp | 10 | ||||
-rw-r--r-- | src/engine/internals/Note.hpp | 4 | ||||
-rw-r--r-- | src/engine/internals/Trigger.cpp | 6 | ||||
-rw-r--r-- | src/engine/internals/Trigger.hpp | 4 | ||||
-rw-r--r-- | src/engine/wscript | 2 |
22 files changed, 158 insertions, 533 deletions
diff --git a/src/engine/LADSPANode.cpp b/src/engine/LADSPANode.cpp index 66472f6a..ec793915 100644 --- a/src/engine/LADSPANode.cpp +++ b/src/engine/LADSPANode.cpp @@ -49,7 +49,7 @@ LADSPANode::LADSPANode(PluginImpl* plugin, PatchImpl* parent, const LADSPA_Descriptor* descriptor, SampleRate srate) - : NodeBase(plugin, path, polyphonic, parent, srate) + : NodeImpl(plugin, path, polyphonic, parent, srate) , _descriptor(descriptor) , _instances(NULL) , _prepared_instances(NULL) @@ -70,7 +70,7 @@ LADSPANode::prepare_poly(BufferFactory& bufs, uint32_t poly) if (!_polyphonic) poly = 1; - NodeBase::prepare_poly(bufs, poly); + NodeImpl::prepare_poly(bufs, poly); if (_polyphony == poly) return true; @@ -118,7 +118,7 @@ LADSPANode::apply_poly(Raul::Maid& maid, uint32_t poly) } assert(poly <= _instances->size()); - return NodeBase::apply_poly(maid, poly); + return NodeImpl::apply_poly(maid, poly); } @@ -243,7 +243,7 @@ LADSPANode::instantiate(BufferFactory& bufs) void LADSPANode::activate(BufferFactory& bufs) { - NodeBase::activate(bufs); + NodeImpl::activate(bufs); if (_descriptor->activate != NULL) for (uint32_t i = 0; i < _polyphony; ++i) @@ -254,7 +254,7 @@ LADSPANode::activate(BufferFactory& bufs) void LADSPANode::deactivate() { - NodeBase::deactivate(); + NodeImpl::deactivate(); for (uint32_t i = 0; i < _polyphony; ++i) if (_descriptor->deactivate != NULL) @@ -265,12 +265,12 @@ LADSPANode::deactivate() void LADSPANode::process(ProcessContext& context) { - NodeBase::pre_process(context); + NodeImpl::pre_process(context); for (uint32_t i = 0; i < _polyphony; ++i) _descriptor->run(instance(i), context.nframes()); - NodeBase::post_process(context); + NodeImpl::post_process(context); } @@ -278,7 +278,7 @@ void LADSPANode::set_port_buffer(uint32_t voice, uint32_t port_num, IntrusivePtr<Buffer> buf, SampleCount offset) { - NodeBase::set_port_buffer(voice, port_num, buf, offset); + NodeImpl::set_port_buffer(voice, port_num, buf, offset); _descriptor->connect_port(instance(voice), port_num, buf ? (LADSPA_Data*)buf->port_data(_ports->at(port_num)->type(), offset) : NULL); diff --git a/src/engine/LADSPANode.hpp b/src/engine/LADSPANode.hpp index ad2073c6..a246e2dc 100644 --- a/src/engine/LADSPANode.hpp +++ b/src/engine/LADSPANode.hpp @@ -23,7 +23,7 @@ #include <boost/optional.hpp> #include "raul/IntrusivePtr.hpp" #include "types.hpp" -#include "NodeBase.hpp" +#include "NodeImpl.hpp" #include "PluginImpl.hpp" namespace Ingen { @@ -33,7 +33,7 @@ namespace Ingen { * * \ingroup engine */ -class LADSPANode : public NodeBase +class LADSPANode : public NodeImpl { public: LADSPANode(PluginImpl* plugin, diff --git a/src/engine/LV2Node.cpp b/src/engine/LV2Node.cpp index a8892925..60bb2bbb 100644 --- a/src/engine/LV2Node.cpp +++ b/src/engine/LV2Node.cpp @@ -49,7 +49,7 @@ LV2Node::LV2Node(LV2Plugin* plugin, bool polyphonic, PatchImpl* parent, SampleRate srate) - : NodeBase(plugin, name, polyphonic, parent, srate) + : NodeImpl(plugin, name, polyphonic, parent, srate) , _lv2_plugin(plugin) , _instances(NULL) , _prepared_instances(NULL) @@ -71,7 +71,7 @@ LV2Node::prepare_poly(BufferFactory& bufs, uint32_t poly) if (!_polyphonic) poly = 1; - NodeBase::prepare_poly(bufs, poly); + NodeImpl::prepare_poly(bufs, poly); if (_polyphony == poly) return true; @@ -123,7 +123,7 @@ LV2Node::apply_poly(Raul::Maid& maid, uint32_t poly) } assert(poly <= _instances->size()); - return NodeBase::apply_poly(maid, poly); + return NodeImpl::apply_poly(maid, poly); } @@ -345,7 +345,7 @@ LV2Node::instantiate(BufferFactory& bufs) void LV2Node::activate(BufferFactory& bufs) { - NodeBase::activate(bufs); + NodeImpl::activate(bufs); for (uint32_t i = 0; i < _polyphony; ++i) slv2_instance_activate(instance(i)); @@ -355,7 +355,7 @@ LV2Node::activate(BufferFactory& bufs) void LV2Node::deactivate() { - NodeBase::deactivate(); + NodeImpl::deactivate(); for (uint32_t i = 0; i < _polyphony; ++i) slv2_instance_deactivate(instance(i)); @@ -382,12 +382,12 @@ LV2Node::message_run(MessageContext& context) void LV2Node::process(ProcessContext& context) { - NodeBase::pre_process(context); + NodeImpl::pre_process(context); for (uint32_t i = 0; i < _polyphony; ++i) slv2_instance_run(instance(i), context.nframes()); - NodeBase::post_process(context); + NodeImpl::post_process(context); } @@ -395,7 +395,7 @@ void LV2Node::set_port_buffer(uint32_t voice, uint32_t port_num, IntrusivePtr<Buffer> buf, SampleCount offset) { - NodeBase::set_port_buffer(voice, port_num, buf, offset); + NodeImpl::set_port_buffer(voice, port_num, buf, offset); slv2_instance_connect_port(instance(voice), port_num, buf ? buf->port_data(_ports->at(port_num)->type(), offset) : NULL); } diff --git a/src/engine/LV2Node.hpp b/src/engine/LV2Node.hpp index 8b7a7bc3..dd3ce1b3 100644 --- a/src/engine/LV2Node.hpp +++ b/src/engine/LV2Node.hpp @@ -23,7 +23,7 @@ #include "raul/IntrusivePtr.hpp" #include "contexts.lv2/contexts.h" #include "types.hpp" -#include "NodeBase.hpp" +#include "NodeImpl.hpp" #include "LV2Features.hpp" namespace Ingen { @@ -35,7 +35,7 @@ class LV2Plugin; * * \ingroup engine */ -class LV2Node : public NodeBase +class LV2Node : public NodeImpl { public: LV2Node(LV2Plugin* plugin, diff --git a/src/engine/MessageContext.cpp b/src/engine/MessageContext.cpp index 71700bbf..eec5acaa 100644 --- a/src/engine/MessageContext.cpp +++ b/src/engine/MessageContext.cpp @@ -15,6 +15,7 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "contexts.lv2/contexts.h" #include "raul/log.hpp" #include "raul/Atom.hpp" #include "ConnectionImpl.hpp" diff --git a/src/engine/NodeBase.cpp b/src/engine/NodeBase.cpp deleted file mode 100644 index 967f7d3c..00000000 --- a/src/engine/NodeBase.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/* This file is part of Ingen. - * Copyright (C) 2007-2009 Dave Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "NodeBase.hpp" -#include <cassert> -#include <stdint.h> -#include "raul/List.hpp" -#include "raul/Array.hpp" -#include "util.hpp" -#include "AudioBuffer.hpp" -#include "ClientBroadcaster.hpp" -#include "EngineStore.hpp" -#include "PatchImpl.hpp" -#include "PluginImpl.hpp" -#include "PortImpl.hpp" -#include "ThreadManager.hpp" - -using namespace std; - -namespace Ingen { - - -NodeBase::NodeBase(PluginImpl* plugin, const Raul::Symbol& symbol, bool polyphonic, PatchImpl* parent, SampleRate srate) - : NodeImpl(parent, symbol) - , _plugin(plugin) - , _polyphonic(polyphonic) - , _polyphony((polyphonic && parent) ? parent->internal_poly() : 1) - , _srate(srate) - , _valid_ports(NULL) - , _input_ready(1) - , _process_lock(0) - , _n_inputs_ready(0) - , _ports(NULL) - , _providers(new Raul::List<NodeImpl*>()) - , _dependants(new Raul::List<NodeImpl*>()) - , _activated(false) - , _traversed(false) -{ - assert(_plugin); - assert(_polyphony > 0); - assert(_parent == NULL || (_polyphony == parent->internal_poly() || _polyphony == 1)); -} - - -NodeBase::~NodeBase() -{ - if (_activated) - deactivate(); - - delete _providers; - delete _dependants; - delete _ports; - - free(_valid_ports); -} - - -Shared::Port* -NodeBase::port(uint32_t index) const -{ - return (*_ports)[index]; -} - - -const Shared::Plugin* -NodeBase::plugin() const -{ - return _plugin; -} - - -void -NodeBase::activate(BufferFactory& bufs) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - assert(!_activated); - _activated = true; - - for (unsigned long p = 0; p < num_ports(); ++p) { - PortImpl* const port = _ports->at(p); - port->setup_buffers(bufs, port->poly()); - port->connect_buffers(); - for (uint32_t v = 0; v < _polyphony; ++v) { - if (!port->buffer(v)) - continue; - if (port->type() == PortType::CONTROL) - ((AudioBuffer*)port->buffer(v).get())->set_value(port->value().get_float(), 0, 0); - else - port->buffer(v)->clear(); - } - } -} - - -void -NodeBase::deactivate() -{ - assert(_activated); - _activated = false; - for (uint32_t i = 0; i < _polyphony; ++i) { - for (unsigned long j = 0; j < num_ports(); ++j) { - PortImpl* const port = _ports->at(j); - if (port->is_output() && port->buffer(i)) - port->buffer(i)->clear(); - } - } -} - - -bool -NodeBase::prepare_poly(BufferFactory& bufs, uint32_t poly) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - - if (!_polyphonic) - poly = 1; - - for (size_t i = 0; i < _ports->size(); ++i) - _ports->at(i)->prepare_poly(bufs, poly); - - return true; -} - - -bool -NodeBase::apply_poly(Raul::Maid& maid, uint32_t poly) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - - if (!_polyphonic) - poly = 1; - - _polyphony = poly; - - for (size_t i = 0; i < num_ports(); ++i) - _ports->at(i)->apply_poly(maid, poly); - - return true; -} - - -void -NodeBase::set_buffer_size(Context& context, BufferFactory& bufs, PortType type, size_t size) -{ - if (_ports) - for (size_t i = 0; i < _ports->size(); ++i) - if (_ports->at(i)->type() == type && _ports->at(i)->context() == context.id()) - _ports->at(i)->set_buffer_size(context, bufs, size); -} - - -void -NodeBase::reset_input_ready() -{ - _n_inputs_ready = 0; - _process_lock = 0; - _input_ready.reset(0); -} - - -bool -NodeBase::process_lock() -{ - return _process_lock.compare_and_exchange(0, 1); -} - - -void -NodeBase::process_unlock() -{ - _process_lock = 0; -} - - -void -NodeBase::wait_for_input(size_t num_providers) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - assert(_process_lock.get() == 1); - - while ((unsigned)_n_inputs_ready.get() < num_providers) - _input_ready.wait(); -} - - -void -NodeBase::signal_input_ready() -{ - ThreadManager::assert_thread(THREAD_PROCESS); - ++_n_inputs_ready; - _input_ready.post(); -} - - -/** Prepare to run a cycle (in the audio thread) - */ -void -NodeBase::pre_process(Context& context) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - - // Mix down input ports - for (uint32_t i = 0; i < num_ports(); ++i) { - PortImpl* const port = _ports->at(i); - if (port->context() == Context::AUDIO) { - port->pre_process(context); - port->connect_buffers(context.offset()); - } - } -} - - -/** Prepare to run a cycle (in the audio thread) - */ -void -NodeBase::post_process(Context& context) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - - // Write output ports - for (size_t i = 0; _ports && i < _ports->size(); ++i) { - PortImpl* const port = _ports->at(i); - if (port->context() == Context::AUDIO) - _ports->at(i)->post_process(context); - } -} - - -/** Flag a port as set (for message context) - */ -void -NodeBase::set_port_valid(uint32_t port_index) -{ - // Allocate enough space for one bit per port - if (!_valid_ports) - _valid_ports = calloc(num_ports() / 8, 1); - lv2_contexts_set_port_valid(_valid_ports, port_index); -} - - -void* -NodeBase::valid_ports() -{ - return _valid_ports; -} - - -void -NodeBase::reset_valid_ports() -{ - if (_valid_ports) - memset(_valid_ports, '\0', num_ports() / 8); -} - - -void -NodeBase::set_port_buffer(uint32_t voice, uint32_t port_num, - BufferFactory::Ref buf, SampleCount offset) -{ - /*std::cout << path() << " set port " << port_num << " voice " << voice - << " buffer " << buf << " offset " << offset << std::endl;*/ -} - - -} // namespace Ingen - diff --git a/src/engine/NodeBase.hpp b/src/engine/NodeBase.hpp deleted file mode 100644 index baab7f50..00000000 --- a/src/engine/NodeBase.hpp +++ /dev/null @@ -1,151 +0,0 @@ -/* This file is part of Ingen. - * Copyright (C) 2007-2009 Dave Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_NODEBASE_HPP -#define INGEN_ENGINE_NODEBASE_HPP - -#include "types.hpp" -#include <string> -#include <cstdlib> -#include "raul/Array.hpp" -#include "raul/Atom.hpp" -#include "raul/AtomicInt.hpp" -#include "raul/IntrusivePtr.hpp" -#include "raul/Semaphore.hpp" -#include "contexts.lv2/contexts.h" -#include "interface/Port.hpp" -#include "interface/PortType.hpp" -#include "NodeImpl.hpp" - -namespace Ingen { - -class Context; -class EngineStore; -class PatchImpl; -class PluginImpl; -class BufferFactory; - -namespace Shared { class ClientInterface; } - - -/** Common implementation stuff for Node. - * - * \ingroup engine - */ -class NodeBase : public NodeImpl -{ -public: - NodeBase(PluginImpl* plugin, - const Raul::Symbol& symbol, - bool poly, - PatchImpl* parent, - SampleRate rate); - - virtual ~NodeBase(); - - virtual void activate(BufferFactory& bufs); - virtual void deactivate(); - bool activated() { return _activated; } - - /** Flag node as polyphonic. - * - * Note this will not actually allocate voices etc., prepare_poly - * and apply_poly must be called after this function to truly make - * a node polyphonic. - */ - virtual void set_polyphonic(bool p) { _polyphonic = p; } - - virtual bool prepare_poly(BufferFactory& bufs, uint32_t poly); - virtual bool apply_poly(Raul::Maid& maid, uint32_t poly); - - virtual void reset_input_ready(); - virtual bool process_lock(); - virtual void process_unlock(); - virtual void wait_for_input(size_t num_providers); - virtual unsigned n_inputs_ready() const { return _n_inputs_ready.get(); } - - virtual void learn() {} - - virtual void message_run(MessageContext& context) {} - - virtual void set_port_valid(uint32_t port_index); - - virtual void* valid_ports(); - virtual void reset_valid_ports(); - - virtual void pre_process(Context& context); - virtual void process(ProcessContext& context) = 0; - virtual void post_process(Context& context); - - virtual void set_port_buffer(uint32_t voice, uint32_t port_num, - IntrusivePtr<Buffer> buf, SampleCount offset); - - virtual void set_buffer_size(Context& context, BufferFactory& bufs, - Shared::PortType type, size_t size); - - SampleRate sample_rate() const { return _srate; } - uint32_t num_ports() const { return _ports ? _ports->size() : 0; } - uint32_t polyphony() const { return _polyphony; } - bool traversed() const { return _traversed; } - void traversed(bool b) { _traversed = b; } - - virtual Shared::Port* port(uint32_t index) const; - virtual PortImpl* port_impl(uint32_t index) const { return (*_ports)[index]; } - - /* These are NOT to be used in the audio thread! - * The providers and dependants in CompiledNode are for that - */ - - Raul::List<NodeImpl*>* providers() { return _providers; } - void providers(Raul::List<NodeImpl*>* l) { _providers = l; } - - Raul::List<NodeImpl*>* dependants() { return _dependants; } - void dependants(Raul::List<NodeImpl*>* l) { _dependants = l; } - - virtual const Shared::Plugin* plugin() const; - virtual PluginImpl* plugin_impl() const { return _plugin; } - virtual void plugin(PluginImpl* pi) { _plugin = pi; } - - /** A node's parent is always a patch, so static cast should be safe */ - inline PatchImpl* parent_patch() const { return (PatchImpl*)_parent; } - -protected: - virtual void signal_input_ready(); - - PluginImpl* _plugin; - - bool _polyphonic; - uint32_t _polyphony; - SampleRate _srate; - - void* _valid_ports; ///< Valid port flags for message context - - Raul::Semaphore _input_ready; ///< Parallelism: input ready signal - Raul::AtomicInt _process_lock; ///< Parallelism: Waiting on inputs 'lock' - Raul::AtomicInt _n_inputs_ready; ///< Parallelism: # input ready signals this cycle - Raul::Array<PortImpl*>* _ports; ///< Access in audio thread only - Raul::List<NodeImpl*>* _providers; ///< Nodes connected to this one's input ports - Raul::List<NodeImpl*>* _dependants; ///< Nodes this one's output ports are connected to - - bool _activated; - bool _traversed; ///< Flag for process order algorithm -}; - - -} // namespace Ingen - -#endif // INGEN_ENGINE_NODEBASE_HPP diff --git a/src/engine/NodeImpl.hpp b/src/engine/NodeImpl.hpp index 97724bfb..53e8b285 100644 --- a/src/engine/NodeImpl.hpp +++ b/src/engine/NodeImpl.hpp @@ -19,7 +19,10 @@ #define INGEN_ENGINE_NODEIMPL_HPP #include <string> +#include "raul/Array.hpp" +#include "raul/AtomicInt.hpp" #include "raul/IntrusivePtr.hpp" +#include "raul/Semaphore.hpp" #include "interface/Node.hpp" #include "GraphObjectImpl.hpp" #include "types.hpp" @@ -28,7 +31,7 @@ namespace Raul { template <typename T> class List; class Maid; } namespace Ingen { -namespace Shared { class Plugin; class Node; class Port; } +namespace Shared { class Plugin; class Port; } class Buffer; class BufferFactory; @@ -45,72 +48,83 @@ class ProcessContext; * A Node is a unit with input/output ports, a process() method, and some other * things. * - * This is a pure abstract base class for any Node, it contains no - * implementation details/data whatsoever. This is the interface you need to - * implement to add a new Node type. - * * \ingroup engine */ class NodeImpl : public GraphObjectImpl, virtual public Ingen::Shared::Node { public: - NodeImpl(GraphObjectImpl* parent, const Raul::Symbol& symbol) - : GraphObjectImpl(parent, symbol) - {} + NodeImpl(PluginImpl* plugin, + const Raul::Symbol& symbol, + bool poly, + PatchImpl* parent, + SampleRate rate); + + virtual ~NodeImpl(); /** Activate this Node. * - * This function will be called in a non-realtime thread before it is + * This function must be called in a non-realtime thread before it is * inserted in to a patch. Any non-realtime actions that need to be * done before the Node is ready for use should be done here. */ - virtual void activate(BufferFactory& bufs) = 0; - virtual void deactivate() = 0; - virtual bool activated() = 0; + virtual void activate(BufferFactory& bufs); - /** Parallelism: Reset flags for start of a new cycle. + /** Deactivate this Node. + * + * This function must be called in a non-realtime thread after the + * node has been removed from its patch (i.e. processing is finished). */ - virtual void reset_input_ready() = 0; + virtual void deactivate(); + + /** Return true iff this node is activated */ + bool activated() { return _activated; } + + /** Parallelism: Reset flags for start of a new cycle. */ + virtual void reset_input_ready(); /** Parallelism: Claim this node (to wait on its input). * Only one thread will ever take this lock on a particular Node. * \return true if lock was aquired, false otherwise */ - virtual bool process_lock() = 0; + virtual bool process_lock(); /** Parallelism: Unclaim this node (let someone else wait on its input). * Only a thread which successfully called process_lock may call this. */ - virtual void process_unlock() = 0; + virtual void process_unlock(); /** Parallelism: Wait for signal that input is ready. * Only a thread which successfully called process_lock may call this. */ - virtual void wait_for_input(size_t num_providers) = 0; + virtual void wait_for_input(size_t num_providers); /** Parallelism: Signal that input is ready. Realtime safe. * Calling this will wake up the thread which blocked on wait_for_input * if there is one, and otherwise cause it to return true the next call. * \return true if lock was aquired and input is ready, false otherwise */ - virtual void signal_input_ready() = 0; + virtual void signal_input_ready(); - /** Parallelism: Return the number of providers that have signalled. - */ - virtual unsigned n_inputs_ready() const = 0; + /** Parallelism: Return the number of providers that have signalled. */ + virtual unsigned n_inputs_ready() const { return _n_inputs_ready.get(); } - /** Run the node for one instant in the message thread. - */ - virtual void message_run(MessageContext& context) = 0; + /** Learn the next incoming MIDI event (for internals) */ + virtual void learn() {} + + /** Run the node for one instant in the message thread. */ + virtual void message_run(MessageContext& context) {} /** Flag a port as valid (for message context) */ - virtual void set_port_valid(uint32_t index) = 0; + virtual void set_port_valid(uint32_t index); /** Return a bit vector of which ports are valid */ - virtual void* valid_ports() = 0; + virtual void* valid_ports(); /** Clear all bits in valid_ports() */ - virtual void reset_valid_ports() = 0; + virtual void reset_valid_ports(); + + /** Do whatever needs doing in the process thread before process() is called */ + virtual void pre_process(Context& context); /** Run the node for @a nframes input/output. * @@ -119,45 +133,86 @@ public: */ virtual void process(ProcessContext& context) = 0; - virtual void set_port_buffer(uint32_t voice, uint32_t port_num, - IntrusivePtr<Buffer> buf, SampleCount offset) = 0; - - virtual uint32_t num_ports() const = 0; + /** Do whatever needs doing in the process thread after process() is called */ + virtual void post_process(Context& context); - virtual Shared::Port* port(uint32_t index) const = 0; - virtual PortImpl* port_impl(uint32_t index) const = 0; + /** Set the buffer of a port to a given buffer (e.g. connect plugin to buffer) */ + virtual void set_port_buffer( + uint32_t voice, + uint32_t port_num, + IntrusivePtr<Buffer> buf, + SampleCount offset); - /** Used by the process order finding algorithm (ie during connections) */ - virtual bool traversed() const = 0; - virtual void traversed(bool b) = 0; + virtual Shared::Port* port(uint32_t index) const; + virtual PortImpl* port_impl(uint32_t index) const { return (*_ports)[index]; } /** Nodes that are connected to this Node's inputs. * (This Node depends on them) */ - virtual Raul::List<NodeImpl*>* providers() = 0; - virtual void providers(Raul::List<NodeImpl*>* l) = 0; + Raul::List<NodeImpl*>* providers() { return _providers; } + void providers(Raul::List<NodeImpl*>* l) { _providers = l; } /** Nodes are are connected to this Node's outputs. * (They depend on this Node) */ - virtual Raul::List<NodeImpl*>* dependants() = 0; - virtual void dependants(Raul::List<NodeImpl*>* l) = 0; + Raul::List<NodeImpl*>* dependants() { return _dependants; } + void dependants(Raul::List<NodeImpl*>* l) { _dependants = l; } - /** The Patch this Node belongs to. */ - virtual PatchImpl* parent_patch() const = 0; + /** Flag node as polyphonic. + * + * Note this will not actually allocate voices etc., prepare_poly + * and apply_poly must be called after this function to truly make + * a node polyphonic. + */ + virtual void set_polyphonic(bool p) { _polyphonic = p; } + + virtual bool prepare_poly(BufferFactory& bufs, uint32_t poly); + virtual bool apply_poly(Raul::Maid& maid, uint32_t poly); /** Information about the Plugin this Node is an instance of. * Not the best name - not all nodes come from plugins (ie Patch) */ - virtual PluginImpl* plugin_impl() const = 0; + virtual PluginImpl* plugin_impl() const { return _plugin; } /** Information about the Plugin this Node is an instance of. * Not the best name - not all nodes come from plugins (ie Patch) */ - virtual const Shared::Plugin* plugin() const = 0; + virtual const Shared::Plugin* plugin() const; + + virtual void plugin(PluginImpl* pi) { _plugin = pi; } virtual void set_buffer_size(Context& context, BufferFactory& bufs, - Shared::PortType type, size_t size) = 0; + Shared::PortType type, size_t size); + + /** The Patch this Node belongs to. */ + inline PatchImpl* parent_patch() const { return (PatchImpl*)_parent; } + + SampleRate sample_rate() const { return _srate; } + virtual uint32_t num_ports() const { return _ports ? _ports->size() : 0; } + virtual uint32_t polyphony() const { return _polyphony; } + + /** Used by the process order finding algorithm (ie during connections) */ + bool traversed() const { return _traversed; } + void traversed(bool b) { _traversed = b; } + +protected: + PluginImpl* _plugin; + + bool _polyphonic; + uint32_t _polyphony; + SampleRate _srate; + + void* _valid_ports; ///< Valid port flags for message context + + Raul::Semaphore _input_ready; ///< Parallelism: input ready signal + Raul::AtomicInt _process_lock; ///< Parallelism: Waiting on inputs 'lock' + Raul::AtomicInt _n_inputs_ready; ///< Parallelism: # input ready signals this cycle + Raul::Array<PortImpl*>* _ports; ///< Access in audio thread only + Raul::List<NodeImpl*>* _providers; ///< Nodes connected to this one's input ports + Raul::List<NodeImpl*>* _dependants; ///< Nodes this one's output ports are connected to + + bool _activated; + bool _traversed; ///< Flag for process order algorithm }; diff --git a/src/engine/PatchImpl.cpp b/src/engine/PatchImpl.cpp index a7b9c699..6b31532a 100644 --- a/src/engine/PatchImpl.cpp +++ b/src/engine/PatchImpl.cpp @@ -39,7 +39,7 @@ using namespace Shared; PatchImpl::PatchImpl(Engine& engine, const Raul::Symbol& symbol, uint32_t poly, PatchImpl* parent, SampleRate srate, uint32_t internal_poly) - : NodeBase(new PatchPlugin("http://example.org/FIXME", "patch", "Ingen Patch"), + : NodeImpl(new PatchPlugin("http://example.org/FIXME", "patch", "Ingen Patch"), symbol, poly, parent, srate) , _engine(engine) , _internal_poly(internal_poly) @@ -62,7 +62,7 @@ PatchImpl::~PatchImpl() void PatchImpl::activate(BufferFactory& bufs) { - NodeBase::activate(bufs); + NodeImpl::activate(bufs); for (List<NodeImpl*>::iterator i = _nodes.begin(); i != _nodes.end(); ++i) (*i)->activate(bufs); @@ -76,7 +76,7 @@ PatchImpl::deactivate() { if (_activated) { - NodeBase::deactivate(); + NodeImpl::deactivate(); for (List<NodeImpl*>::iterator i = _nodes.begin(); i != _nodes.end(); ++i) { if ((*i)->activated()) @@ -160,7 +160,7 @@ PatchImpl::process(ProcessContext& context) if (!_process) return; - NodeBase::pre_process(context); + NodeImpl::pre_process(context); // Run all nodes if (_compiled_patch && _compiled_patch->size() > 0) { @@ -180,7 +180,7 @@ PatchImpl::process(ProcessContext& context) } } - NodeBase::post_process(context); + NodeImpl::post_process(context); } @@ -263,7 +263,7 @@ PatchImpl::process_single(ProcessContext& context) void PatchImpl::set_buffer_size(Context& context, BufferFactory& bufs, PortType type, size_t size) { - NodeBase::set_buffer_size(context, bufs, type, size); + NodeImpl::set_buffer_size(context, bufs, type, size); for (size_t i = 0; i < _compiled_patch->size(); ++i) (*_compiled_patch)[i].node()->set_buffer_size(context, bufs, type, size); @@ -349,7 +349,7 @@ PatchImpl::num_ports() const ThreadID context = ThreadManager::current_thread_id(); if (context == THREAD_PROCESS) - return NodeBase::num_ports(); + return NodeImpl::num_ports(); else return _input_ports.size() + _output_ports.size(); } diff --git a/src/engine/PatchImpl.hpp b/src/engine/PatchImpl.hpp index a8392aca..ff2f0631 100644 --- a/src/engine/PatchImpl.hpp +++ b/src/engine/PatchImpl.hpp @@ -23,7 +23,7 @@ #include "raul/List.hpp" #include "interface/PortType.hpp" #include "interface/Patch.hpp" -#include "NodeBase.hpp" +#include "NodeImpl.hpp" #include "PluginImpl.hpp" #include "CompiledPatch.hpp" @@ -46,7 +46,7 @@ class ProcessContext; * * \ingroup engine */ -class PatchImpl : public NodeBase, public Ingen::Shared::Patch +class PatchImpl : public NodeImpl, public Ingen::Shared::Patch { public: PatchImpl(Engine& engine, diff --git a/src/engine/events/CreatePort.cpp b/src/engine/events/CreatePort.cpp index 7d8f9d16..4aebc0b2 100644 --- a/src/engine/events/CreatePort.cpp +++ b/src/engine/events/CreatePort.cpp @@ -62,7 +62,7 @@ CreatePort::CreatePort( , _properties(properties) { /* This is blocking because of the two different sets of Patch ports, the array used in the - * audio thread (inherited from NodeBase), and the arrays used in the pre processor thread. + * audio thread (inherited from NodeImpl), and the arrays used in the pre processor thread. * If two add port events arrive in the same cycle and the second pre processes before the * first executes, bad things happen (ports are lost). * diff --git a/src/engine/events/Delete.cpp b/src/engine/events/Delete.cpp index 31e249f5..9e4548ac 100644 --- a/src/engine/events/Delete.cpp +++ b/src/engine/events/Delete.cpp @@ -24,7 +24,7 @@ #include "Driver.hpp" #include "Engine.hpp" #include "EngineStore.hpp" -#include "NodeBase.hpp" +#include "NodeImpl.hpp" #include "PatchImpl.hpp" #include "PluginImpl.hpp" #include "PortImpl.hpp" diff --git a/src/engine/events/SetMetadata.cpp b/src/engine/events/SetMetadata.cpp index 4de74eac..c1cc97f0 100644 --- a/src/engine/events/SetMetadata.cpp +++ b/src/engine/events/SetMetadata.cpp @@ -231,7 +231,7 @@ SetMetadata::pre_process() op = POLYPHONIC; _blocking = true; obj->set_property(key, value.get_bool()); - NodeBase* node = dynamic_cast<NodeBase*>(obj); + NodeImpl* node = dynamic_cast<NodeImpl*>(obj); if (node) node->set_polyphonic(value.get_bool()); if (value.get_bool()) { @@ -280,7 +280,7 @@ SetMetadata::execute(ProcessContext& context) (*i)->execute(context); GraphObjectImpl* const object = dynamic_cast<GraphObjectImpl*>(_object); - NodeBase* const node = dynamic_cast<NodeBase*>(_object); + NodeImpl* const node = dynamic_cast<NodeImpl*>(_object); PortImpl* const port = dynamic_cast<PortImpl*>(_object); std::vector<SpecialType>::const_iterator t = _types.begin(); diff --git a/src/engine/internals/Controller.cpp b/src/engine/internals/Controller.cpp index 870dfc8e..aeeb1cd1 100644 --- a/src/engine/internals/Controller.cpp +++ b/src/engine/internals/Controller.cpp @@ -45,7 +45,7 @@ ControllerNode::ControllerNode(BufferFactory& bufs, bool polyphonic, PatchImpl* parent, SampleRate srate) - : NodeBase(&controller_plugin, path, false, parent, srate) + : NodeImpl(&controller_plugin, path, false, parent, srate) , _learning(false) { const LV2URIMap& uris = Shared::LV2URIMap::instance(); @@ -84,7 +84,7 @@ ControllerNode::ControllerNode(BufferFactory& bufs, void ControllerNode::process(ProcessContext& context) { - NodeBase::pre_process(context); + NodeImpl::pre_process(context); uint32_t frames = 0; uint32_t subframes = 0; @@ -104,7 +104,7 @@ ControllerNode::process(ProcessContext& context) midi_in->increment(); } - NodeBase::post_process(context); + NodeImpl::post_process(context); } diff --git a/src/engine/internals/Controller.hpp b/src/engine/internals/Controller.hpp index b6d7302f..b3363665 100644 --- a/src/engine/internals/Controller.hpp +++ b/src/engine/internals/Controller.hpp @@ -19,7 +19,7 @@ #define INGEN_INTERNALS_CONTROLLER_HPP #include <string> -#include "NodeBase.hpp" +#include "NodeImpl.hpp" namespace Ingen { @@ -37,7 +37,7 @@ namespace Internals { * * \ingroup engine */ -class ControllerNode : public NodeBase +class ControllerNode : public NodeImpl { public: ControllerNode(BufferFactory& bufs, const std::string& path, bool polyphonic, PatchImpl* parent, SampleRate srate); diff --git a/src/engine/internals/Delay.cpp b/src/engine/internals/Delay.cpp index 202ba616..7910713f 100644 --- a/src/engine/internals/Delay.cpp +++ b/src/engine/internals/Delay.cpp @@ -54,7 +54,7 @@ static InternalPlugin note_plugin(NS_INTERNALS "Delay", "delay"); InternalPlugin& DelayNode::internal_plugin() { return note_plugin; } DelayNode::DelayNode(BufferFactory& bufs, const string& path, bool polyphonic, PatchImpl* parent, SampleRate srate) - : NodeBase(¬e_plugin, path, polyphonic, parent, srate) + : NodeImpl(¬e_plugin, path, polyphonic, parent, srate) , _buffer(0) , _buffer_length(0) , _buffer_mask(0) @@ -97,7 +97,7 @@ DelayNode::~DelayNode() void DelayNode::activate(BufferFactory& bufs) { - NodeBase::activate(bufs); + NodeImpl::activate(bufs); const SampleCount min_size = MAX_DELAY_SECONDS * _srate; // Smallest power of two larger than min_size @@ -142,7 +142,7 @@ DelayNode::process(ProcessContext& context) AudioBuffer* const in_buf = (AudioBuffer*)_in_port->buffer(0).get(); AudioBuffer* const out_buf = (AudioBuffer*)_out_port->buffer(0).get(); - NodeBase::pre_process(context); + NodeImpl::pre_process(context); DelayNode* plugin_data = this; @@ -199,7 +199,7 @@ DelayNode::process(ProcessContext& context) _write_phase = write_phase; - NodeBase::post_process(context); + NodeImpl::post_process(context); } diff --git a/src/engine/internals/Delay.hpp b/src/engine/internals/Delay.hpp index 077c65f9..758d32e7 100644 --- a/src/engine/internals/Delay.hpp +++ b/src/engine/internals/Delay.hpp @@ -23,7 +23,7 @@ #include "types.hpp" //#include "Buffer.hpp" //#include "BufferFactory.hpp" -#include "NodeBase.hpp" +#include "NodeImpl.hpp" namespace Ingen { @@ -41,7 +41,7 @@ namespace Internals { * * \ingroup engine */ -class DelayNode : public NodeBase +class DelayNode : public NodeImpl { public: DelayNode(BufferFactory& bufs, const std::string& path, bool polyphonic, PatchImpl* parent, SampleRate srate); diff --git a/src/engine/internals/Note.cpp b/src/engine/internals/Note.cpp index fd2dee71..298af84a 100644 --- a/src/engine/internals/Note.cpp +++ b/src/engine/internals/Note.cpp @@ -48,7 +48,7 @@ static InternalPlugin note_plugin(NS_INTERNALS "Note", "note"); InternalPlugin& NoteNode::internal_plugin() { return note_plugin; } NoteNode::NoteNode(BufferFactory& bufs, const string& path, bool polyphonic, PatchImpl* parent, SampleRate srate) - : NodeBase(¬e_plugin, path, polyphonic, parent, srate) + : NodeImpl(¬e_plugin, path, polyphonic, parent, srate) , _voices(new Raul::Array<Voice>(_polyphony)) , _prepared_voices(NULL) , _sustain(false) @@ -94,7 +94,7 @@ NoteNode::prepare_poly(BufferFactory& bufs, uint32_t poly) if (!_polyphonic) return true; - NodeBase::prepare_poly(bufs, poly); + NodeImpl::prepare_poly(bufs, poly); if (_prepared_voices && poly <= _prepared_voices->size()) return true; @@ -108,7 +108,7 @@ NoteNode::prepare_poly(BufferFactory& bufs, uint32_t poly) bool NoteNode::apply_poly(Raul::Maid& maid, uint32_t poly) { - if (!NodeBase::apply_poly(maid, poly)) + if (!NodeImpl::apply_poly(maid, poly)) return false; if (_prepared_voices) { @@ -127,7 +127,7 @@ void NoteNode::process(ProcessContext& context) { EventBuffer* const midi_in = (EventBuffer*)_midi_in_port->buffer(0).get(); - NodeBase::pre_process(context); + NodeImpl::pre_process(context); uint32_t frames = 0; uint32_t subframes = 0; @@ -195,7 +195,7 @@ NoteNode::process(ProcessContext& context) } } - NodeBase::post_process(context); + NodeImpl::post_process(context); } diff --git a/src/engine/internals/Note.hpp b/src/engine/internals/Note.hpp index 8ad7f452..2866fb01 100644 --- a/src/engine/internals/Note.hpp +++ b/src/engine/internals/Note.hpp @@ -20,7 +20,7 @@ #include <string> #include "types.hpp" -#include "NodeBase.hpp" +#include "NodeImpl.hpp" namespace Ingen { @@ -37,7 +37,7 @@ namespace Internals { * * \ingroup engine */ -class NoteNode : public NodeBase +class NoteNode : public NodeImpl { public: NoteNode(BufferFactory& bufs, const std::string& path, bool polyphonic, PatchImpl* parent, SampleRate srate); diff --git a/src/engine/internals/Trigger.cpp b/src/engine/internals/Trigger.cpp index c8d6b77e..ed3b2d90 100644 --- a/src/engine/internals/Trigger.cpp +++ b/src/engine/internals/Trigger.cpp @@ -44,7 +44,7 @@ static InternalPlugin trigger_plugin(NS_INTERNALS "Trigger", "trigger"); InternalPlugin& TriggerNode::internal_plugin() { return trigger_plugin; } TriggerNode::TriggerNode(BufferFactory& bufs, const string& path, bool polyphonic, PatchImpl* parent, SampleRate srate) - : NodeBase(&trigger_plugin, path, false, parent, srate) + : NodeImpl(&trigger_plugin, path, false, parent, srate) , _learning(false) { const LV2URIMap& uris = LV2URIMap::instance(); @@ -82,7 +82,7 @@ TriggerNode::TriggerNode(BufferFactory& bufs, const string& path, bool polyphoni void TriggerNode::process(ProcessContext& context) { - NodeBase::pre_process(context); + NodeImpl::pre_process(context); uint32_t frames = 0; uint32_t subframes = 0; @@ -120,7 +120,7 @@ TriggerNode::process(ProcessContext& context) midi_in->increment(); } - NodeBase::post_process(context); + NodeImpl::post_process(context); } diff --git a/src/engine/internals/Trigger.hpp b/src/engine/internals/Trigger.hpp index 53aba06f..5513f6d8 100644 --- a/src/engine/internals/Trigger.hpp +++ b/src/engine/internals/Trigger.hpp @@ -19,7 +19,7 @@ #define INGEN_INTERNALS_TRIGGER_HPP #include <string> -#include "NodeBase.hpp" +#include "NodeImpl.hpp" namespace Ingen { @@ -40,7 +40,7 @@ namespace Internals { * * \ingroup engine */ -class TriggerNode : public NodeBase +class TriggerNode : public NodeImpl { public: TriggerNode(BufferFactory& bufs, const std::string& path, bool polyphonic, PatchImpl* parent, SampleRate srate); diff --git a/src/engine/wscript b/src/engine/wscript index b551a5bc..39ac47d5 100644 --- a/src/engine/wscript +++ b/src/engine/wscript @@ -22,8 +22,8 @@ def build(bld): InputPort.cpp InternalPlugin.cpp MessageContext.cpp - NodeBase.cpp NodeFactory.cpp + NodeImpl.cpp ObjectBuffer.cpp ObjectSender.cpp OutputPort.cpp |