From 317627ef40f7654c298aa1ac707851c852259e3a Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 18 Aug 2012 23:05:06 +0000 Subject: Node => Block git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@4720 a436a847-0d15-0410-975c-d299462d15a1 --- src/server/BlockFactory.cpp | 134 +++++++++++ src/server/BlockFactory.hpp | 63 +++++ src/server/BlockImpl.cpp | 187 ++++++++++++++ src/server/BlockImpl.hpp | 175 ++++++++++++++ src/server/Broadcaster.cpp | 10 +- src/server/Broadcaster.hpp | 6 +- src/server/CompiledPatch.hpp | 30 +-- src/server/Driver.hpp | 7 +- src/server/DuplexPort.cpp | 6 +- src/server/DuplexPort.hpp | 6 +- src/server/EdgeImpl.cpp | 8 +- src/server/EdgeImpl.hpp | 2 +- src/server/Engine.cpp | 8 +- src/server/Engine.hpp | 6 +- src/server/GraphObjectImpl.cpp | 2 +- src/server/GraphObjectImpl.hpp | 2 +- src/server/InputPort.cpp | 6 +- src/server/InputPort.hpp | 6 +- src/server/InternalPlugin.cpp | 2 +- src/server/InternalPlugin.hpp | 12 +- src/server/LV2Block.cpp | 469 ++++++++++++++++++++++++++++++++++++ src/server/LV2Block.hpp | 116 +++++++++ src/server/LV2Node.cpp | 469 ------------------------------------ src/server/LV2Node.hpp | 116 --------- src/server/LV2Plugin.cpp | 12 +- src/server/LV2Plugin.hpp | 12 +- src/server/LV2ResizeFeature.hpp | 16 +- src/server/NodeFactory.cpp | 134 ----------- src/server/NodeFactory.hpp | 65 ----- src/server/NodeImpl.cpp | 187 -------------- src/server/NodeImpl.hpp | 175 -------------- src/server/OutputPort.cpp | 4 +- src/server/OutputPort.hpp | 2 +- src/server/PatchImpl.cpp | 68 +++--- src/server/PatchImpl.hpp | 24 +- src/server/PatchPlugin.hpp | 12 +- src/server/PluginImpl.hpp | 18 +- src/server/PortImpl.cpp | 12 +- src/server/PortImpl.hpp | 14 +- src/server/Worker.cpp | 28 +-- src/server/Worker.hpp | 4 +- src/server/events.hpp | 2 +- src/server/events/Connect.cpp | 38 +-- src/server/events/CreateBlock.cpp | 144 +++++++++++ src/server/events/CreateBlock.hpp | 70 ++++++ src/server/events/CreateNode.cpp | 144 ----------- src/server/events/CreateNode.hpp | 70 ------ src/server/events/CreatePatch.cpp | 4 +- src/server/events/Delete.cpp | 22 +- src/server/events/Delete.hpp | 8 +- src/server/events/Delta.cpp | 26 +- src/server/events/Disconnect.cpp | 44 ++-- src/server/events/DisconnectAll.cpp | 20 +- src/server/events/DisconnectAll.hpp | 6 +- src/server/events/Get.cpp | 32 +-- src/server/events/Get.hpp | 4 +- src/server/events/Move.cpp | 2 +- src/server/events/SetPortValue.cpp | 4 +- src/server/ingen_lv2.cpp | 2 +- src/server/internals/Controller.cpp | 6 +- src/server/internals/Controller.hpp | 6 +- src/server/internals/Delay.cpp | 8 +- src/server/internals/Delay.hpp | 4 +- src/server/internals/Note.cpp | 10 +- src/server/internals/Note.hpp | 6 +- src/server/internals/Trigger.cpp | 6 +- src/server/internals/Trigger.hpp | 10 +- src/server/wscript | 8 +- 68 files changed, 1667 insertions(+), 1674 deletions(-) create mode 100644 src/server/BlockFactory.cpp create mode 100644 src/server/BlockFactory.hpp create mode 100644 src/server/BlockImpl.cpp create mode 100644 src/server/BlockImpl.hpp create mode 100644 src/server/LV2Block.cpp create mode 100644 src/server/LV2Block.hpp delete mode 100644 src/server/LV2Node.cpp delete mode 100644 src/server/LV2Node.hpp delete mode 100644 src/server/NodeFactory.cpp delete mode 100644 src/server/NodeFactory.hpp delete mode 100644 src/server/NodeImpl.cpp delete mode 100644 src/server/NodeImpl.hpp create mode 100644 src/server/events/CreateBlock.cpp create mode 100644 src/server/events/CreateBlock.hpp delete mode 100644 src/server/events/CreateNode.cpp delete mode 100644 src/server/events/CreateNode.hpp (limited to 'src/server') diff --git a/src/server/BlockFactory.cpp b/src/server/BlockFactory.cpp new file mode 100644 index 00000000..3e08aa7f --- /dev/null +++ b/src/server/BlockFactory.cpp @@ -0,0 +1,134 @@ +/* + This file is part of Ingen. + Copyright 2007-2012 David Robillard + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see . +*/ + +#include + +#include "lilv/lilv.h" + +#include "ingen/World.hpp" +#include "internals/Controller.hpp" +#include "internals/Delay.hpp" +#include "internals/Note.hpp" +#include "internals/Trigger.hpp" + +#include "InternalPlugin.hpp" +#include "LV2Plugin.hpp" +#include "BlockFactory.hpp" +#include "ThreadManager.hpp" + +using namespace std; + +namespace Ingen { +namespace Server { + +using namespace Internals; + +BlockFactory::BlockFactory(Ingen::World* world) + : _world(world) + , _lv2_info(new LV2Info(world)) + , _has_loaded(false) +{ + load_internal_plugins(); +} + +BlockFactory::~BlockFactory() +{ + for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) + delete i->second; + + _plugins.clear(); +} + +const BlockFactory::Plugins& +BlockFactory::plugins() +{ + ThreadManager::assert_thread(THREAD_PRE_PROCESS); + if (!_has_loaded) { + _has_loaded = true; + // TODO: Plugin list refreshing + load_lv2_plugins(); + _has_loaded = true; + } + return _plugins; +} + +PluginImpl* +BlockFactory::plugin(const Raul::URI& uri) +{ + load_plugin(uri); + const Plugins::const_iterator i = _plugins.find(uri); + return ((i != _plugins.end()) ? i->second : NULL); +} + +void +BlockFactory::load_internal_plugins() +{ + Ingen::URIs& uris = _world->uris(); + InternalPlugin* controller_plug = ControllerNode::internal_plugin(uris); + _plugins.insert(make_pair(controller_plug->uri(), controller_plug)); + + InternalPlugin* delay_plug = DelayNode::internal_plugin(uris); + _plugins.insert(make_pair(delay_plug->uri(), delay_plug)); + + InternalPlugin* note_plug = NoteNode::internal_plugin(uris); + _plugins.insert(make_pair(note_plug->uri(), note_plug)); + + InternalPlugin* trigger_plug = TriggerNode::internal_plugin(uris); + _plugins.insert(make_pair(trigger_plug->uri(), trigger_plug)); +} + +void +BlockFactory::load_plugin(const Raul::URI& uri) +{ + if (_has_loaded || _plugins.find(uri) != _plugins.end()) { + return; + } + + LilvNode* node = lilv_new_uri(_world->lilv_world(), uri.c_str()); + const LilvPlugins* plugs = lilv_world_get_all_plugins(_world->lilv_world()); + const LilvPlugin* plug = lilv_plugins_get_by_uri(plugs, node); + if (plug) { + LV2Plugin* const ingen_plugin = new LV2Plugin(_lv2_info, uri); + ingen_plugin->lilv_plugin(plug); + _plugins.insert(make_pair(uri, ingen_plugin)); + } + lilv_node_free(node); +} + +/** Loads information about all LV2 plugins into internal plugin database. + */ +void +BlockFactory::load_lv2_plugins() +{ + const LilvPlugins* plugins = lilv_world_get_all_plugins(_world->lilv_world()); + LILV_FOREACH(plugins, i, plugins) { + const LilvPlugin* lv2_plug = lilv_plugins_get(plugins, i); + + const Raul::URI uri(lilv_node_as_uri(lilv_plugin_get_uri(lv2_plug))); + + if (_plugins.find(uri) != _plugins.end()) { + continue; + } + + LV2Plugin* const plugin = new LV2Plugin(_lv2_info, uri); + + plugin->lilv_plugin(lv2_plug); + _plugins.insert(make_pair(uri, plugin)); + } +} + +} // namespace Server +} // namespace Ingen diff --git a/src/server/BlockFactory.hpp b/src/server/BlockFactory.hpp new file mode 100644 index 00000000..a66b7913 --- /dev/null +++ b/src/server/BlockFactory.hpp @@ -0,0 +1,63 @@ +/* + This file is part of Ingen. + Copyright 2007-2012 David Robillard + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see . +*/ + +#ifndef INGEN_ENGINE_BLOCKFACTORY_HPP +#define INGEN_ENGINE_BLOCKFACTORY_HPP + +#include + +#include "ingen/World.hpp" +#include "raul/Noncopyable.hpp" +#include "raul/SharedPtr.hpp" +#include "raul/URI.hpp" + +namespace Ingen { +namespace Server { + +class PluginImpl; +class LV2Info; + +/** Discovers and loads plugin libraries. + * + * \ingroup engine + */ +class BlockFactory : public Raul::Noncopyable +{ +public: + explicit BlockFactory(Ingen::World* world); + ~BlockFactory(); + + void load_plugin(const Raul::URI& uri); + + typedef std::map Plugins; + const Plugins& plugins(); + + PluginImpl* plugin(const Raul::URI& uri); + +private: + void load_lv2_plugins(); + void load_internal_plugins(); + + Plugins _plugins; + Ingen::World* _world; + SharedPtr _lv2_info; + bool _has_loaded; +}; + +} // namespace Server +} // namespace Ingen + +#endif // INGEN_ENGINE_BLOCKFACTORY_HPP diff --git a/src/server/BlockImpl.cpp b/src/server/BlockImpl.cpp new file mode 100644 index 00000000..7d99ca28 --- /dev/null +++ b/src/server/BlockImpl.cpp @@ -0,0 +1,187 @@ +/* + This file is part of Ingen. + Copyright 2007-2012 David Robillard + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see . +*/ + +#include +#include + +#include "raul/Array.hpp" + +#include "Buffer.hpp" +#include "Engine.hpp" +#include "BlockImpl.hpp" +#include "PatchImpl.hpp" +#include "PluginImpl.hpp" +#include "PortImpl.hpp" +#include "ProcessContext.hpp" +#include "ThreadManager.hpp" + +using namespace std; + +namespace Ingen { +namespace Server { + +BlockImpl::BlockImpl(PluginImpl* plugin, + const Raul::Symbol& symbol, + bool polyphonic, + PatchImpl* parent, + SampleRate srate) + : GraphObjectImpl(plugin->uris(), parent, symbol) + , _plugin(plugin) + , _ports(NULL) + , _context(Context::AUDIO) + , _polyphony((polyphonic && parent) ? parent->internal_poly() : 1) + , _polyphonic(polyphonic) + , _activated(false) + , _traversed(false) +{ + assert(_plugin); + assert(_polyphony > 0); +} + +BlockImpl::~BlockImpl() +{ + if (_activated) { + deactivate(); + } + + if (is_linked()) { + parent_patch()->remove_block(*this); + } + + delete _ports; +} + +GraphObject* +BlockImpl::port(uint32_t index) const +{ + return (*_ports)[index]; +} + +const Plugin* +BlockImpl::plugin() const +{ + return _plugin; +} + +void +BlockImpl::activate(BufferFactory& bufs) +{ + ThreadManager::assert_thread(THREAD_PRE_PROCESS); + + _activated = true; + for (uint32_t p = 0; p < num_ports(); ++p) { + PortImpl* const port = _ports->at(p); + port->setup_buffers(bufs, port->poly(), false); + port->connect_buffers(); + port->clear_buffers(); + } +} + +void +BlockImpl::deactivate() +{ + _activated = false; + for (uint32_t i = 0; i < _polyphony; ++i) { + for (uint32_t j = 0; j < num_ports(); ++j) { + PortImpl* const port = _ports->at(j); + if (port->is_output() && port->buffer(i)) + port->buffer(i)->clear(); + } + } +} + +bool +BlockImpl::prepare_poly(BufferFactory& bufs, uint32_t poly) +{ + ThreadManager::assert_thread(THREAD_PRE_PROCESS); + + if (!_polyphonic) + poly = 1; + + if (_ports) + for (uint32_t i = 0; i < _ports->size(); ++i) + _ports->at(i)->prepare_poly(bufs, poly); + + return true; +} + +bool +BlockImpl::apply_poly(ProcessContext& context, Raul::Maid& maid, uint32_t poly) +{ + if (!_polyphonic) + poly = 1; + + _polyphony = poly; + + if (_ports) + for (uint32_t i = 0; i < num_ports(); ++i) + _ports->at(i)->apply_poly(context, maid, poly); + + return true; +} + +void +BlockImpl::set_buffer_size(Context& context, + BufferFactory& bufs, + LV2_URID type, + uint32_t size) +{ + if (_ports) { + for (uint32_t i = 0; i < _ports->size(); ++i) { + PortImpl* const p = _ports->at(i); + if (p->buffer_type() == type) { + p->set_buffer_size(context, bufs, size); + } + } + } +} + +/** Prepare to run a cycle (in the audio thread) + */ +void +BlockImpl::pre_process(ProcessContext& context) +{ + // Mix down input ports + for (uint32_t i = 0; i < num_ports(); ++i) { + PortImpl* const port = _ports->at(i); + port->pre_process(context); + port->connect_buffers(); + } +} + +/** Prepare to run a cycle (in the audio thread) + */ +void +BlockImpl::post_process(ProcessContext& context) +{ + // Write output ports + for (uint32_t i = 0; _ports && i < _ports->size(); ++i) { + _ports->at(i)->post_process(context); + } +} + +void +BlockImpl::set_port_buffer(uint32_t voice, + uint32_t port_num, + BufferRef buf) +{ + /*std::cout << path() << " set port " << port_num << " voice " << voice + << " buffer " << buf << " offset " << offset << std::endl;*/ +} + +} // namespace Server +} // namespace Ingen + diff --git a/src/server/BlockImpl.hpp b/src/server/BlockImpl.hpp new file mode 100644 index 00000000..fd2af927 --- /dev/null +++ b/src/server/BlockImpl.hpp @@ -0,0 +1,175 @@ +/* + This file is part of Ingen. + Copyright 2007-2012 David Robillard + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see . +*/ + +#ifndef INGEN_ENGINE_NODEIMPL_HPP +#define INGEN_ENGINE_NODEIMPL_HPP + +#include + +#include + +#include "raul/Array.hpp" +#include "raul/AtomicInt.hpp" + +#include "BufferRef.hpp" +#include "Context.hpp" +#include "GraphObjectImpl.hpp" +#include "PortType.hpp" +#include "types.hpp" + +namespace Raul { +class Maid; +} + +namespace Ingen { + +class Plugin; + +namespace Server { + +class Buffer; +class BufferFactory; +class Context; +class PatchImpl; +class PluginImpl; +class PortImpl; +class ProcessContext; + +/** A Block in a Patch (which is also a Block). + * + * This is what is often called a "Module" in modular synthesizers. A Block is + * a unit with input/output ports, a process() method, and some other things. + * + * \ingroup engine + */ +class BlockImpl : public GraphObjectImpl + , public boost::intrusive::slist_base_hook<> // In PatchImpl +{ +public: + BlockImpl(PluginImpl* plugin, + const Raul::Symbol& symbol, + bool poly, + PatchImpl* parent, + SampleRate rate); + + virtual ~BlockImpl(); + + virtual GraphType graph_type() const { return BLOCK; } + + /** Activate this Block. + * + * 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 Block is ready for use should be done here. + */ + virtual void activate(BufferFactory& bufs); + + /** Deactivate this Block. + * + * This function must be called in a non-realtime thread after the + * block has been removed from its patch (i.e. processing is finished). + */ + virtual void deactivate(); + + /** Return true iff this block is activated */ + bool activated() { return _activated; } + + /** Learn the next incoming MIDI event (for internals) */ + virtual void learn() {} + + /** Do whatever needs doing in the process thread before process() is called */ + virtual void pre_process(ProcessContext& context); + + /** Run the block for @a nframes input/output. + * + * @a start and @a end are transport times: end is not redundant in the case + * of varispeed, where end-start != nframes. + */ + virtual void process(ProcessContext& context) = 0; + + /** Do whatever needs doing in the process thread after process() is called */ + virtual void post_process(ProcessContext& context); + + /** 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, + BufferRef buf); + + virtual GraphObject* port(uint32_t index) const; + virtual PortImpl* port_impl(uint32_t index) const { return (*_ports)[index]; } + + /** Blocks that are connected to this Block's inputs. */ + std::list& providers() { return _providers; } + + /** Blocks are are connected to this Block's outputs. */ + std::list& dependants() { return _dependants; } + + /** Flag block 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 block polyphonic. + */ + virtual void set_polyphonic(bool p) { _polyphonic = p; } + + virtual bool prepare_poly(BufferFactory& bufs, uint32_t poly); + virtual bool apply_poly( + ProcessContext& context, Raul::Maid& maid, uint32_t poly); + + /** Information about the Plugin this Block is an instance of. + * Not the best name - not all blocks come from plugins (e.g. Patch) + */ + virtual PluginImpl* plugin_impl() const { return _plugin; } + + /** Information about the Plugin this Block is an instance of. + * Not the best name - not all blocks come from plugins (ie Patch) + */ + virtual const Plugin* plugin() const; + + virtual void plugin(PluginImpl* pi) { _plugin = pi; } + + virtual void set_buffer_size(Context& context, + BufferFactory& bufs, + LV2_URID type, + uint32_t size); + + /** The Patch this Block belongs to. */ + inline PatchImpl* parent_patch() const { return (PatchImpl*)_parent; } + + Context::ID context() const { return _context; } + 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; + Raul::Array* _ports; ///< Access in audio thread only + Context::ID _context; ///< Context this block runs in + uint32_t _polyphony; + std::list _providers; ///< Blocks connected to this one's input ports + std::list _dependants; ///< Blocks this one's output ports are connected to + bool _polyphonic; + bool _activated; + bool _traversed; ///< Flag for process order algorithm +}; + +} // namespace Server +} // namespace Ingen + +#endif // INGEN_ENGINE_BLOCKIMPL_HPP diff --git a/src/server/Broadcaster.cpp b/src/server/Broadcaster.cpp index 33ee5369..ab6b16fb 100644 --- a/src/server/Broadcaster.cpp +++ b/src/server/Broadcaster.cpp @@ -21,7 +21,7 @@ #include "Broadcaster.hpp" #include "PluginImpl.hpp" -#include "NodeFactory.hpp" +#include "BlockFactory.hpp" namespace Ingen { namespace Server { @@ -64,7 +64,7 @@ Broadcaster::client(const Raul::URI& uri) } void -Broadcaster::send_plugins(const NodeFactory::Plugins& plugins) +Broadcaster::send_plugins(const BlockFactory::Plugins& plugins) { Glib::Mutex::Lock lock(_clients_mutex); for (Clients::const_iterator c = _clients.begin(); c != _clients.end(); ++c) { @@ -73,12 +73,12 @@ Broadcaster::send_plugins(const NodeFactory::Plugins& plugins) } void -Broadcaster::send_plugins_to(Interface* client, - const NodeFactory::Plugins& plugins) +Broadcaster::send_plugins_to(Interface* client, + const BlockFactory::Plugins& plugins) { client->bundle_begin(); - for (NodeFactory::Plugins::const_iterator i = plugins.begin(); i != plugins.end(); ++i) { + for (BlockFactory::Plugins::const_iterator i = plugins.begin(); i != plugins.end(); ++i) { const PluginImpl* const plugin = i->second; client->put(plugin->uri(), plugin->properties()); } diff --git a/src/server/Broadcaster.hpp b/src/server/Broadcaster.hpp index 507e8eec..0bc7576a 100644 --- a/src/server/Broadcaster.hpp +++ b/src/server/Broadcaster.hpp @@ -27,7 +27,7 @@ #include "ingen/Interface.hpp" -#include "NodeFactory.hpp" +#include "BlockFactory.hpp" namespace Ingen { namespace Server { @@ -47,8 +47,8 @@ public: SharedPtr client(const Raul::URI& uri); - void send_plugins(const NodeFactory::Plugins& plugin_list); - void send_plugins_to(Interface*, const NodeFactory::Plugins& plugin_list); + void send_plugins(const BlockFactory::Plugins& plugin_list); + void send_plugins_to(Interface*, const BlockFactory::Plugins& plugin_list); #define BROADCAST(msg, ...) \ Glib::Mutex::Lock lock(_clients_mutex); \ diff --git a/src/server/CompiledPatch.hpp b/src/server/CompiledPatch.hpp index 7f973792..15d1137a 100644 --- a/src/server/CompiledPatch.hpp +++ b/src/server/CompiledPatch.hpp @@ -27,42 +27,42 @@ namespace Ingen { namespace Server { class EdgeImpl; -class NodeImpl; +class BlockImpl; -/** All information required about a node to execute it in an audio thread. +/** All information required about a block to execute it in an audio thread. */ -class CompiledNode { +class CompiledBlock { public: - CompiledNode(NodeImpl* n, size_t np, const std::list& d) - : _node(n), _n_providers(np) + CompiledBlock(BlockImpl* b, size_t np, const std::list& d) + : _block(b), _n_providers(np) { // Copy to a vector for maximum iteration speed and cache optimization // (Need to take a copy anyway) _dependants.reserve(d.size()); - for (std::list::const_iterator i = d.begin(); i != d.end(); ++i) + for (std::list::const_iterator i = d.begin(); i != d.end(); ++i) _dependants.push_back(*i); } - NodeImpl* node() const { return _node; } - size_t n_providers() const { return _n_providers; } - const std::vector& dependants() const { return _dependants; } + BlockImpl* block() const { return _block; } + size_t n_providers() const { return _n_providers; } + const std::vector& dependants() const { return _dependants; } private: - NodeImpl* _node; - size_t _n_providers; ///< Number of input ready signals to trigger run - std::vector _dependants; ///< Nodes this one's output ports are connected to + BlockImpl* _block; + size_t _n_providers; ///< Number of input ready signals to trigger run + std::vector _dependants; ///< Blocks this one's output ports are connected to }; /** A patch ``compiled'' into a flat structure with the correct order so * the audio thread(s) can execute it without threading problems (since * the preprocessor thread modifies the graph). * - * The nodes contained here are sorted in the order they must be executed. - * The parallel processing algorithm guarantees no node will be executed + * The blocks contained here are sorted in the order they must be executed. + * The parallel processing algorithm guarantees no block will be executed * before its providers, using this order as well as semaphores. */ -class CompiledPatch : public std::vector +class CompiledPatch : public std::vector , public Raul::Disposable , public Raul::Noncopyable { diff --git a/src/server/Driver.hpp b/src/server/Driver.hpp index 1d6e7ef0..e038b2bc 100644 --- a/src/server/Driver.hpp +++ b/src/server/Driver.hpp @@ -34,9 +34,10 @@ class EnginePort; /** Engine driver base class. * - * A Driver is, from the perspective of GraphObjects (nodes, patches, ports) an - * interface for managing system ports. An implementation of Driver basically - * needs to manage EnginePorts, and handle writing/reading data to/from them. + * A Driver is, from the perspective of GraphObjects (blocks, patches, ports) + * an interface for managing system ports. An implementation of Driver + * basically needs to manage EnginePorts, and handle writing/reading data + * to/from them. * * \ingroup engine */ diff --git a/src/server/DuplexPort.cpp b/src/server/DuplexPort.cpp index f28831ff..43197844 100644 --- a/src/server/DuplexPort.cpp +++ b/src/server/DuplexPort.cpp @@ -27,7 +27,7 @@ namespace Ingen { namespace Server { DuplexPort::DuplexPort(BufferFactory& bufs, - NodeImpl* parent, + BlockImpl* parent, const Raul::Symbol& symbol, uint32_t index, bool polyphonic, @@ -85,8 +85,8 @@ DuplexPort::pre_process(Context& context) } } else { /* This is a a patch input, which is an output from the internal - perspective. Do whatever a normal node's input port does to prepare - input for reading. */ + perspective. Do whatever a normal block's input port does to + prepare input for reading. */ InputPort::pre_process(context); } } diff --git a/src/server/DuplexPort.hpp b/src/server/DuplexPort.hpp index 90146e40..25d389c5 100644 --- a/src/server/DuplexPort.hpp +++ b/src/server/DuplexPort.hpp @@ -26,14 +26,14 @@ namespace Ingen { namespace Server { -class NodeImpl; +class BlockImpl; /** A duplex Port (both an InputPort and an OutputPort on a Patch) * * This is used for Patch ports, since they need to appear as both an input and * an output port based on context. There are no actual duplex ports in Ingen, * a Port is either an Input or Output. This class only exists to allow Patch - * outputs to appear as inputs to Nodes inside that patch, and vice versa. + * outputs to appear as inputs from within that Patch, and vice versa. * * \ingroup engine */ @@ -43,7 +43,7 @@ class DuplexPort : public InputPort { public: DuplexPort(BufferFactory& bufs, - NodeImpl* parent, + BlockImpl* parent, const Raul::Symbol& symbol, uint32_t index, bool polyphonic, diff --git a/src/server/EdgeImpl.cpp b/src/server/EdgeImpl.cpp index 23b840d4..08096d45 100644 --- a/src/server/EdgeImpl.cpp +++ b/src/server/EdgeImpl.cpp @@ -17,29 +17,27 @@ #include "ingen/URIs.hpp" #include "lv2/lv2plug.in/ns/ext/atom/util.h" +#include "BlockImpl.hpp" #include "Buffer.hpp" #include "BufferFactory.hpp" #include "EdgeImpl.hpp" #include "Engine.hpp" #include "InputPort.hpp" -#include "NodeImpl.hpp" #include "OutputPort.hpp" #include "PortImpl.hpp" namespace Ingen { namespace Server { -/** Constructor for a edge from a node's output port. +/** Constructor for a edge from a block's output port. * - * This handles both polyphonic and monophonic nodes, transparently to the + * This handles both polyphonic and monophonic blocks, transparently to the * user (InputPort). */ EdgeImpl::EdgeImpl(PortImpl* tail, PortImpl* head) : _tail(tail) , _head(head) { - assert(tail); - assert(head); assert(tail != head); assert(tail->path() != head->path()); } diff --git a/src/server/EdgeImpl.hpp b/src/server/EdgeImpl.hpp index 4a4553b1..0627a7ba 100644 --- a/src/server/EdgeImpl.hpp +++ b/src/server/EdgeImpl.hpp @@ -38,7 +38,7 @@ class InputPort; /** Represents a single inbound connection for an InputPort. * - * This can be a group of ports (ie coming from a polyphonic Node) or + * This can be a group of ports (coming from a polyphonic Block) or * a single Port. This class exists basically as an abstraction of mixing * down polyphonic inputs, so InputPort can just deal with mixing down * multiple connections (oblivious to the polyphonic situation of the diff --git a/src/server/Engine.cpp b/src/server/Engine.cpp index 4efb9f5e..eada608a 100644 --- a/src/server/Engine.cpp +++ b/src/server/Engine.cpp @@ -25,15 +25,15 @@ #include "raul/Maid.hpp" #include "raul/SharedPtr.hpp" +#include "BlockFactory.hpp" #include "Broadcaster.hpp" #include "BufferFactory.hpp" -#include "DirectDriver.hpp" #include "ControlBindings.hpp" +#include "DirectDriver.hpp" #include "Driver.hpp" #include "Engine.hpp" #include "Event.hpp" #include "EventWriter.hpp" -#include "NodeFactory.hpp" #include "PatchImpl.hpp" #include "PostProcessor.hpp" #include "PreProcessor.hpp" @@ -51,11 +51,11 @@ bool ThreadManager::single_threaded(true); Engine::Engine(Ingen::World* world) : _world(world) + , _block_factory(new BlockFactory(world)) , _broadcaster(new Broadcaster()) , _buffer_factory(new BufferFactory(*this, world->uris())) , _control_bindings(NULL) , _maid(new Raul::Maid()) - , _node_factory(new NodeFactory(world)) , _pre_processor(new PreProcessor()) , _post_processor(new PostProcessor(*this)) , _event_writer(new EventWriter(*this)) @@ -92,7 +92,7 @@ Engine::~Engine() delete _maid; delete _pre_processor; delete _post_processor; - delete _node_factory; + delete _block_factory; delete _control_bindings; delete _broadcaster; delete _event_writer; diff --git a/src/server/Engine.hpp b/src/server/Engine.hpp index ca844261..66930938 100644 --- a/src/server/Engine.hpp +++ b/src/server/Engine.hpp @@ -40,7 +40,7 @@ class ControlBindings; class Driver; class Event; class EventWriter; -class NodeFactory; +class BlockFactory; class PostProcessor; class PreProcessor; class ProcessContext; @@ -92,12 +92,12 @@ public: Ingen::World* world() const { return _world; } EventWriter* interface() const { return _event_writer; } + BlockFactory* block_factory() const { return _block_factory; } Broadcaster* broadcaster() const { return _broadcaster; } BufferFactory* buffer_factory() const { return _buffer_factory; } ControlBindings* control_bindings() const { return _control_bindings; } Driver* driver() const { return _driver.get(); } Log& log() const { return _world->log(); } - NodeFactory* node_factory() const { return _node_factory; } PatchImpl* root_patch() const { return _root_patch; } PostProcessor* post_processor() const { return _post_processor; } Raul::Maid* maid() const { return _maid; } @@ -112,12 +112,12 @@ public: private: Ingen::World* _world; + BlockFactory* _block_factory; Broadcaster* _broadcaster; BufferFactory* _buffer_factory; ControlBindings* _control_bindings; SharedPtr _driver; Raul::Maid* _maid; - NodeFactory* _node_factory; PreProcessor* _pre_processor; PostProcessor* _post_processor; EventWriter* _event_writer; diff --git a/src/server/GraphObjectImpl.cpp b/src/server/GraphObjectImpl.cpp index 212e5196..d5608b0f 100644 --- a/src/server/GraphObjectImpl.cpp +++ b/src/server/GraphObjectImpl.cpp @@ -45,7 +45,7 @@ GraphObjectImpl::get_property(const Raul::URI& key) const PatchImpl* GraphObjectImpl::parent_patch() const { - return dynamic_cast((NodeImpl*)_parent); + return dynamic_cast((BlockImpl*)_parent); } } // namespace Server diff --git a/src/server/GraphObjectImpl.hpp b/src/server/GraphObjectImpl.hpp index bfc97fb1..5388981f 100644 --- a/src/server/GraphObjectImpl.hpp +++ b/src/server/GraphObjectImpl.hpp @@ -40,7 +40,7 @@ class Context; class ProcessContext; class BufferFactory; -/** An object on the audio graph - Patch, Node, Port, etc. +/** An object on the audio graph (a Patch, Block, or Port). * * Each of these is a Raul::Deletable and so can be deleted in a realtime safe * way from anywhere, and they all have a map of variable for clients to store diff --git a/src/server/InputPort.cpp b/src/server/InputPort.cpp index 0bce5b93..fff29f30 100644 --- a/src/server/InputPort.cpp +++ b/src/server/InputPort.cpp @@ -20,12 +20,12 @@ #include "ingen/Log.hpp" #include "ingen/URIs.hpp" +#include "BlockImpl.hpp" #include "Buffer.hpp" #include "BufferFactory.hpp" #include "EdgeImpl.hpp" #include "Engine.hpp" #include "InputPort.hpp" -#include "NodeImpl.hpp" #include "OutputPort.hpp" #include "PatchImpl.hpp" #include "ProcessContext.hpp" @@ -37,7 +37,7 @@ namespace Ingen { namespace Server { InputPort::InputPort(BufferFactory& bufs, - NodeImpl* parent, + BlockImpl* parent, const Raul::Symbol& symbol, uint32_t index, uint32_t poly, @@ -159,7 +159,7 @@ InputPort::remove_edge(ProcessContext& context, const OutputPort* tail) uint32_t InputPort::max_tail_poly(Context& context) const { - return parent_node()->parent_patch()->internal_poly_process(); + return parent_block()->parent_patch()->internal_poly_process(); } static void diff --git a/src/server/InputPort.hpp b/src/server/InputPort.hpp index d4d565af..40650415 100644 --- a/src/server/InputPort.hpp +++ b/src/server/InputPort.hpp @@ -32,11 +32,11 @@ namespace Server { class EdgeImpl; class Context; -class NodeImpl; +class BlockImpl; class OutputPort; class ProcessContext; -/** An input port on a Node or Patch. +/** An input port on a Block or Patch. * * All ports have a Buffer, but the actual contents (data) of that buffer may be * set directly to the incoming edge's buffer if there's only one inbound @@ -51,7 +51,7 @@ class InputPort : virtual public PortImpl { public: InputPort(BufferFactory& bufs, - NodeImpl* parent, + BlockImpl* parent, const Raul::Symbol& symbol, uint32_t index, uint32_t poly, diff --git a/src/server/InternalPlugin.cpp b/src/server/InternalPlugin.cpp index 60a5699c..0e15fd9d 100644 --- a/src/server/InternalPlugin.cpp +++ b/src/server/InternalPlugin.cpp @@ -42,7 +42,7 @@ InternalPlugin::InternalPlugin(URIs& uris, set_property(uris.rdf_type, uris.ingen_Internal); } -NodeImpl* +BlockImpl* InternalPlugin::instantiate(BufferFactory& bufs, const Raul::Symbol& symbol, bool polyphonic, diff --git a/src/server/InternalPlugin.hpp b/src/server/InternalPlugin.hpp index bb90f5e6..29753c69 100644 --- a/src/server/InternalPlugin.hpp +++ b/src/server/InternalPlugin.hpp @@ -29,7 +29,7 @@ namespace Ingen { namespace Server { -class NodeImpl; +class BlockImpl; class BufferFactory; /** Implementation of an Internal plugin. @@ -41,11 +41,11 @@ public: const Raul::URI& uri, const Raul::Symbol& symbol); - NodeImpl* instantiate(BufferFactory& bufs, - const Raul::Symbol& symbol, - bool polyphonic, - PatchImpl* parent, - Engine& engine); + BlockImpl* instantiate(BufferFactory& bufs, + const Raul::Symbol& symbol, + bool polyphonic, + PatchImpl* parent, + Engine& engine); const Raul::Symbol symbol() const { return _symbol; } diff --git a/src/server/LV2Block.cpp b/src/server/LV2Block.cpp new file mode 100644 index 00000000..d26f7417 --- /dev/null +++ b/src/server/LV2Block.cpp @@ -0,0 +1,469 @@ +/* + This file is part of Ingen. + Copyright 2007-2012 David Robillard + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see . +*/ + +#include + +#include +#include + +#include "lv2/lv2plug.in/ns/ext/resize-port/resize-port.h" +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" + +#include "raul/Maid.hpp" +#include "raul/Array.hpp" + +#include "ingen/Log.hpp" +#include "ingen/URIMap.hpp" +#include "ingen/URIs.hpp" + +#include "Buffer.hpp" +#include "Driver.hpp" +#include "Engine.hpp" +#include "InputPort.hpp" +#include "LV2Block.hpp" +#include "LV2Plugin.hpp" +#include "OutputPort.hpp" +#include "PatchImpl.hpp" +#include "ProcessContext.hpp" + +using namespace std; + +namespace Ingen { +namespace Server { + +/** Partially construct a LV2Block. + * + * Object is not usable until instantiate() is called with success. + * (It _will_ crash!) + */ +LV2Block::LV2Block(LV2Plugin* plugin, + const Raul::Symbol& symbol, + bool polyphonic, + PatchImpl* parent, + SampleRate srate) +: BlockImpl(plugin, symbol, polyphonic, parent, srate) + , _lv2_plugin(plugin) + , _instances(NULL) + , _prepared_instances(NULL) + , _worker_iface(NULL) +{ + assert(_lv2_plugin); +} + +LV2Block::~LV2Block() +{ + delete _instances; +} + +SharedPtr +LV2Block::make_instance(URIs& uris, + SampleRate rate, + uint32_t voice, + bool preparing) +{ + LilvInstance* inst = lilv_plugin_instantiate( + _lv2_plugin->lilv_plugin(), rate, _features->array()); + + if (!inst) { + parent_patch()->engine().log().error( + Raul::fmt("Failed to instantiate <%1%>\n") + % _lv2_plugin->uri().c_str()); + return SharedPtr(); + } + + const LV2_Morph_Interface* morph_iface = (const LV2_Morph_Interface*) + lilv_instance_get_extension_data(inst, LV2_MORPH__interface); + + for (uint32_t p = 0; p < num_ports(); ++p) { + PortImpl* const port = _ports->at(p); + Buffer* const buffer = (preparing) + ? port->prepared_buffer(voice).get() + : port->buffer(voice).get(); + if (port->is_morph() && port->is_a(PortType::CV)) { + if (morph_iface) { + morph_iface->morph_port( + inst->lv2_handle, p, uris.lv2_CVPort, NULL); + } + } + + if (buffer) { + if (port->is_a(PortType::CV) || port->is_a(PortType::CONTROL)) { + buffer->set_block(port->value().get_float(), 0, buffer->nframes()); + } else { + buffer->clear(); + } + } + } + + if (morph_iface) { + for (uint32_t p = 0; p < num_ports(); ++p) { + PortImpl* const port = _ports->at(p); + if (port->is_auto_morph()) { + LV2_URID type = morph_iface->port_type( + inst->lv2_handle, p, NULL); + if (type == _uris.lv2_ControlPort) { + port->set_type(PortType::CONTROL, 0); + } else if (type == _uris.lv2_CVPort) { + port->set_type(PortType::CV, 0); + } else { + parent_patch()->engine().log().error( + Raul::fmt("%1% auto-morphed to unknown type %2%\n") + % port->path().c_str() % type); + return SharedPtr(); + } + } + } + } + + return SharedPtr(inst, lilv_instance_free); +} + +bool +LV2Block::prepare_poly(BufferFactory& bufs, uint32_t poly) +{ + if (!_polyphonic) + poly = 1; + + BlockImpl::prepare_poly(bufs, poly); + + if (_polyphony == poly) + return true; + + const SampleRate rate = bufs.engine().driver()->sample_rate(); + assert(!_prepared_instances); + _prepared_instances = new Instances(poly, *_instances, SharedPtr()); + for (uint32_t i = _polyphony; i < _prepared_instances->size(); ++i) { + SharedPtr inst = make_instance(bufs.uris(), rate, i, true); + if (!inst) { + return false; + } + + _prepared_instances->at(i) = inst; + + if (_activated) { + lilv_instance_activate(inst.get()); + } + } + + return true; +} + +bool +LV2Block::apply_poly(ProcessContext& context, Raul::Maid& maid, uint32_t poly) +{ + if (!_polyphonic) + poly = 1; + + if (_prepared_instances) { + maid.dispose(_instances); + _instances = _prepared_instances; + _prepared_instances = NULL; + } + assert(poly <= _instances->size()); + + return BlockImpl::apply_poly(context, maid, poly); +} + +/** Instantiate self from LV2 plugin descriptor. + * + * Implemented as a seperate function (rather than in the constructor) to + * allow graceful error-catching of broken plugins. + * + * Returns whether or not plugin was successfully instantiated. If return + * value is false, this object may not be used. + */ +bool +LV2Block::instantiate(BufferFactory& bufs) +{ + const Ingen::URIs& uris = bufs.uris(); + SharedPtr info = _lv2_plugin->lv2_info(); + const LilvPlugin* plug = _lv2_plugin->lilv_plugin(); + Ingen::Forge& forge = bufs.forge(); + const uint32_t num_ports = lilv_plugin_get_num_ports(plug); + + _ports = new Raul::Array(num_ports, NULL); + + bool ret = true; + + float* min_values = new float[num_ports]; + float* max_values = new float[num_ports]; + float* def_values = new float[num_ports]; + lilv_plugin_get_port_ranges_float(plug, min_values, max_values, def_values); + + // Get all the necessary information about ports + for (uint32_t j = 0; j < num_ports; ++j) { + const LilvPort* id = lilv_plugin_get_port_by_index(plug, j); + + /* LV2 port symbols are guaranteed to be unique, valid C identifiers, + and Lilv guarantees that lilv_port_get_symbol() is valid. */ + const Raul::Symbol port_sym( + lilv_node_as_string(lilv_port_get_symbol(plug, id))); + + // Get port type + Raul::Atom val; + PortType port_type = PortType::UNKNOWN; + LV2_URID buffer_type = 0; + bool is_morph = false; + bool is_auto_morph = false; + if (lilv_port_is_a(plug, id, info->lv2_ControlPort)) { + if (lilv_port_is_a(plug, id, info->morph_MorphPort)) { + is_morph = true; + LilvNodes* types = lilv_port_get_value( + plug, id, info->morph_supportsType); + LILV_FOREACH(nodes, i, types) { + const LilvNode* type = lilv_nodes_get(types, i); + if (lilv_node_equals(type, info->lv2_CVPort)) { + port_type = PortType::CV; + buffer_type = uris.atom_Sound; + } + } + lilv_nodes_free(types); + } + if (port_type == PortType::UNKNOWN) { + port_type = PortType::CONTROL; + buffer_type = uris.atom_Float; + } + } else if (lilv_port_is_a(plug, id, info->lv2_CVPort)) { + port_type = PortType::CV; + buffer_type = uris.atom_Sound; + } else if (lilv_port_is_a(plug, id, info->lv2_AudioPort)) { + port_type = PortType::AUDIO; + buffer_type = uris.atom_Sound; + } else if (lilv_port_is_a(plug, id, info->atom_AtomPort)) { + port_type = PortType::ATOM; + } + + if (lilv_port_is_a(plug, id, info->morph_AutoMorphPort)) { + is_auto_morph = true; + } + + // Get buffer type if necessary (atom ports) + if (!buffer_type) { + LilvNodes* types = lilv_port_get_value( + plug, id, info->atom_bufferType); + LILV_FOREACH(nodes, i, types) { + const LilvNode* type = lilv_nodes_get(types, i); + if (lilv_node_is_uri(type)) { + buffer_type = bufs.engine().world()->uri_map().map_uri( + lilv_node_as_uri(type)); + } + } + lilv_nodes_free(types); + } + + uint32_t port_buffer_size = bufs.default_size(buffer_type); + + if (port_type == PortType::ATOM) { + // Get default value, and its length + LilvNodes* defaults = lilv_port_get_value(plug, id, info->lv2_default); + LILV_FOREACH(nodes, i, defaults) { + const LilvNode* d = lilv_nodes_get(defaults, i); + if (lilv_node_is_string(d)) { + const char* str_val = lilv_node_as_string(d); + const uint32_t str_val_len = strlen(str_val); + val = forge.alloc(str_val); + port_buffer_size = std::max(port_buffer_size, str_val_len); + } + } + lilv_nodes_free(defaults); + + // Get minimum size, if set in data + LilvNodes* sizes = lilv_port_get_value(plug, id, info->rsz_minimumSize); + LILV_FOREACH(nodes, i, sizes) { + const LilvNode* d = lilv_nodes_get(sizes, i); + if (lilv_node_is_int(d)) { + uint32_t size_val = lilv_node_as_int(d); + port_buffer_size = std::max(port_buffer_size, size_val); + } + } + lilv_nodes_free(sizes); + + bufs.engine().log().info( + Raul::fmt("Atom port %1% buffer size %2%\n") + % path().c_str() % port_buffer_size); + } + + enum { UNKNOWN, INPUT, OUTPUT } direction = UNKNOWN; + if (lilv_port_is_a(plug, id, info->lv2_InputPort)) { + direction = INPUT; + } else if (lilv_port_is_a(plug, id, info->lv2_OutputPort)) { + direction = OUTPUT; + } + + if (port_type == PortType::UNKNOWN || direction == UNKNOWN) { + parent_patch()->engine().log().error( + Raul::fmt("<%1%> port %2% has unknown type or direction\n") + % _lv2_plugin->uri().c_str() % port_sym.c_str()); + ret = false; + break; + } + + if (!val.type()) + val = forge.make(isnan(def_values[j]) ? 0.0f : def_values[j]); + + PortImpl* port = (direction == INPUT) + ? static_cast( + new InputPort(bufs, this, port_sym, j, _polyphony, + port_type, buffer_type, val)) + : static_cast( + new OutputPort(bufs, this, port_sym, j, _polyphony, + port_type, buffer_type, val)); + + port->set_morphable(is_morph, is_auto_morph); + if (direction == INPUT && (port_type == PortType::CONTROL + || port_type == PortType::CV)) { + port->set_value(val); + if (!isnan(min_values[j])) { + port->set_property(uris.lv2_minimum, forge.make(min_values[j])); + port->set_minimum(forge.make(min_values[j])); + } + if (!isnan(max_values[j])) { + port->set_property(uris.lv2_maximum, forge.make(max_values[j])); + port->set_maximum(forge.make(max_values[j])); + } + } + + // Inherit certain properties from plugin port + LilvNode* preds[] = { info->lv2_portProperty, info->atom_supports, 0 }; + for (int p = 0; preds[p]; ++p) { + LilvNodes* values = lilv_port_get_value(plug, id, preds[p]); + LILV_FOREACH(nodes, v, values) { + const LilvNode* val = lilv_nodes_get(values, v); + if (lilv_node_is_uri(val)) { + port->add_property(Raul::URI(lilv_node_as_uri(preds[p])), + forge.alloc_uri(lilv_node_as_uri(val))); + } + } + lilv_nodes_free(values); + } + + port->cache_properties(); + + _ports->at(j) = port; + } + + delete[] min_values; + delete[] max_values; + delete[] def_values; + + if (!ret) { + delete _ports; + _ports = NULL; + return ret; + } + + _features = info->world().lv2_features().lv2_features(&info->world(), this); + + // Actually create plugin instances and port buffers. + const SampleRate rate = bufs.engine().driver()->sample_rate(); + _instances = new Instances(_polyphony, SharedPtr()); + for (uint32_t i = 0; i < _polyphony; ++i) { + _instances->at(i) = make_instance(bufs.uris(), rate, i, false); + if (!_instances->at(i)) { + return false; + } + } + + // FIXME: Polyphony + worker? + if (lilv_plugin_has_feature(plug, info->work_schedule)) { + _worker_iface = (const LV2_Worker_Interface*) + lilv_instance_get_extension_data(instance(0), + LV2_WORKER__interface); + } + + return ret; +} + +void +LV2Block::activate(BufferFactory& bufs) +{ + BlockImpl::activate(bufs); + + for (uint32_t i = 0; i < _polyphony; ++i) + lilv_instance_activate(instance(i)); +} + +void +LV2Block::deactivate() +{ + BlockImpl::deactivate(); + + for (uint32_t i = 0; i < _polyphony; ++i) + lilv_instance_deactivate(instance(i)); +} + +LV2_Worker_Status +LV2Block::work_respond(LV2_Worker_Respond_Handle handle, + uint32_t size, + const void* data) +{ + LV2Block* block = (LV2Block*)handle; + LV2Block::Response* r = new LV2Block::Response(size, data); + block->_responses.push_back(*r); + return LV2_WORKER_SUCCESS; +} + +void +LV2Block::work(uint32_t size, const void* data) +{ + if (_worker_iface) { + LV2_Handle inst = lilv_instance_get_handle(instance(0)); + if (_worker_iface->work(inst, work_respond, this, size, data)) { + parent_patch()->engine().log().error( + Raul::fmt("Error calling %1% work method\n") % _path); + } + } +} + +void +LV2Block::process(ProcessContext& context) +{ + BlockImpl::pre_process(context); + + for (uint32_t i = 0; i < _polyphony; ++i) + lilv_instance_run(instance(i), context.nframes()); + + if (_worker_iface) { + LV2_Handle inst = lilv_instance_get_handle(instance(0)); + while (!_responses.empty()) { + Response& r = _responses.front(); + _worker_iface->work_response(inst, r.size, r.data); + _responses.pop_front(); + context.engine().maid()->dispose(&r); + } + + if (_worker_iface->end_run) { + _worker_iface->end_run(inst); + } + } + + BlockImpl::post_process(context); +} + +void +LV2Block::set_port_buffer(uint32_t voice, + uint32_t port_num, + BufferRef buf) +{ + BlockImpl::set_port_buffer(voice, port_num, buf); + lilv_instance_connect_port( + instance(voice), port_num, + buf ? buf->port_data(_ports->at(port_num)->type()) : NULL); +} + +} // namespace Server +} // namespace Ingen + diff --git a/src/server/LV2Block.hpp b/src/server/LV2Block.hpp new file mode 100644 index 00000000..3746b201 --- /dev/null +++ b/src/server/LV2Block.hpp @@ -0,0 +1,116 @@ +/* + This file is part of Ingen. + Copyright 2007-2012 David Robillard + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see . +*/ + +#ifndef INGEN_ENGINE_LV2BLOCK_HPP +#define INGEN_ENGINE_LV2BLOCK_HPP + +#include "lilv/lilv.h" +#include "lv2/lv2plug.in/ns/ext/worker/worker.h" +#include "raul/Disposable.hpp" + +#include "BufferRef.hpp" +#include "BlockImpl.hpp" +#include "ingen/LV2Features.hpp" +#include "types.hpp" + +namespace Ingen { +namespace Server { + +class LV2Plugin; + +/** An instance of a LV2 plugin. + * + * \ingroup engine + */ +class LV2Block : public BlockImpl +{ +public: + LV2Block(LV2Plugin* plugin, + const Raul::Symbol& symbol, + bool polyphonic, + PatchImpl* parent, + SampleRate srate); + + ~LV2Block(); + + bool instantiate(BufferFactory& bufs); + + bool prepare_poly(BufferFactory& bufs, uint32_t poly); + bool apply_poly(ProcessContext& context, Raul::Maid& maid, uint32_t poly); + + void activate(BufferFactory& bufs); + void deactivate(); + + void work(uint32_t size, const void* data); + + void process(ProcessContext& context); + + void set_port_buffer(uint32_t voice, + uint32_t port_num, + BufferRef buf); + +protected: + SharedPtr make_instance(URIs& uris, + SampleRate rate, + uint32_t voice, + bool preparing); + + inline LilvInstance* instance(uint32_t voice) { + return (LilvInstance*)(*_instances)[voice].get(); + } + + typedef Raul::Array< SharedPtr > Instances; + + struct Response : public Raul::Disposable + , public Raul::Noncopyable + , public boost::intrusive::slist_base_hook<> + { + inline Response(uint32_t s, const void* d) + : size(s) + , data(malloc(s)) + { + memcpy(data, d, s); + } + + ~Response() { + free(data); + } + + const uint32_t size; + void* const data; + }; + + typedef boost::intrusive::slist, + boost::intrusive::constant_time_size + > Responses; + + static LV2_Worker_Status work_respond( + LV2_Worker_Respond_Handle handle, uint32_t size, const void* data); + + LV2Plugin* _lv2_plugin; + Instances* _instances; + Instances* _prepared_instances; + const LV2_Worker_Interface* _worker_iface; + Responses _responses; + SharedPtr _features; +}; + +} // namespace Server +} // namespace Ingen + +#endif // INGEN_ENGINE_LV2BLOCK_HPP + diff --git a/src/server/LV2Node.cpp b/src/server/LV2Node.cpp deleted file mode 100644 index 654aeab0..00000000 --- a/src/server/LV2Node.cpp +++ /dev/null @@ -1,469 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include - -#include -#include - -#include "lv2/lv2plug.in/ns/ext/resize-port/resize-port.h" -#include "lv2/lv2plug.in/ns/ext/morph/morph.h" - -#include "raul/Maid.hpp" -#include "raul/Array.hpp" - -#include "ingen/Log.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/URIs.hpp" - -#include "Buffer.hpp" -#include "Driver.hpp" -#include "Engine.hpp" -#include "InputPort.hpp" -#include "LV2Node.hpp" -#include "LV2Plugin.hpp" -#include "OutputPort.hpp" -#include "PatchImpl.hpp" -#include "ProcessContext.hpp" - -using namespace std; - -namespace Ingen { -namespace Server { - -/** Partially construct a LV2Node. - * - * Object is not usable until instantiate() is called with success. - * (It _will_ crash!) - */ -LV2Node::LV2Node(LV2Plugin* plugin, - const Raul::Symbol& symbol, - bool polyphonic, - PatchImpl* parent, - SampleRate srate) - : NodeImpl(plugin, symbol, polyphonic, parent, srate) - , _lv2_plugin(plugin) - , _instances(NULL) - , _prepared_instances(NULL) - , _worker_iface(NULL) -{ - assert(_lv2_plugin); -} - -LV2Node::~LV2Node() -{ - delete _instances; -} - -SharedPtr -LV2Node::make_instance(URIs& uris, - SampleRate rate, - uint32_t voice, - bool preparing) -{ - LilvInstance* inst = lilv_plugin_instantiate( - _lv2_plugin->lilv_plugin(), rate, _features->array()); - - if (!inst) { - parent_patch()->engine().log().error( - Raul::fmt("Failed to instantiate <%1%>\n") - % _lv2_plugin->uri().c_str()); - return SharedPtr(); - } - - const LV2_Morph_Interface* morph_iface = (const LV2_Morph_Interface*) - lilv_instance_get_extension_data(inst, LV2_MORPH__interface); - - for (uint32_t p = 0; p < num_ports(); ++p) { - PortImpl* const port = _ports->at(p); - Buffer* const buffer = (preparing) - ? port->prepared_buffer(voice).get() - : port->buffer(voice).get(); - if (port->is_morph() && port->is_a(PortType::CV)) { - if (morph_iface) { - morph_iface->morph_port( - inst->lv2_handle, p, uris.lv2_CVPort, NULL); - } - } - - if (buffer) { - if (port->is_a(PortType::CV) || port->is_a(PortType::CONTROL)) { - buffer->set_block(port->value().get_float(), 0, buffer->nframes()); - } else { - buffer->clear(); - } - } - } - - if (morph_iface) { - for (uint32_t p = 0; p < num_ports(); ++p) { - PortImpl* const port = _ports->at(p); - if (port->is_auto_morph()) { - LV2_URID type = morph_iface->port_type( - inst->lv2_handle, p, NULL); - if (type == _uris.lv2_ControlPort) { - port->set_type(PortType::CONTROL, 0); - } else if (type == _uris.lv2_CVPort) { - port->set_type(PortType::CV, 0); - } else { - parent_patch()->engine().log().error( - Raul::fmt("%1% auto-morphed to unknown type %2%\n") - % port->path().c_str() % type); - return SharedPtr(); - } - } - } - } - - return SharedPtr(inst, lilv_instance_free); -} - -bool -LV2Node::prepare_poly(BufferFactory& bufs, uint32_t poly) -{ - if (!_polyphonic) - poly = 1; - - NodeImpl::prepare_poly(bufs, poly); - - if (_polyphony == poly) - return true; - - const SampleRate rate = bufs.engine().driver()->sample_rate(); - assert(!_prepared_instances); - _prepared_instances = new Instances(poly, *_instances, SharedPtr()); - for (uint32_t i = _polyphony; i < _prepared_instances->size(); ++i) { - SharedPtr inst = make_instance(bufs.uris(), rate, i, true); - if (!inst) { - return false; - } - - _prepared_instances->at(i) = inst; - - if (_activated) { - lilv_instance_activate(inst.get()); - } - } - - return true; -} - -bool -LV2Node::apply_poly(ProcessContext& context, Raul::Maid& maid, uint32_t poly) -{ - if (!_polyphonic) - poly = 1; - - if (_prepared_instances) { - maid.dispose(_instances); - _instances = _prepared_instances; - _prepared_instances = NULL; - } - assert(poly <= _instances->size()); - - return NodeImpl::apply_poly(context, maid, poly); -} - -/** Instantiate self from LV2 plugin descriptor. - * - * Implemented as a seperate function (rather than in the constructor) to - * allow graceful error-catching of broken plugins. - * - * Returns whether or not plugin was successfully instantiated. If return - * value is false, this object may not be used. - */ -bool -LV2Node::instantiate(BufferFactory& bufs) -{ - const Ingen::URIs& uris = bufs.uris(); - SharedPtr info = _lv2_plugin->lv2_info(); - const LilvPlugin* plug = _lv2_plugin->lilv_plugin(); - Ingen::Forge& forge = bufs.forge(); - const uint32_t num_ports = lilv_plugin_get_num_ports(plug); - - _ports = new Raul::Array(num_ports, NULL); - - bool ret = true; - - float* min_values = new float[num_ports]; - float* max_values = new float[num_ports]; - float* def_values = new float[num_ports]; - lilv_plugin_get_port_ranges_float(plug, min_values, max_values, def_values); - - // Get all the necessary information about ports - for (uint32_t j = 0; j < num_ports; ++j) { - const LilvPort* id = lilv_plugin_get_port_by_index(plug, j); - - /* LV2 port symbols are guaranteed to be unique, valid C identifiers, - and Lilv guarantees that lilv_port_get_symbol() is valid. */ - const Raul::Symbol port_sym( - lilv_node_as_string(lilv_port_get_symbol(plug, id))); - - // Get port type - Raul::Atom val; - PortType port_type = PortType::UNKNOWN; - LV2_URID buffer_type = 0; - bool is_morph = false; - bool is_auto_morph = false; - if (lilv_port_is_a(plug, id, info->lv2_ControlPort)) { - if (lilv_port_is_a(plug, id, info->morph_MorphPort)) { - is_morph = true; - LilvNodes* types = lilv_port_get_value( - plug, id, info->morph_supportsType); - LILV_FOREACH(nodes, i, types) { - const LilvNode* type = lilv_nodes_get(types, i); - if (lilv_node_equals(type, info->lv2_CVPort)) { - port_type = PortType::CV; - buffer_type = uris.atom_Sound; - } - } - lilv_nodes_free(types); - } - if (port_type == PortType::UNKNOWN) { - port_type = PortType::CONTROL; - buffer_type = uris.atom_Float; - } - } else if (lilv_port_is_a(plug, id, info->lv2_CVPort)) { - port_type = PortType::CV; - buffer_type = uris.atom_Sound; - } else if (lilv_port_is_a(plug, id, info->lv2_AudioPort)) { - port_type = PortType::AUDIO; - buffer_type = uris.atom_Sound; - } else if (lilv_port_is_a(plug, id, info->atom_AtomPort)) { - port_type = PortType::ATOM; - } - - if (lilv_port_is_a(plug, id, info->morph_AutoMorphPort)) { - is_auto_morph = true; - } - - // Get buffer type if necessary (atom ports) - if (!buffer_type) { - LilvNodes* types = lilv_port_get_value( - plug, id, info->atom_bufferType); - LILV_FOREACH(nodes, i, types) { - const LilvNode* type = lilv_nodes_get(types, i); - if (lilv_node_is_uri(type)) { - buffer_type = bufs.engine().world()->uri_map().map_uri( - lilv_node_as_uri(type)); - } - } - lilv_nodes_free(types); - } - - uint32_t port_buffer_size = bufs.default_size(buffer_type); - - if (port_type == PortType::ATOM) { - // Get default value, and its length - LilvNodes* defaults = lilv_port_get_value(plug, id, info->lv2_default); - LILV_FOREACH(nodes, i, defaults) { - const LilvNode* d = lilv_nodes_get(defaults, i); - if (lilv_node_is_string(d)) { - const char* str_val = lilv_node_as_string(d); - const uint32_t str_val_len = strlen(str_val); - val = forge.alloc(str_val); - port_buffer_size = std::max(port_buffer_size, str_val_len); - } - } - lilv_nodes_free(defaults); - - // Get minimum size, if set in data - LilvNodes* sizes = lilv_port_get_value(plug, id, info->rsz_minimumSize); - LILV_FOREACH(nodes, i, sizes) { - const LilvNode* d = lilv_nodes_get(sizes, i); - if (lilv_node_is_int(d)) { - uint32_t size_val = lilv_node_as_int(d); - port_buffer_size = std::max(port_buffer_size, size_val); - } - } - lilv_nodes_free(sizes); - - bufs.engine().log().info( - Raul::fmt("Atom port %1% buffer size %2%\n") - % path().c_str() % port_buffer_size); - } - - enum { UNKNOWN, INPUT, OUTPUT } direction = UNKNOWN; - if (lilv_port_is_a(plug, id, info->lv2_InputPort)) { - direction = INPUT; - } else if (lilv_port_is_a(plug, id, info->lv2_OutputPort)) { - direction = OUTPUT; - } - - if (port_type == PortType::UNKNOWN || direction == UNKNOWN) { - parent_patch()->engine().log().error( - Raul::fmt("<%1%> port %2% has unknown type or direction\n") - % _lv2_plugin->uri().c_str() % port_sym.c_str()); - ret = false; - break; - } - - if (!val.type()) - val = forge.make(isnan(def_values[j]) ? 0.0f : def_values[j]); - - PortImpl* port = (direction == INPUT) - ? static_cast( - new InputPort(bufs, this, port_sym, j, _polyphony, - port_type, buffer_type, val)) - : static_cast( - new OutputPort(bufs, this, port_sym, j, _polyphony, - port_type, buffer_type, val)); - - port->set_morphable(is_morph, is_auto_morph); - if (direction == INPUT && (port_type == PortType::CONTROL - || port_type == PortType::CV)) { - port->set_value(val); - if (!isnan(min_values[j])) { - port->set_property(uris.lv2_minimum, forge.make(min_values[j])); - port->set_minimum(forge.make(min_values[j])); - } - if (!isnan(max_values[j])) { - port->set_property(uris.lv2_maximum, forge.make(max_values[j])); - port->set_maximum(forge.make(max_values[j])); - } - } - - // Inherit certain properties from plugin port - LilvNode* preds[] = { info->lv2_portProperty, info->atom_supports, 0 }; - for (int p = 0; preds[p]; ++p) { - LilvNodes* values = lilv_port_get_value(plug, id, preds[p]); - LILV_FOREACH(nodes, v, values) { - const LilvNode* val = lilv_nodes_get(values, v); - if (lilv_node_is_uri(val)) { - port->add_property(Raul::URI(lilv_node_as_uri(preds[p])), - forge.alloc_uri(lilv_node_as_uri(val))); - } - } - lilv_nodes_free(values); - } - - port->cache_properties(); - - _ports->at(j) = port; - } - - delete[] min_values; - delete[] max_values; - delete[] def_values; - - if (!ret) { - delete _ports; - _ports = NULL; - return ret; - } - - _features = info->world().lv2_features().lv2_features(&info->world(), this); - - // Actually create plugin instances and port buffers. - const SampleRate rate = bufs.engine().driver()->sample_rate(); - _instances = new Instances(_polyphony, SharedPtr()); - for (uint32_t i = 0; i < _polyphony; ++i) { - _instances->at(i) = make_instance(bufs.uris(), rate, i, false); - if (!_instances->at(i)) { - return false; - } - } - - // FIXME: Polyphony + worker? - if (lilv_plugin_has_feature(plug, info->work_schedule)) { - _worker_iface = (const LV2_Worker_Interface*) - lilv_instance_get_extension_data(instance(0), - LV2_WORKER__interface); - } - - return ret; -} - -void -LV2Node::activate(BufferFactory& bufs) -{ - NodeImpl::activate(bufs); - - for (uint32_t i = 0; i < _polyphony; ++i) - lilv_instance_activate(instance(i)); -} - -void -LV2Node::deactivate() -{ - NodeImpl::deactivate(); - - for (uint32_t i = 0; i < _polyphony; ++i) - lilv_instance_deactivate(instance(i)); -} - -LV2_Worker_Status -LV2Node::work_respond(LV2_Worker_Respond_Handle handle, - uint32_t size, - const void* data) -{ - LV2Node* node = (LV2Node*)handle; - LV2Node::Response* r = new LV2Node::Response(size, data); - node->_responses.push_back(*r); - return LV2_WORKER_SUCCESS; -} - -void -LV2Node::work(uint32_t size, const void* data) -{ - if (_worker_iface) { - LV2_Handle inst = lilv_instance_get_handle(instance(0)); - if (_worker_iface->work(inst, work_respond, this, size, data)) { - parent_patch()->engine().log().error( - Raul::fmt("Error calling %1% work method\n") % _path); - } - } -} - -void -LV2Node::process(ProcessContext& context) -{ - NodeImpl::pre_process(context); - - for (uint32_t i = 0; i < _polyphony; ++i) - lilv_instance_run(instance(i), context.nframes()); - - if (_worker_iface) { - LV2_Handle inst = lilv_instance_get_handle(instance(0)); - while (!_responses.empty()) { - Response& r = _responses.front(); - _worker_iface->work_response(inst, r.size, r.data); - _responses.pop_front(); - context.engine().maid()->dispose(&r); - } - - if (_worker_iface->end_run) { - _worker_iface->end_run(inst); - } - } - - NodeImpl::post_process(context); -} - -void -LV2Node::set_port_buffer(uint32_t voice, - uint32_t port_num, - BufferRef buf) -{ - NodeImpl::set_port_buffer(voice, port_num, buf); - lilv_instance_connect_port( - instance(voice), port_num, - buf ? buf->port_data(_ports->at(port_num)->type()) : NULL); -} - -} // namespace Server -} // namespace Ingen - diff --git a/src/server/LV2Node.hpp b/src/server/LV2Node.hpp deleted file mode 100644 index e7f8eae6..00000000 --- a/src/server/LV2Node.hpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_ENGINE_LV2NODE_HPP -#define INGEN_ENGINE_LV2NODE_HPP - -#include "lilv/lilv.h" -#include "lv2/lv2plug.in/ns/ext/worker/worker.h" -#include "raul/Disposable.hpp" - -#include "BufferRef.hpp" -#include "NodeImpl.hpp" -#include "ingen/LV2Features.hpp" -#include "types.hpp" - -namespace Ingen { -namespace Server { - -class LV2Plugin; - -/** An instance of a LV2 plugin. - * - * \ingroup engine - */ -class LV2Node : public NodeImpl -{ -public: - LV2Node(LV2Plugin* plugin, - const Raul::Symbol& symbol, - bool polyphonic, - PatchImpl* parent, - SampleRate srate); - - ~LV2Node(); - - bool instantiate(BufferFactory& bufs); - - bool prepare_poly(BufferFactory& bufs, uint32_t poly); - bool apply_poly(ProcessContext& context, Raul::Maid& maid, uint32_t poly); - - void activate(BufferFactory& bufs); - void deactivate(); - - void work(uint32_t size, const void* data); - - void process(ProcessContext& context); - - void set_port_buffer(uint32_t voice, - uint32_t port_num, - BufferRef buf); - -protected: - SharedPtr make_instance(URIs& uris, - SampleRate rate, - uint32_t voice, - bool preparing); - - inline LilvInstance* instance(uint32_t voice) { - return (LilvInstance*)(*_instances)[voice].get(); - } - - typedef Raul::Array< SharedPtr > Instances; - - struct Response : public Raul::Disposable - , public Raul::Noncopyable - , public boost::intrusive::slist_base_hook<> - { - inline Response(uint32_t s, const void* d) - : size(s) - , data(malloc(s)) - { - memcpy(data, d, s); - } - - ~Response() { - free(data); - } - - const uint32_t size; - void* const data; - }; - - typedef boost::intrusive::slist, - boost::intrusive::constant_time_size - > Responses; - - static LV2_Worker_Status work_respond( - LV2_Worker_Respond_Handle handle, uint32_t size, const void* data); - - LV2Plugin* _lv2_plugin; - Instances* _instances; - Instances* _prepared_instances; - const LV2_Worker_Interface* _worker_iface; - Responses _responses; - SharedPtr _features; -}; - -} // namespace Server -} // namespace Ingen - -#endif // INGEN_ENGINE_LV2NODE_HPP - diff --git a/src/server/LV2Plugin.cpp b/src/server/LV2Plugin.cpp index 0e2a16b2..0febfc7d 100644 --- a/src/server/LV2Plugin.cpp +++ b/src/server/LV2Plugin.cpp @@ -20,7 +20,7 @@ #include "Driver.hpp" #include "Engine.hpp" -#include "LV2Node.hpp" +#include "LV2Block.hpp" #include "LV2Plugin.hpp" using namespace std; @@ -56,21 +56,21 @@ LV2Plugin::symbol() const return Raul::Symbol("lv2_symbol"); } -NodeImpl* +BlockImpl* LV2Plugin::instantiate(BufferFactory& bufs, const Raul::Symbol& symbol, bool polyphonic, PatchImpl* parent, Engine& engine) { - LV2Node* n = new LV2Node( + LV2Block* b = new LV2Block( this, symbol, polyphonic, parent, engine.driver()->sample_rate()); - if (!n->instantiate(bufs)) { - delete n; + if (!b->instantiate(bufs)) { + delete b; return NULL; } else { - return n; + return b; } } diff --git a/src/server/LV2Plugin.hpp b/src/server/LV2Plugin.hpp index 226d61ab..ed26b4ae 100644 --- a/src/server/LV2Plugin.hpp +++ b/src/server/LV2Plugin.hpp @@ -30,7 +30,7 @@ namespace Ingen { namespace Server { class PatchImpl; -class NodeImpl; +class BlockImpl; /** Implementation of an LV2 plugin (loaded shared library). */ @@ -39,11 +39,11 @@ class LV2Plugin : public PluginImpl public: LV2Plugin(SharedPtr lv2_info, const Raul::URI& uri); - NodeImpl* instantiate(BufferFactory& bufs, - const Raul::Symbol& symbol, - bool polyphonic, - PatchImpl* parent, - Engine& engine); + BlockImpl* instantiate(BufferFactory& bufs, + const Raul::Symbol& symbol, + bool polyphonic, + PatchImpl* parent, + Engine& engine); const Raul::Symbol symbol() const; diff --git a/src/server/LV2ResizeFeature.hpp b/src/server/LV2ResizeFeature.hpp index eeab3d4a..5b385a2f 100644 --- a/src/server/LV2ResizeFeature.hpp +++ b/src/server/LV2ResizeFeature.hpp @@ -20,9 +20,9 @@ #include "ingen/LV2Features.hpp" #include "lv2/lv2plug.in/ns/ext/resize-port/resize-port.h" -#include "NodeImpl.hpp" -#include "PortImpl.hpp" +#include "BlockImpl.hpp" #include "Buffer.hpp" +#include "PortImpl.hpp" namespace Ingen { namespace Server { @@ -32,9 +32,9 @@ struct ResizeFeature : public Ingen::LV2Features::Feature { LV2_Resize_Port_Feature_Data data, uint32_t index, size_t size) { - NodeImpl* node = (NodeImpl*)data; - PortImpl* port = node->port_impl(index); - if (node->context() == Context::MESSAGE) { + BlockImpl* block = (BlockImpl*)data; + PortImpl* port = block->port_impl(index); + if (block->context() == Context::MESSAGE) { port->buffer(0)->resize(size); port->connect_buffers(); return LV2_RESIZE_PORT_SUCCESS; @@ -48,12 +48,12 @@ struct ResizeFeature : public Ingen::LV2Features::Feature { } SharedPtr feature(World* w, GraphObject* n) { - NodeImpl* node = dynamic_cast(n); - if (!node) + BlockImpl* block = dynamic_cast(n); + if (!block) return SharedPtr(); LV2_Resize_Port_Resize* data = (LV2_Resize_Port_Resize*)malloc(sizeof(LV2_Resize_Port_Resize)); - data->data = node; + data->data = block; data->resize = &resize_port; LV2_Feature* f = (LV2_Feature*)malloc(sizeof(LV2_Feature)); f->URI = LV2_RESIZE_PORT_URI; diff --git a/src/server/NodeFactory.cpp b/src/server/NodeFactory.cpp deleted file mode 100644 index 6683658b..00000000 --- a/src/server/NodeFactory.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include - -#include "lilv/lilv.h" - -#include "ingen/World.hpp" -#include "internals/Controller.hpp" -#include "internals/Delay.hpp" -#include "internals/Note.hpp" -#include "internals/Trigger.hpp" - -#include "InternalPlugin.hpp" -#include "LV2Plugin.hpp" -#include "NodeFactory.hpp" -#include "ThreadManager.hpp" - -using namespace std; - -namespace Ingen { -namespace Server { - -using namespace Internals; - -NodeFactory::NodeFactory(Ingen::World* world) - : _world(world) - , _lv2_info(new LV2Info(world)) - , _has_loaded(false) -{ - load_internal_plugins(); -} - -NodeFactory::~NodeFactory() -{ - for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) - delete i->second; - - _plugins.clear(); -} - -const NodeFactory::Plugins& -NodeFactory::plugins() -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - if (!_has_loaded) { - _has_loaded = true; - // TODO: Plugin list refreshing - load_lv2_plugins(); - _has_loaded = true; - } - return _plugins; -} - -PluginImpl* -NodeFactory::plugin(const Raul::URI& uri) -{ - load_plugin(uri); - const Plugins::const_iterator i = _plugins.find(uri); - return ((i != _plugins.end()) ? i->second : NULL); -} - -void -NodeFactory::load_internal_plugins() -{ - Ingen::URIs& uris = _world->uris(); - InternalPlugin* controller_plug = ControllerNode::internal_plugin(uris); - _plugins.insert(make_pair(controller_plug->uri(), controller_plug)); - - InternalPlugin* delay_plug = DelayNode::internal_plugin(uris); - _plugins.insert(make_pair(delay_plug->uri(), delay_plug)); - - InternalPlugin* note_plug = NoteNode::internal_plugin(uris); - _plugins.insert(make_pair(note_plug->uri(), note_plug)); - - InternalPlugin* trigger_plug = TriggerNode::internal_plugin(uris); - _plugins.insert(make_pair(trigger_plug->uri(), trigger_plug)); -} - -void -NodeFactory::load_plugin(const Raul::URI& uri) -{ - if (_has_loaded || _plugins.find(uri) != _plugins.end()) { - return; - } - - LilvNode* node = lilv_new_uri(_world->lilv_world(), uri.c_str()); - const LilvPlugins* plugs = lilv_world_get_all_plugins(_world->lilv_world()); - const LilvPlugin* plug = lilv_plugins_get_by_uri(plugs, node); - if (plug) { - LV2Plugin* const ingen_plugin = new LV2Plugin(_lv2_info, uri); - ingen_plugin->lilv_plugin(plug); - _plugins.insert(make_pair(uri, ingen_plugin)); - } - lilv_node_free(node); -} - -/** Loads information about all LV2 plugins into internal plugin database. - */ -void -NodeFactory::load_lv2_plugins() -{ - const LilvPlugins* plugins = lilv_world_get_all_plugins(_world->lilv_world()); - LILV_FOREACH(plugins, i, plugins) { - const LilvPlugin* lv2_plug = lilv_plugins_get(plugins, i); - - const Raul::URI uri(lilv_node_as_uri(lilv_plugin_get_uri(lv2_plug))); - - if (_plugins.find(uri) != _plugins.end()) { - continue; - } - - LV2Plugin* const plugin = new LV2Plugin(_lv2_info, uri); - - plugin->lilv_plugin(lv2_plug); - _plugins.insert(make_pair(uri, plugin)); - } -} - -} // namespace Server -} // namespace Ingen diff --git a/src/server/NodeFactory.hpp b/src/server/NodeFactory.hpp deleted file mode 100644 index 502d7757..00000000 --- a/src/server/NodeFactory.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_ENGINE_NODEFACTORY_HPP -#define INGEN_ENGINE_NODEFACTORY_HPP - -#include - -#include "ingen/World.hpp" -#include "raul/Noncopyable.hpp" -#include "raul/SharedPtr.hpp" -#include "raul/URI.hpp" - -namespace Ingen { -namespace Server { - -class NodeImpl; -class PatchImpl; -class PluginImpl; -class LV2Info; - -/** Discovers and loads plugin libraries. - * - * \ingroup engine - */ -class NodeFactory : public Raul::Noncopyable -{ -public: - explicit NodeFactory(Ingen::World* world); - ~NodeFactory(); - - void load_plugin(const Raul::URI& uri); - - typedef std::map Plugins; - const Plugins& plugins(); - - PluginImpl* plugin(const Raul::URI& uri); - -private: - void load_lv2_plugins(); - void load_internal_plugins(); - - Plugins _plugins; - Ingen::World* _world; - SharedPtr _lv2_info; - bool _has_loaded; -}; - -} // namespace Server -} // namespace Ingen - -#endif // INGEN_ENGINE_NODEFACTORY_HPP diff --git a/src/server/NodeImpl.cpp b/src/server/NodeImpl.cpp deleted file mode 100644 index f1f6c362..00000000 --- a/src/server/NodeImpl.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include - -#include "raul/Array.hpp" - -#include "Buffer.hpp" -#include "Engine.hpp" -#include "NodeImpl.hpp" -#include "PatchImpl.hpp" -#include "PluginImpl.hpp" -#include "PortImpl.hpp" -#include "ProcessContext.hpp" -#include "ThreadManager.hpp" - -using namespace std; - -namespace Ingen { -namespace Server { - -NodeImpl::NodeImpl(PluginImpl* plugin, - const Raul::Symbol& symbol, - bool polyphonic, - PatchImpl* parent, - SampleRate srate) - : GraphObjectImpl(plugin->uris(), parent, symbol) - , _plugin(plugin) - , _ports(NULL) - , _context(Context::AUDIO) - , _polyphony((polyphonic && parent) ? parent->internal_poly() : 1) - , _polyphonic(polyphonic) - , _activated(false) - , _traversed(false) -{ - assert(_plugin); - assert(_polyphony > 0); -} - -NodeImpl::~NodeImpl() -{ - if (_activated) { - deactivate(); - } - - if (is_linked()) { - parent_patch()->remove_node(*this); - } - - delete _ports; -} - -GraphObject* -NodeImpl::port(uint32_t index) const -{ - return (*_ports)[index]; -} - -const Plugin* -NodeImpl::plugin() const -{ - return _plugin; -} - -void -NodeImpl::activate(BufferFactory& bufs) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - - _activated = true; - for (uint32_t p = 0; p < num_ports(); ++p) { - PortImpl* const port = _ports->at(p); - port->setup_buffers(bufs, port->poly(), false); - port->connect_buffers(); - port->clear_buffers(); - } -} - -void -NodeImpl::deactivate() -{ - _activated = false; - for (uint32_t i = 0; i < _polyphony; ++i) { - for (uint32_t j = 0; j < num_ports(); ++j) { - PortImpl* const port = _ports->at(j); - if (port->is_output() && port->buffer(i)) - port->buffer(i)->clear(); - } - } -} - -bool -NodeImpl::prepare_poly(BufferFactory& bufs, uint32_t poly) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - - if (!_polyphonic) - poly = 1; - - if (_ports) - for (uint32_t i = 0; i < _ports->size(); ++i) - _ports->at(i)->prepare_poly(bufs, poly); - - return true; -} - -bool -NodeImpl::apply_poly(ProcessContext& context, Raul::Maid& maid, uint32_t poly) -{ - if (!_polyphonic) - poly = 1; - - _polyphony = poly; - - if (_ports) - for (uint32_t i = 0; i < num_ports(); ++i) - _ports->at(i)->apply_poly(context, maid, poly); - - return true; -} - -void -NodeImpl::set_buffer_size(Context& context, - BufferFactory& bufs, - LV2_URID type, - uint32_t size) -{ - if (_ports) { - for (uint32_t i = 0; i < _ports->size(); ++i) { - PortImpl* const p = _ports->at(i); - if (p->buffer_type() == type) { - p->set_buffer_size(context, bufs, size); - } - } - } -} - -/** Prepare to run a cycle (in the audio thread) - */ -void -NodeImpl::pre_process(ProcessContext& context) -{ - // Mix down input ports - for (uint32_t i = 0; i < num_ports(); ++i) { - PortImpl* const port = _ports->at(i); - port->pre_process(context); - port->connect_buffers(); - } -} - -/** Prepare to run a cycle (in the audio thread) - */ -void -NodeImpl::post_process(ProcessContext& context) -{ - // Write output ports - for (uint32_t i = 0; _ports && i < _ports->size(); ++i) { - _ports->at(i)->post_process(context); - } -} - -void -NodeImpl::set_port_buffer(uint32_t voice, - uint32_t port_num, - BufferRef buf) -{ - /*std::cout << path() << " set port " << port_num << " voice " << voice - << " buffer " << buf << " offset " << offset << std::endl;*/ -} - -} // namespace Server -} // namespace Ingen - diff --git a/src/server/NodeImpl.hpp b/src/server/NodeImpl.hpp deleted file mode 100644 index 86741156..00000000 --- a/src/server/NodeImpl.hpp +++ /dev/null @@ -1,175 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_ENGINE_NODEIMPL_HPP -#define INGEN_ENGINE_NODEIMPL_HPP - -#include - -#include - -#include "raul/Array.hpp" -#include "raul/AtomicInt.hpp" - -#include "BufferRef.hpp" -#include "Context.hpp" -#include "GraphObjectImpl.hpp" -#include "PortType.hpp" -#include "types.hpp" - -namespace Raul { -class Maid; -} - -namespace Ingen { - -class Plugin; - -namespace Server { - -class Buffer; -class BufferFactory; -class Context; -class PatchImpl; -class PluginImpl; -class PortImpl; -class ProcessContext; - -/** A Node (or "module") in a Patch (which is also a Node). - * - * A Node is a unit with input/output ports, a process() method, and some other - * things. - * - * \ingroup engine - */ -class NodeImpl : public GraphObjectImpl - , public boost::intrusive::slist_base_hook<> // In PatchImpl -{ -public: - NodeImpl(PluginImpl* plugin, - const Raul::Symbol& symbol, - bool poly, - PatchImpl* parent, - SampleRate rate); - - virtual ~NodeImpl(); - - virtual GraphType graph_type() const { return NODE; } - - /** Activate this Node. - * - * 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); - - /** 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 deactivate(); - - /** Return true iff this node is activated */ - bool activated() { return _activated; } - - /** Learn the next incoming MIDI event (for internals) */ - virtual void learn() {} - - /** Do whatever needs doing in the process thread before process() is called */ - virtual void pre_process(ProcessContext& context); - - /** Run the node for @a nframes input/output. - * - * @a start and @a end are transport times: end is not redundant in the case - * of varispeed, where end-start != nframes. - */ - virtual void process(ProcessContext& context) = 0; - - /** Do whatever needs doing in the process thread after process() is called */ - virtual void post_process(ProcessContext& context); - - /** 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, - BufferRef buf); - - virtual GraphObject* 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. */ - std::list& providers() { return _providers; } - - /** Nodes are are connected to this Node's outputs. */ - std::list& dependants() { return _dependants; } - - /** 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( - ProcessContext& context, 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 (e.g. Patch) - */ - 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 Plugin* plugin() const; - - virtual void plugin(PluginImpl* pi) { _plugin = pi; } - - virtual void set_buffer_size(Context& context, - BufferFactory& bufs, - LV2_URID type, - uint32_t size); - - /** The Patch this Node belongs to. */ - inline PatchImpl* parent_patch() const { return (PatchImpl*)_parent; } - - Context::ID context() const { return _context; } - 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; - Raul::Array* _ports; ///< Access in audio thread only - Context::ID _context; ///< Context this node runs in - uint32_t _polyphony; - std::list _providers; ///< Nodes connected to this one's input ports - std::list _dependants; ///< Nodes this one's output ports are connected to - bool _polyphonic; - bool _activated; - bool _traversed; ///< Flag for process order algorithm -}; - -} // namespace Server -} // namespace Ingen - -#endif // INGEN_ENGINE_NODEIMPL_HPP diff --git a/src/server/OutputPort.cpp b/src/server/OutputPort.cpp index 7558dda3..1fa53451 100644 --- a/src/server/OutputPort.cpp +++ b/src/server/OutputPort.cpp @@ -19,7 +19,7 @@ #include "Buffer.hpp" #include "BufferFactory.hpp" #include "Engine.hpp" -#include "NodeImpl.hpp" +#include "BlockImpl.hpp" #include "OutputPort.hpp" using namespace std; @@ -28,7 +28,7 @@ namespace Ingen { namespace Server { OutputPort::OutputPort(BufferFactory& bufs, - NodeImpl* parent, + BlockImpl* parent, const Raul::Symbol& symbol, uint32_t index, uint32_t poly, diff --git a/src/server/OutputPort.hpp b/src/server/OutputPort.hpp index 2156c2ab..b117847f 100644 --- a/src/server/OutputPort.hpp +++ b/src/server/OutputPort.hpp @@ -39,7 +39,7 @@ class OutputPort : virtual public PortImpl { public: OutputPort(BufferFactory& bufs, - NodeImpl* parent, + BlockImpl* parent, const Raul::Symbol& symbol, uint32_t index, uint32_t poly, diff --git a/src/server/PatchImpl.cpp b/src/server/PatchImpl.cpp index b280886e..ae16c634 100644 --- a/src/server/PatchImpl.cpp +++ b/src/server/PatchImpl.cpp @@ -20,11 +20,11 @@ #include "ingen/URIs.hpp" #include "ingen/World.hpp" +#include "BlockImpl.hpp" #include "BufferFactory.hpp" -#include "EdgeImpl.hpp" #include "DuplexPort.hpp" +#include "EdgeImpl.hpp" #include "Engine.hpp" -#include "NodeImpl.hpp" #include "PatchImpl.hpp" #include "PatchPlugin.hpp" #include "PortImpl.hpp" @@ -41,10 +41,10 @@ PatchImpl::PatchImpl(Engine& engine, PatchImpl* parent, SampleRate srate, uint32_t internal_poly) - : NodeImpl(new PatchPlugin(engine.world()->uris(), - engine.world()->uris().ingen_Patch, - Raul::Symbol("patch"), - "Ingen Patch"), + : BlockImpl(new PatchPlugin(engine.world()->uris(), + engine.world()->uris().ingen_Patch, + Raul::Symbol("patch"), + "Ingen Patch"), symbol, poly, parent, srate) , _engine(engine) , _poly_pre(internal_poly) @@ -65,9 +65,9 @@ PatchImpl::~PatchImpl() void PatchImpl::activate(BufferFactory& bufs) { - NodeImpl::activate(bufs); + BlockImpl::activate(bufs); - for (Nodes::iterator i = _nodes.begin(); i != _nodes.end(); ++i) { + for (Blocks::iterator i = _blocks.begin(); i != _blocks.end(); ++i) { i->activate(bufs); } @@ -78,9 +78,9 @@ void PatchImpl::deactivate() { if (_activated) { - NodeImpl::deactivate(); + BlockImpl::deactivate(); - for (Nodes::iterator i = _nodes.begin(); i != _nodes.end(); ++i) { + for (Blocks::iterator i = _blocks.begin(); i != _blocks.end(); ++i) { if (i->activated()) { i->deactivate(); } @@ -104,7 +104,7 @@ PatchImpl::prepare_internal_poly(BufferFactory& bufs, uint32_t poly) // TODO: Subpatch dynamic polyphony (i.e. changing port polyphony) - for (Nodes::iterator i = _nodes.begin(); i != _nodes.end(); ++i) { + for (Blocks::iterator i = _blocks.begin(); i != _blocks.end(); ++i) { i->prepare_poly(bufs, poly); } @@ -120,11 +120,11 @@ PatchImpl::apply_internal_poly(ProcessContext& context, { // TODO: Subpatch dynamic polyphony (i.e. changing port polyphony) - for (Nodes::iterator i = _nodes.begin(); i != _nodes.end(); ++i) { + for (Blocks::iterator i = _blocks.begin(); i != _blocks.end(); ++i) { i->apply_poly(context, maid, poly); } - for (Nodes::iterator i = _nodes.begin(); i != _nodes.end(); ++i) { + for (Blocks::iterator i = _blocks.begin(); i != _blocks.end(); ++i) { for (uint32_t j = 0; j < i->num_ports(); ++j) { PortImpl* const port = i->port_impl(j); if (port->is_input() && dynamic_cast(port)->direct_connect()) @@ -143,7 +143,7 @@ PatchImpl::apply_internal_poly(ProcessContext& context, /** Run the patch for the specified number of frames. * - * Calls all Nodes in (roughly, if parallel) the order _compiled_patch specifies. + * Calls all Blocks in (roughly, if parallel) the order _compiled_patch specifies. */ void PatchImpl::process(ProcessContext& context) @@ -151,16 +151,16 @@ PatchImpl::process(ProcessContext& context) if (!_process) return; - NodeImpl::pre_process(context); + BlockImpl::pre_process(context); if (_compiled_patch && _compiled_patch->size() > 0) { - // Run all nodes + // Run all blocks for (size_t i = 0; i < _compiled_patch->size(); ++i) { - (*_compiled_patch)[i].node()->process(context); + (*_compiled_patch)[i].block()->process(context); } } - NodeImpl::post_process(context); + BlockImpl::post_process(context); } void @@ -169,31 +169,31 @@ PatchImpl::set_buffer_size(Context& context, LV2_URID type, uint32_t size) { - NodeImpl::set_buffer_size(context, bufs, type, size); + BlockImpl::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); + (*_compiled_patch)[i].block()->set_buffer_size(context, bufs, type, size); } // Patch specific stuff -/** Add a node. +/** Add a block. * Preprocessing thread only. */ void -PatchImpl::add_node(NodeImpl& node) +PatchImpl::add_block(BlockImpl& block) { ThreadManager::assert_thread(THREAD_PRE_PROCESS); - _nodes.push_front(node); + _blocks.push_front(block); } -/** Remove a node. +/** Remove a block. * Preprocessing thread only. */ void -PatchImpl::remove_node(NodeImpl& node) +PatchImpl::remove_block(BlockImpl& block) { - _nodes.erase(_nodes.iterator_to(node)); + _blocks.erase(_blocks.iterator_to(block)); } void @@ -317,7 +317,7 @@ PatchImpl::build_ports_array() } static inline void -compile_recursive(NodeImpl* n, CompiledPatch* output) +compile_recursive(BlockImpl* n, CompiledPatch* output) { if (n == NULL || n->traversed()) return; @@ -325,12 +325,12 @@ compile_recursive(NodeImpl* n, CompiledPatch* output) n->traversed(true); assert(output != NULL); - for (std::list::iterator i = n->providers().begin(); + for (std::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())); + output->push_back(CompiledBlock(n, n->providers().size(), n->dependants())); } /** Find the process order for this Patch. @@ -350,25 +350,25 @@ PatchImpl::compile() CompiledPatch* const compiled_patch = new CompiledPatch(); - for (Nodes::iterator i = _nodes.begin(); i != _nodes.end(); ++i) { + for (Blocks::iterator i = _blocks.begin(); i != _blocks.end(); ++i) { i->traversed(false); } - for (Nodes::iterator i = _nodes.begin(); i != _nodes.end(); ++i) { + for (Blocks::iterator i = _blocks.begin(); i != _blocks.end(); ++i) { // Either a sink or connected to our output ports: if (!i->traversed() && i->dependants().empty()) { compile_recursive(&*i, compiled_patch); } } - // Traverse any nodes we didn't hit yet - for (Nodes::iterator i = _nodes.begin(); i != _nodes.end(); ++i) { + // Traverse any blocks we didn't hit yet + for (Blocks::iterator i = _blocks.begin(); i != _blocks.end(); ++i) { if (!i->traversed()) { compile_recursive(&*i, compiled_patch); } } - if (compiled_patch->size() != _nodes.size()) { + if (compiled_patch->size() != _blocks.size()) { _engine.log().error(Raul::fmt("Failed to compile patch %1%\n") % _path); delete compiled_patch; return NULL; diff --git a/src/server/PatchImpl.hpp b/src/server/PatchImpl.hpp index badbfb81..fa212b1a 100644 --- a/src/server/PatchImpl.hpp +++ b/src/server/PatchImpl.hpp @@ -19,9 +19,9 @@ #include +#include "BlockImpl.hpp" #include "CompiledPatch.hpp" #include "DuplexPort.hpp" -#include "NodeImpl.hpp" #include "PluginImpl.hpp" #include "PortType.hpp" #include "ThreadManager.hpp" @@ -38,15 +38,15 @@ class Context; class Engine; class ProcessContext; -/** A group of nodes in a graph, possibly polyphonic. +/** A group of blocks in a graph, possibly polyphonic. * - * Note that this is also a Node, just one which contains Nodes. + * Note that this is also a Block, just one which contains Blocks. * Therefore infinite subpatching is possible, of polyphonic - * patches of polyphonic nodes etc. etc. + * patches of polyphonic blocks etc. etc. * * \ingroup engine */ -class PatchImpl : public NodeImpl +class PatchImpl : public BlockImpl { public: PatchImpl(Engine& engine, @@ -91,16 +91,16 @@ public: Raul::Maid& maid, uint32_t poly); - // Patch specific stuff not inherited from Node + // Patch specific stuff not inherited from Block typedef boost::intrusive::slist< - NodeImpl, boost::intrusive::constant_time_size > Nodes; + BlockImpl, boost::intrusive::constant_time_size > Blocks; - void add_node(NodeImpl& node); - void remove_node(NodeImpl& node); + void add_block(BlockImpl& block); + void remove_block(BlockImpl& block); - Nodes& nodes() { return _nodes; } - const Nodes& nodes() const { return _nodes; } + Blocks& blocks() { return _blocks; } + const Blocks& blocks() const { return _blocks; } uint32_t num_ports_non_rt() const; @@ -161,7 +161,7 @@ private: CompiledPatch* _compiled_patch; ///< Process thread only Ports _inputs; ///< Pre-process thread only Ports _outputs; ///< Pre-process thread only - Nodes _nodes; ///< Pre-process thread only + Blocks _blocks; ///< Pre-process thread only bool _process; }; diff --git a/src/server/PatchPlugin.hpp b/src/server/PatchPlugin.hpp index ba1cfa40..1fd9069f 100644 --- a/src/server/PatchPlugin.hpp +++ b/src/server/PatchPlugin.hpp @@ -23,7 +23,7 @@ namespace Ingen { namespace Server { -class NodeImpl; +class BlockImpl; /** Implementation of a Patch plugin. * @@ -39,11 +39,11 @@ public: : PluginImpl(uris, Plugin::Patch, uri) {} - NodeImpl* instantiate(BufferFactory& bufs, - const Raul::Symbol& symbol, - bool polyphonic, - PatchImpl* parent, - Engine& engine) + BlockImpl* instantiate(BufferFactory& bufs, + const Raul::Symbol& symbol, + bool polyphonic, + PatchImpl* parent, + Engine& engine) { return NULL; } diff --git a/src/server/PluginImpl.hpp b/src/server/PluginImpl.hpp index 13e78b1f..624b3f6d 100644 --- a/src/server/PluginImpl.hpp +++ b/src/server/PluginImpl.hpp @@ -32,14 +32,14 @@ class URIs; namespace Server { -class PatchImpl; -class NodeImpl; -class Engine; +class BlockImpl; class BufferFactory; +class Engine; +class PatchImpl; /** Implementation of a plugin (internal code, or a loaded shared library). * - * Conceptually, a Node is an instance of this. + * Conceptually, a Block is an instance of this. */ class PluginImpl : public Plugin , public boost::noncopyable @@ -52,11 +52,11 @@ public: , _type(type) {} - virtual NodeImpl* instantiate(BufferFactory& bufs, - const Raul::Symbol& symbol, - bool polyphonic, - PatchImpl* parent, - Engine& engine) = 0; + virtual BlockImpl* instantiate(BufferFactory& bufs, + const Raul::Symbol& symbol, + bool polyphonic, + PatchImpl* parent, + Engine& engine) = 0; virtual const Raul::Symbol symbol() const = 0; diff --git a/src/server/PortImpl.cpp b/src/server/PortImpl.cpp index 698cd458..bd088913 100644 --- a/src/server/PortImpl.cpp +++ b/src/server/PortImpl.cpp @@ -19,10 +19,10 @@ #include "raul/Array.hpp" #include "raul/Maid.hpp" +#include "BlockImpl.hpp" #include "Buffer.hpp" #include "BufferFactory.hpp" #include "Engine.hpp" -#include "NodeImpl.hpp" #include "PortImpl.hpp" #include "PortType.hpp" #include "ThreadManager.hpp" @@ -33,7 +33,7 @@ namespace Ingen { namespace Server { PortImpl::PortImpl(BufferFactory& bufs, - NodeImpl* const node, + BlockImpl* const block, const Raul::Symbol& name, uint32_t index, uint32_t poly, @@ -41,7 +41,7 @@ PortImpl::PortImpl(BufferFactory& bufs, LV2_URID buffer_type, const Raul::Atom& value, size_t buffer_size) - : GraphObjectImpl(bufs.uris(), node, name) + : GraphObjectImpl(bufs.uris(), block, name) , _bufs(bufs) , _index(index) , _poly(poly) @@ -64,7 +64,7 @@ PortImpl::PortImpl(BufferFactory& bufs, , _is_sample_rate(false) , _is_toggled(false) { - assert(node != NULL); + assert(block != NULL); assert(_poly > 0); const Ingen::URIs& uris = bufs.uris(); @@ -163,7 +163,7 @@ PortImpl::set_voice_value(const Context& context, break; case PortType::AUDIO: case PortType::CV: { - // Time may be at end so internal nodes can set triggers + // Time may be at end so internal blocks can set triggers assert(time >= context.start()); assert(time <= context.start() + context.nframes()); @@ -298,7 +298,7 @@ void PortImpl::connect_buffers() { for (uint32_t v = 0; v < _poly; ++v) - PortImpl::parent_node()->set_port_buffer(v, _index, buffer(v)); + PortImpl::parent_block()->set_port_buffer(v, _index, buffer(v)); } void diff --git a/src/server/PortImpl.hpp b/src/server/PortImpl.hpp index 68787db8..d7aed3ff 100644 --- a/src/server/PortImpl.hpp +++ b/src/server/PortImpl.hpp @@ -33,14 +33,10 @@ namespace Raul { class Maid; } namespace Ingen { namespace Server { -class NodeImpl; +class BlockImpl; class BufferFactory; -/** A port on a Node. - * - * This is a non-template abstract base class, which basically exists so - * things can pass around Port pointers and not have to worry about type, - * templates, etc. +/** A port (input or output) on a Block. * * \ingroup engine */ @@ -51,8 +47,8 @@ public: virtual GraphType graph_type() const { return PORT; } - /** A port's parent is always a node, so static cast should be safe */ - NodeImpl* parent_node() const { return (NodeImpl*)_parent; } + /** A port's parent is always a block, so static cast should be safe */ + BlockImpl* parent_block() const { return (BlockImpl*)_parent; } /** Set the buffers array for this port. * @@ -175,7 +171,7 @@ public: protected: PortImpl(BufferFactory& bufs, - NodeImpl* node, + BlockImpl* block, const Raul::Symbol& name, uint32_t index, uint32_t poly, diff --git a/src/server/Worker.cpp b/src/server/Worker.cpp index e8c51335..6a39cba8 100644 --- a/src/server/Worker.cpp +++ b/src/server/Worker.cpp @@ -20,7 +20,7 @@ #include "Driver.hpp" #include "Engine.hpp" -#include "LV2Node.hpp" +#include "LV2Block.hpp" #include "PatchImpl.hpp" #include "Worker.hpp" @@ -29,8 +29,8 @@ namespace Server { /// A message in the Worker::_requests ring struct MessageHeader { - LV2Node* node; ///< Node this message is from - uint32_t size; ///< Size of following data + LV2Block* block; ///< Node this message is from + uint32_t size; ///< Size of following data // `size' bytes of data follow here }; @@ -39,25 +39,25 @@ schedule(LV2_Worker_Schedule_Handle handle, uint32_t size, const void* data) { - LV2Node* node = (LV2Node*)handle; - Engine& engine = node->parent_patch()->engine(); - Worker* worker = engine.worker(); + LV2Block* block = (LV2Block*)handle; + Engine& engine = block->parent_patch()->engine(); + Worker* worker = engine.worker(); - return worker->request(node, size, data); + return worker->request(block, size, data); } LV2_Worker_Status -Worker::request(LV2Node* node, +Worker::request(LV2Block* block, uint32_t size, const void* data) { - Engine& engine = node->parent_patch()->engine(); + Engine& engine = block->parent_patch()->engine(); if (_requests.write_space() < sizeof(MessageHeader) + size) { engine.log().error("Work request ring overflow\n"); return LV2_WORKER_ERR_NO_SPACE; } - const MessageHeader msg = { node, size }; + const MessageHeader msg = { block, size }; if (_requests.write(sizeof(msg), &msg) != sizeof(msg)) { engine.log().error("Error writing header to work request ring\n"); return LV2_WORKER_ERR_UNKNOWN; @@ -82,14 +82,14 @@ delete_feature(LV2_Feature* feature) SharedPtr Worker::Schedule::feature(World* world, GraphObject* n) { - LV2Node* node = dynamic_cast(n); - if (!node) { + LV2Block* block = dynamic_cast(n); + if (!block) { return SharedPtr(); } LV2_Worker_Schedule* data = (LV2_Worker_Schedule*)malloc( sizeof(LV2_Worker_Schedule)); - data->handle = node; + data->handle = block; data->schedule_work = schedule; LV2_Feature* f = (LV2_Feature*)malloc(sizeof(LV2_Feature)); @@ -139,7 +139,7 @@ Worker::_run() continue; } - msg.node->work(msg.size, _buffer); + msg.block->work(msg.size, _buffer); } } } diff --git a/src/server/Worker.hpp b/src/server/Worker.hpp index 0310de90..f8c9216e 100644 --- a/src/server/Worker.hpp +++ b/src/server/Worker.hpp @@ -29,7 +29,7 @@ class Log; namespace Server { -class LV2Node; +class LV2Block; class Worker : public Raul::Thread { @@ -41,7 +41,7 @@ public: SharedPtr feature(World* world, GraphObject* n); }; - LV2_Worker_Status request(LV2Node* node, + LV2_Worker_Status request(LV2Block* block, uint32_t size, const void* data); diff --git a/src/server/events.hpp b/src/server/events.hpp index cf764fa9..95f3d35f 100644 --- a/src/server/events.hpp +++ b/src/server/events.hpp @@ -18,7 +18,7 @@ #define INGEN_ENGINE_EVENTS_HPP #include "events/Connect.hpp" -#include "events/CreateNode.hpp" +#include "events/CreateBlock.hpp" #include "events/CreatePatch.hpp" #include "events/CreatePort.hpp" #include "events/Delete.hpp" diff --git a/src/server/events/Connect.cpp b/src/server/events/Connect.cpp index 2403b327..db8e044f 100644 --- a/src/server/events/Connect.cpp +++ b/src/server/events/Connect.cpp @@ -70,15 +70,15 @@ Connect::pre_process() return Event::pre_process_done(BAD_REQUEST, _head_path); } - NodeImpl* const tail_node = tail_output->parent_node(); - NodeImpl* const head_node = _head->parent_node(); - if (!tail_node || !head_node) { + BlockImpl* const tail_block = tail_output->parent_block(); + BlockImpl* const head_block = _head->parent_block(); + if (!tail_block || !head_block) { return Event::pre_process_done(PARENT_NOT_FOUND, _head_path); } - if (tail_node->parent() != head_node->parent() - && tail_node != head_node->parent() - && tail_node->parent() != head_node) { + if (tail_block->parent() != head_block->parent() + && tail_block != head_block->parent() + && tail_block->parent() != head_block) { return Event::pre_process_done(PARENT_DIFFERS, _head_path); } @@ -86,20 +86,20 @@ Connect::pre_process() return Event::pre_process_done(TYPE_MISMATCH, _head_path); } - if (tail_node->parent_patch() != head_node->parent_patch()) { + if (tail_block->parent_patch() != head_block->parent_patch()) { // Edge to a patch port from inside the patch - assert(tail_node->parent() == head_node || head_node->parent() == tail_node); - if (tail_node->parent() == head_node) { - _patch = dynamic_cast(head_node); + assert(tail_block->parent() == head_block || head_block->parent() == tail_block); + if (tail_block->parent() == head_block) { + _patch = dynamic_cast(head_block); } else { - _patch = dynamic_cast(tail_node); + _patch = dynamic_cast(tail_block); } - } else if (tail_node == head_node && dynamic_cast(tail_node)) { + } else if (tail_block == head_block && dynamic_cast(tail_block)) { // Edge from a patch input to a patch output (pass through) - _patch = dynamic_cast(tail_node); + _patch = dynamic_cast(tail_block); } else { - // Normal edge between nodes with the same parent - _patch = tail_node->parent_patch(); + // Normal edge between blocks with the same parent + _patch = tail_block->parent_patch(); } if (_patch->has_edge(tail_output, _head)) { @@ -114,12 +114,12 @@ Connect::pre_process() Glib::RWLock::ReaderLock wlock(_engine.store()->lock()); /* Need to be careful about patch port edges here and adding a - node's parent as a dependant/provider, or adding a patch as its own + block's parent as a dependant/provider, or adding a patch as its own provider... */ - if (tail_node != head_node && tail_node->parent() == head_node->parent()) { - head_node->providers().push_back(tail_node); - tail_node->dependants().push_back(head_node); + if (tail_block != head_block && tail_block->parent() == head_block->parent()) { + head_block->providers().push_back(tail_block); + tail_block->dependants().push_back(head_block); } _patch->add_edge(_edge); diff --git a/src/server/events/CreateBlock.cpp b/src/server/events/CreateBlock.cpp new file mode 100644 index 00000000..73ff7ba2 --- /dev/null +++ b/src/server/events/CreateBlock.cpp @@ -0,0 +1,144 @@ +/* + This file is part of Ingen. + Copyright 2007-2012 David Robillard + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see . +*/ + +#include "ingen/Store.hpp" +#include "ingen/URIs.hpp" +#include "raul/Maid.hpp" +#include "raul/Path.hpp" + +#include "BlockFactory.hpp" +#include "BlockImpl.hpp" +#include "Broadcaster.hpp" +#include "CreateBlock.hpp" +#include "Engine.hpp" +#include "PatchImpl.hpp" +#include "PluginImpl.hpp" +#include "PortImpl.hpp" + +namespace Ingen { +namespace Server { +namespace Events { + +CreateBlock::CreateBlock(Engine& engine, + SharedPtr client, + int32_t id, + SampleCount timestamp, + const Raul::Path& path, + const Resource::Properties& properties) + : Event(engine, client, id, timestamp) + , _path(path) + , _properties(properties) + , _patch(NULL) + , _block(NULL) + , _compiled_patch(NULL) +{} + +bool +CreateBlock::pre_process() +{ + Ingen::URIs& uris = _engine.world()->uris(); + + typedef Resource::Properties::const_iterator iterator; + + if (_path.is_root()) { + return Event::pre_process_done(BAD_URI, _path); + } + + std::string plugin_uri_str; + const iterator t = _properties.find(uris.ingen_prototype); + if (t != _properties.end() && t->second.type() == uris.forge.URI) { + plugin_uri_str = t->second.get_uri(); + } else { + return Event::pre_process_done(BAD_REQUEST); + } + + if (_engine.store()->get(_path)) { + return Event::pre_process_done(EXISTS, _path); + } + + _patch = dynamic_cast(_engine.store()->get(_path.parent())); + if (!_patch) { + return Event::pre_process_done(PARENT_NOT_FOUND, _path.parent()); + } + + const Raul::URI plugin_uri(plugin_uri_str); + PluginImpl* plugin = _engine.block_factory()->plugin(plugin_uri); + if (!plugin) { + return Event::pre_process_done(PLUGIN_NOT_FOUND, Raul::URI(plugin_uri)); + } + + const iterator p = _properties.find(uris.ingen_polyphonic); + const bool polyphonic = ( + p != _properties.end() && + p->second.type() == _engine.world()->forge().Bool && + p->second.get_bool()); + + if (!(_block = plugin->instantiate(*_engine.buffer_factory(), + Raul::Symbol(_path.symbol()), + polyphonic, + _patch, + _engine))) { + return Event::pre_process_done(CREATION_FAILED, _path); + } + + _block->properties().insert(_properties.begin(), _properties.end()); + _block->activate(*_engine.buffer_factory()); + + // Add block to the store and the patch's pre-processor only block list + _patch->add_block(*_block); + _engine.store()->add(_block); + + /* Compile patch with new block added for insertion in audio thread + TODO: Since the block is not connected at this point, a full compilation + could be avoided and the block simply appended. */ + if (_patch->enabled()) { + _compiled_patch = _patch->compile(); + } + + _update.push_back(make_pair(_block->uri(), _block->properties())); + for (uint32_t i = 0; i < _block->num_ports(); ++i) { + const PortImpl* port = _block->port_impl(i); + Resource::Properties pprops = port->properties(); + pprops.erase(uris.ingen_value); + pprops.insert(std::make_pair(uris.ingen_value, port->value())); + _update.push_back(std::make_pair(port->uri(), pprops)); + } + + return Event::pre_process_done(SUCCESS); +} + +void +CreateBlock::execute(ProcessContext& context) +{ + if (_block) { + _engine.maid()->dispose(_patch->compiled_patch()); + _patch->compiled_patch(_compiled_patch); + } +} + +void +CreateBlock::post_process() +{ + if (!respond()) { + for (Update::const_iterator i = _update.begin(); i != _update.end(); ++i) { + _engine.broadcaster()->put(i->first, i->second); + } + } +} + +} // namespace Events +} // namespace Server +} // namespace Ingen diff --git a/src/server/events/CreateBlock.hpp b/src/server/events/CreateBlock.hpp new file mode 100644 index 00000000..ea3c4b5c --- /dev/null +++ b/src/server/events/CreateBlock.hpp @@ -0,0 +1,70 @@ +/* + This file is part of Ingen. + Copyright 2007-2012 David Robillard + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see . +*/ + +#ifndef INGEN_EVENTS_CREATEBLOCK_HPP +#define INGEN_EVENTS_CREATEBLOCK_HPP + +#include +#include + +#include "ingen/Resource.hpp" + +#include "Event.hpp" + +namespace Ingen { +namespace Server { + +class BlockImpl; +class CompiledPatch; +class PatchImpl; + +namespace Events { + +/** An event to load a Block and insert it into a Patch. + * + * \ingroup engine + */ +class CreateBlock : public Event +{ +public: + CreateBlock(Engine& engine, + SharedPtr client, + int32_t id, + SampleCount timestamp, + const Raul::Path& block_path, + const Resource::Properties& properties); + + bool pre_process(); + void execute(ProcessContext& context); + void post_process(); + +private: + /// Update put message to broadcast to clients + typedef std::list< std::pair > Update; + + Raul::Path _path; + Resource::Properties _properties; + Update _update; + PatchImpl* _patch; + BlockImpl* _block; + CompiledPatch* _compiled_patch; +}; + +} // namespace Events +} // namespace Server +} // namespace Ingen + +#endif // INGEN_EVENTS_CREATEBLOCK_HPP diff --git a/src/server/events/CreateNode.cpp b/src/server/events/CreateNode.cpp deleted file mode 100644 index ca2be305..00000000 --- a/src/server/events/CreateNode.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include "ingen/Store.hpp" -#include "ingen/URIs.hpp" -#include "raul/Maid.hpp" -#include "raul/Path.hpp" - -#include "Broadcaster.hpp" -#include "CreateNode.hpp" -#include "Engine.hpp" -#include "NodeFactory.hpp" -#include "NodeImpl.hpp" -#include "PatchImpl.hpp" -#include "PluginImpl.hpp" -#include "PortImpl.hpp" - -namespace Ingen { -namespace Server { -namespace Events { - -CreateNode::CreateNode(Engine& engine, - SharedPtr client, - int32_t id, - SampleCount timestamp, - const Raul::Path& path, - const Resource::Properties& properties) - : Event(engine, client, id, timestamp) - , _path(path) - , _properties(properties) - , _patch(NULL) - , _node(NULL) - , _compiled_patch(NULL) -{} - -bool -CreateNode::pre_process() -{ - Ingen::URIs& uris = _engine.world()->uris(); - - typedef Resource::Properties::const_iterator iterator; - - if (_path.is_root()) { - return Event::pre_process_done(BAD_URI, _path); - } - - std::string plugin_uri_str; - const iterator t = _properties.find(uris.ingen_prototype); - if (t != _properties.end() && t->second.type() == uris.forge.URI) { - plugin_uri_str = t->second.get_uri(); - } else { - return Event::pre_process_done(BAD_REQUEST); - } - - if (_engine.store()->get(_path)) { - return Event::pre_process_done(EXISTS, _path); - } - - _patch = dynamic_cast(_engine.store()->get(_path.parent())); - if (!_patch) { - return Event::pre_process_done(PARENT_NOT_FOUND, _path.parent()); - } - - const Raul::URI plugin_uri(plugin_uri_str); - PluginImpl* plugin = _engine.node_factory()->plugin(plugin_uri); - if (!plugin) { - return Event::pre_process_done(PLUGIN_NOT_FOUND, Raul::URI(plugin_uri)); - } - - const iterator p = _properties.find(uris.ingen_polyphonic); - const bool polyphonic = ( - p != _properties.end() && - p->second.type() == _engine.world()->forge().Bool && - p->second.get_bool()); - - if (!(_node = plugin->instantiate(*_engine.buffer_factory(), - Raul::Symbol(_path.symbol()), - polyphonic, - _patch, - _engine))) { - return Event::pre_process_done(CREATION_FAILED, _path); - } - - _node->properties().insert(_properties.begin(), _properties.end()); - _node->activate(*_engine.buffer_factory()); - - // Add node to the store and the patch's pre-processor only node list - _patch->add_node(*_node); - _engine.store()->add(_node); - - /* Compile patch with new node added for insertion in audio thread - TODO: Since the node is not connected at this point, a full compilation - could be avoided and the node simply appended. */ - if (_patch->enabled()) { - _compiled_patch = _patch->compile(); - } - - _update.push_back(make_pair(_node->uri(), _node->properties())); - for (uint32_t i = 0; i < _node->num_ports(); ++i) { - const PortImpl* port = _node->port_impl(i); - Resource::Properties pprops = port->properties(); - pprops.erase(uris.ingen_value); - pprops.insert(std::make_pair(uris.ingen_value, port->value())); - _update.push_back(std::make_pair(port->uri(), pprops)); - } - - return Event::pre_process_done(SUCCESS); -} - -void -CreateNode::execute(ProcessContext& context) -{ - if (_node) { - _engine.maid()->dispose(_patch->compiled_patch()); - _patch->compiled_patch(_compiled_patch); - } -} - -void -CreateNode::post_process() -{ - if (!respond()) { - for (Update::const_iterator i = _update.begin(); i != _update.end(); ++i) { - _engine.broadcaster()->put(i->first, i->second); - } - } -} - -} // namespace Events -} // namespace Server -} // namespace Ingen diff --git a/src/server/events/CreateNode.hpp b/src/server/events/CreateNode.hpp deleted file mode 100644 index 32c0f4b9..00000000 --- a/src/server/events/CreateNode.hpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_EVENTS_CREATENODE_HPP -#define INGEN_EVENTS_CREATENODE_HPP - -#include -#include - -#include "ingen/Resource.hpp" - -#include "Event.hpp" - -namespace Ingen { -namespace Server { - -class PatchImpl; -class NodeImpl; -class CompiledPatch; - -namespace Events { - -/** An event to load a Node and insert it into a Patch. - * - * \ingroup engine - */ -class CreateNode : public Event -{ -public: - CreateNode(Engine& engine, - SharedPtr client, - int32_t id, - SampleCount timestamp, - const Raul::Path& node_path, - const Resource::Properties& properties); - - bool pre_process(); - void execute(ProcessContext& context); - void post_process(); - -private: - /// Update put message to broadcast to clients - typedef std::list< std::pair > Update; - - Raul::Path _path; - Resource::Properties _properties; - Update _update; - PatchImpl* _patch; - NodeImpl* _node; - CompiledPatch* _compiled_patch; -}; - -} // namespace Events -} // namespace Server -} // namespace Ingen - -#endif // INGEN_EVENTS_CREATENODE_HPP diff --git a/src/server/events/CreatePatch.cpp b/src/server/events/CreatePatch.cpp index 4f14ade5..e9adc547 100644 --- a/src/server/events/CreatePatch.cpp +++ b/src/server/events/CreatePatch.cpp @@ -81,9 +81,9 @@ CreatePatch::pre_process() _patch->properties().insert(_properties.begin(), _properties.end()); _patch->add_property(uris.rdf_type, uris.ingen_Patch); _patch->add_property(uris.rdf_type, - Resource::Property(uris.ingen_Node, Resource::EXTERNAL)); + Resource::Property(uris.ingen_Block, Resource::EXTERNAL)); - _parent->add_node(*_patch); + _parent->add_block(*_patch); if (_parent->enabled()) { _patch->enable(); _compiled_patch = _parent->compile(); diff --git a/src/server/events/Delete.cpp b/src/server/events/Delete.cpp index d2e3e58e..dbda331c 100644 --- a/src/server/events/Delete.cpp +++ b/src/server/events/Delete.cpp @@ -18,6 +18,7 @@ #include "raul/Maid.hpp" #include "raul/Path.hpp" +#include "BlockImpl.hpp" #include "Broadcaster.hpp" #include "ControlBindings.hpp" #include "Delete.hpp" @@ -25,7 +26,6 @@ #include "Driver.hpp" #include "Engine.hpp" #include "EnginePort.hpp" -#include "NodeImpl.hpp" #include "PatchImpl.hpp" #include "PluginImpl.hpp" #include "PortImpl.hpp" @@ -73,24 +73,24 @@ Delete::pre_process() return Event::pre_process_done(NOT_FOUND, _path); } - if (!(_node = PtrCast(iter->second))) { + if (!(_block = PtrCast(iter->second))) { _port = PtrCast(iter->second); } - if (!_node && !_port) { + if (!_block && !_port) { return Event::pre_process_done(NOT_DELETABLE, _path); } - PatchImpl* parent = _node ? _node->parent_patch() : _port->parent_patch(); + PatchImpl* parent = _block ? _block->parent_patch() : _port->parent_patch(); if (!parent) { return Event::pre_process_done(INTERNAL_ERROR, _path); } _engine.store()->remove(iter, _removed_objects); - if (_node) { - parent->remove_node(*_node); - _disconnect_event = new DisconnectAll(_engine, parent, _node.get()); + if (_block) { + parent->remove_block(*_block); + _disconnect_event = new DisconnectAll(_engine, parent, _block.get()); _disconnect_event->pre_process(); if (parent->enabled()) { @@ -122,7 +122,7 @@ Delete::execute(ProcessContext& context) _disconnect_event->execute(context); } - PatchImpl* parent = _node ? _node->parent_patch() : _port->parent_patch(); + PatchImpl* parent = _block ? _block->parent_patch() : _port->parent_patch(); if (_port) { _engine.maid()->dispose(parent->external_ports()); parent->external_ports(_ports_array); @@ -143,9 +143,9 @@ Delete::post_process() { _lock.release(); _removed_bindings.reset(); - if (!respond() && (_node || _port)) { - if (_node) { - _node->deactivate(); + if (!respond() && (_block || _port)) { + if (_block) { + _block->deactivate(); } _engine.broadcaster()->bundle_begin(); diff --git a/src/server/events/Delete.hpp b/src/server/events/Delete.hpp index f307eba4..c14c5567 100644 --- a/src/server/events/Delete.hpp +++ b/src/server/events/Delete.hpp @@ -30,11 +30,11 @@ template class Array; namespace Ingen { namespace Server { -class NodeImpl; -class PortImpl; +class BlockImpl; +class CompiledPatch; class DuplexPort; class EnginePort; -class CompiledPatch; +class PortImpl; namespace Events { @@ -72,7 +72,7 @@ public: private: Raul::URI _uri; Raul::Path _path; - SharedPtr _node; ///< Non-NULL iff a node + SharedPtr _block; ///< Non-NULL iff a block SharedPtr _port; ///< Non-NULL iff a port EnginePort* _engine_port; Raul::Array* _ports_array; ///< New (external) ports for Patch diff --git a/src/server/events/Delta.cpp b/src/server/events/Delta.cpp index 1120af92..3b31cedb 100644 --- a/src/server/events/Delta.cpp +++ b/src/server/events/Delta.cpp @@ -24,7 +24,7 @@ #include "Broadcaster.hpp" #include "ControlBindings.hpp" -#include "CreateNode.hpp" +#include "CreateBlock.hpp" #include "CreatePatch.hpp" #include "CreatePort.hpp" #include "Delta.hpp" @@ -112,7 +112,7 @@ Delta::pre_process() _object = is_graph_object ? static_cast(_engine.store()->get(GraphObject::uri_to_path(_subject))) - : static_cast(_engine.node_factory()->plugin(_subject)); + : static_cast(_engine.block_factory()->plugin(_subject)); if (!_object && (!is_graph_object || !_create)) { return Event::pre_process_done(NOT_FOUND, _subject); @@ -122,14 +122,14 @@ Delta::pre_process() if (is_graph_object && !_object) { Raul::Path path(GraphObject::uri_to_path(_subject)); - bool is_patch = false, is_node = false, is_port = false, is_output = false; - Ingen::Resource::type(uris, _properties, is_patch, is_node, is_port, is_output); + bool is_patch = false, is_block = false, is_port = false, is_output = false; + Ingen::Resource::type(uris, _properties, is_patch, is_block, is_port, is_output); if (is_patch) { _create_event = new CreatePatch( _engine, _request_client, _request_id, _time, path, _properties); - } else if (is_node) { - _create_event = new CreateNode( + } else if (is_block) { + _create_event = new CreateBlock( _engine, _request_client, _request_id, _time, path, _properties); } else if (is_port) { _create_event = new CreatePort( @@ -223,9 +223,9 @@ Delta::pre_process() if (value.type() == uris.forge.Bool) { op = POLYPHONIC; obj->set_property(key, value, value.context()); - NodeImpl* node = dynamic_cast(obj); - if (node) - node->set_polyphonic(value.get_bool()); + BlockImpl* block = dynamic_cast(obj); + if (block) + block->set_polyphonic(value.get_bool()); if (value.get_bool()) { obj->prepare_poly(*_engine.buffer_factory(), parent->internal_poly()); } else { @@ -271,7 +271,7 @@ Delta::execute(ProcessContext& context) } GraphObjectImpl* const object = dynamic_cast(_object); - NodeImpl* const node = dynamic_cast(_object); + BlockImpl* const block = dynamic_cast(_object); PortImpl* const port = dynamic_cast(_object); std::vector::const_iterator t = _types.begin(); @@ -315,9 +315,9 @@ Delta::execute(ProcessContext& context) case CONTROL_BINDING: if (port) { _engine.control_bindings()->port_binding_changed(context, port, value); - } else if (node) { - if (node->plugin_impl()->type() == Plugin::Internal) { - node->learn(); + } else if (block) { + if (block->plugin_impl()->type() == Plugin::Internal) { + block->learn(); } } break; diff --git a/src/server/events/Disconnect.cpp b/src/server/events/Disconnect.cpp index 9e1e9531..9cf2974a 100644 --- a/src/server/events/Disconnect.cpp +++ b/src/server/events/Disconnect.cpp @@ -67,21 +67,21 @@ Disconnect::Impl::Impl(Engine& e, { ThreadManager::assert_thread(THREAD_PRE_PROCESS); - NodeImpl* const src_node = _src_output_port->parent_node(); - NodeImpl* const dst_node = _dst_input_port->parent_node(); + BlockImpl* const src_block = _src_output_port->parent_block(); + BlockImpl* const dst_block = _dst_input_port->parent_block(); - for (std::list::iterator i = dst_node->providers().begin(); - i != dst_node->providers().end(); ++i) { - if ((*i) == src_node) { - dst_node->providers().erase(i); + for (std::list::iterator i = dst_block->providers().begin(); + i != dst_block->providers().end(); ++i) { + if ((*i) == src_block) { + dst_block->providers().erase(i); break; } } - for (std::list::iterator i = src_node->dependants().begin(); - i != src_node->dependants().end(); ++i) { - if ((*i) == dst_node) { - src_node->dependants().erase(i); + for (std::list::iterator i = src_block->dependants().begin(); + i != src_block->dependants().end(); ++i) { + if ((*i) == dst_block) { + src_block->dependants().erase(i); break; } } @@ -130,23 +130,23 @@ Disconnect::pre_process() return Event::pre_process_done(PORT_NOT_FOUND, _head_path); } - NodeImpl* const src_node = tail->parent_node(); - NodeImpl* const dst_node = head->parent_node(); + BlockImpl* const src_block = tail->parent_block(); + BlockImpl* const dst_block = head->parent_block(); - if (src_node->parent_patch() != dst_node->parent_patch()) { + if (src_block->parent_patch() != dst_block->parent_patch()) { // Edge 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 = dynamic_cast(dst_node); + assert(src_block->parent() == dst_block || dst_block->parent() == src_block); + if (src_block->parent() == dst_block) { + _patch = dynamic_cast(dst_block); } else { - _patch = dynamic_cast(src_node); + _patch = dynamic_cast(src_block); } - } else if (src_node == dst_node && dynamic_cast(src_node)) { + } else if (src_block == dst_block && dynamic_cast(src_block)) { // Edge from a patch input to a patch output (pass through) - _patch = dynamic_cast(src_node); + _patch = dynamic_cast(src_block); } else { - // Normal edge between nodes with the same parent - _patch = src_node->parent_patch(); + // Normal edge between blocks with the same parent + _patch = src_block->parent_patch(); } assert(_patch); @@ -155,7 +155,7 @@ Disconnect::pre_process() return Event::pre_process_done(NOT_FOUND, _head_path); } - if (src_node == NULL || dst_node == NULL) { + if (src_block == NULL || dst_block == NULL) { return Event::pre_process_done(PARENT_NOT_FOUND, _head_path); } diff --git a/src/server/events/DisconnectAll.cpp b/src/server/events/DisconnectAll.cpp index 693c8784..4169622d 100644 --- a/src/server/events/DisconnectAll.cpp +++ b/src/server/events/DisconnectAll.cpp @@ -24,11 +24,11 @@ #include "raul/Maid.hpp" #include "raul/Path.hpp" +#include "BlockImpl.hpp" #include "Broadcaster.hpp" #include "EdgeImpl.hpp" #include "Engine.hpp" #include "InputPort.hpp" -#include "NodeImpl.hpp" #include "OutputPort.hpp" #include "PatchImpl.hpp" #include "PortImpl.hpp" @@ -50,7 +50,7 @@ DisconnectAll::DisconnectAll(Engine& engine, , _parent_path(parent_path) , _path(path) , _parent(NULL) - , _node(NULL) + , _block(NULL) , _port(NULL) , _compiled_patch(NULL) , _deleting(false) @@ -66,7 +66,7 @@ DisconnectAll::DisconnectAll(Engine& engine, , _parent_path(parent->path()) , _path(object->path()) , _parent(parent) - , _node(dynamic_cast(object)) + , _block(dynamic_cast(object)) , _port(dynamic_cast(object)) , _compiled_patch(NULL) , _deleting(true) @@ -104,10 +104,10 @@ DisconnectAll::pre_process() } // Only one of these will succeed - _node = dynamic_cast(object); - _port = dynamic_cast(object); + _block = dynamic_cast(object); + _port = dynamic_cast(object); - assert((_node || _port) && !(_node && _port)); + assert((_block || _port) && !(_block && _port)); } // Find set of edges to remove @@ -115,9 +115,9 @@ DisconnectAll::pre_process() for (GraphObject::Edges::const_iterator i = _parent->edges().begin(); i != _parent->edges().end(); ++i) { EdgeImpl* const c = (EdgeImpl*)i->second.get(); - if (_node) { - if (c->tail()->parent_node() == _node - || c->head()->parent_node() == _node) { + if (_block) { + if (c->tail()->parent_block() == _block + || c->head()->parent_block() == _block) { to_remove.insert(c); } } else { @@ -149,7 +149,7 @@ DisconnectAll::execute(ProcessContext& context) if (_status == SUCCESS) { for (Impls::iterator i = _impls.begin(); i != _impls.end(); ++i) { (*i)->execute(context, - !_deleting || ((*i)->head()->parent_node() != _node)); + !_deleting || ((*i)->head()->parent_block() != _block)); } } diff --git a/src/server/events/DisconnectAll.hpp b/src/server/events/DisconnectAll.hpp index 12c04ffa..68ba8ebe 100644 --- a/src/server/events/DisconnectAll.hpp +++ b/src/server/events/DisconnectAll.hpp @@ -27,8 +27,8 @@ namespace Ingen { namespace Server { +class BlockImpl; class CompiledPatch; -class NodeImpl; class PatchImpl; class PortImpl; @@ -36,7 +36,7 @@ namespace Events { class Disconnect; -/** An event to disconnect all connections to a Node. +/** An event to disconnect all connections to a Block. * * \ingroup engine */ @@ -66,7 +66,7 @@ private: Raul::Path _parent_path; Raul::Path _path; PatchImpl* _parent; - NodeImpl* _node; + BlockImpl* _block; PortImpl* _port; Impls _impls; CompiledPatch* _compiled_patch; diff --git a/src/server/events/Get.cpp b/src/server/events/Get.cpp index 294a15b3..24b4daae 100644 --- a/src/server/events/Get.cpp +++ b/src/server/events/Get.cpp @@ -20,12 +20,12 @@ #include "ingen/Interface.hpp" #include "ingen/Store.hpp" +#include "BlockImpl.hpp" #include "Broadcaster.hpp" #include "BufferFactory.hpp" #include "Driver.hpp" #include "Engine.hpp" #include "Get.hpp" -#include "NodeImpl.hpp" #include "PatchImpl.hpp" #include "PluginImpl.hpp" #include "PortImpl.hpp" @@ -56,7 +56,7 @@ Get::pre_process() _lock.acquire(); if (_uri == "ingen:plugins") { - _plugins = _engine.node_factory()->plugins(); + _plugins = _engine.block_factory()->plugins(); return Event::pre_process_done(SUCCESS); } else if (_uri == "ingen:engine") { return Event::pre_process_done(SUCCESS); @@ -64,7 +64,7 @@ Get::pre_process() _object = _engine.store()->get(GraphObject::uri_to_path(_uri)); return Event::pre_process_done(_object ? SUCCESS : NOT_FOUND, _uri); } else { - _plugin = _engine.node_factory()->plugin(_uri); + _plugin = _engine.block_factory()->plugin(_uri); return Event::pre_process_done(_plugin ? SUCCESS : NOT_FOUND, _uri); } } @@ -84,15 +84,15 @@ send_port(Interface* client, const PortImpl* port) } static void -send_node(Interface* client, const NodeImpl* node) +send_block(Interface* client, const BlockImpl* block) { - PluginImpl* const plugin = node->plugin_impl(); + PluginImpl* const plugin = block->plugin_impl(); if (plugin->type() == Plugin::Patch) { - send_patch(client, (const PatchImpl*)node); + send_patch(client, (const PatchImpl*)block); } else { - client->put(node->uri(), node->properties()); - for (size_t j = 0; j < node->num_ports(); ++j) { - send_port(client, node->port_impl(j)); + client->put(block->uri(), block->properties()); + for (size_t j = 0; j < block->num_ports(); ++j) { + send_port(client, block->port_impl(j)); } } } @@ -108,10 +108,10 @@ send_patch(Interface* client, const PatchImpl* patch) patch->properties(Resource::EXTERNAL), Resource::EXTERNAL); - // Send nodes - for (PatchImpl::Nodes::const_iterator j = patch->nodes().begin(); - j != patch->nodes().end(); ++j) { - send_node(client, &*j); + // Send blocks + for (PatchImpl::Blocks::const_iterator j = patch->blocks().begin(); + j != patch->blocks().end(); ++j) { + send_block(client, &*j); } // Send ports @@ -141,13 +141,13 @@ Get::post_process() uris.forge.make(int32_t(_engine.driver()->sample_rate()))); } else if (_object) { _request_client->bundle_begin(); - const NodeImpl* node = NULL; + const BlockImpl* block = NULL; const PatchImpl* patch = NULL; const PortImpl* port = NULL; if ((patch = dynamic_cast(_object))) { send_patch(_request_client.get(), patch); - } else if ((node = dynamic_cast(_object))) { - send_node(_request_client.get(), node); + } else if ((block = dynamic_cast(_object))) { + send_block(_request_client.get(), block); } else if ((port = dynamic_cast(_object))) { send_port(_request_client.get(), port); } diff --git a/src/server/events/Get.hpp b/src/server/events/Get.hpp index 12cedd4d..7b33304e 100644 --- a/src/server/events/Get.hpp +++ b/src/server/events/Get.hpp @@ -20,7 +20,7 @@ #include #include "Event.hpp" -#include "NodeFactory.hpp" +#include "BlockFactory.hpp" #include "types.hpp" namespace Ingen { @@ -51,7 +51,7 @@ private: const Raul::URI _uri; const GraphObject* _object; const PluginImpl* _plugin; - NodeFactory::Plugins _plugins; + BlockFactory::Plugins _plugins; Glib::RWLock::ReaderLock _lock; }; diff --git a/src/server/events/Move.cpp b/src/server/events/Move.cpp index 5fa58825..d5b4d116 100644 --- a/src/server/events/Move.cpp +++ b/src/server/events/Move.cpp @@ -19,11 +19,11 @@ #include "ingen/Store.hpp" #include "raul/Path.hpp" +#include "BlockImpl.hpp" #include "Broadcaster.hpp" #include "Driver.hpp" #include "Engine.hpp" #include "EnginePort.hpp" -#include "NodeImpl.hpp" #include "PatchImpl.hpp" #include "events/Move.hpp" diff --git a/src/server/events/SetPortValue.cpp b/src/server/events/SetPortValue.cpp index d81a38f7..7a994caa 100644 --- a/src/server/events/SetPortValue.cpp +++ b/src/server/events/SetPortValue.cpp @@ -19,12 +19,12 @@ #include "ingen/URIs.hpp" #include "ingen/World.hpp" +#include "BlockImpl.hpp" #include "Broadcaster.hpp" #include "Buffer.hpp" #include "ControlBindings.hpp" #include "Driver.hpp" #include "Engine.hpp" -#include "NodeImpl.hpp" #include "PortImpl.hpp" #include "ProcessContext.hpp" #include "SetPortValue.hpp" @@ -71,7 +71,7 @@ SetPortValue::execute(ProcessContext& context) { assert(_time >= context.start() && _time <= context.end()); - if (_port->parent_node()->context() == Context::MESSAGE) + if (_port->parent_block()->context() == Context::MESSAGE) return; apply(context); diff --git a/src/server/ingen_lv2.cpp b/src/server/ingen_lv2.cpp index 69775873..5158e441 100644 --- a/src/server/ingen_lv2.cpp +++ b/src/server/ingen_lv2.cpp @@ -432,7 +432,7 @@ find_patches(const Glib::ustring& manifest_uri) const Sord::URI rdf_type (world, NS_RDF "type"); const Sord::URI rdfs_seeAlso(world, NS_RDFS "seeAlso"); - SerdEnv* env = serd_env_new(sord_node_to_serd_node(base.c_obj())); + SerdEnv* env = serd_env_new(sord_node_to_serd_node(base.c_obj())); Sord::Model model(world, manifest_uri); model.load_file(env, SERD_TURTLE, manifest_uri); diff --git a/src/server/internals/Controller.cpp b/src/server/internals/Controller.cpp index 1fb3cf76..0e8d125e 100644 --- a/src/server/internals/Controller.cpp +++ b/src/server/internals/Controller.cpp @@ -47,7 +47,7 @@ ControllerNode::ControllerNode(InternalPlugin* plugin, bool polyphonic, PatchImpl* parent, SampleRate srate) - : NodeImpl(plugin, symbol, false, parent, srate) + : BlockImpl(plugin, symbol, false, parent, srate) , _learning(false) { const Ingen::URIs& uris = bufs.uris(); @@ -91,7 +91,7 @@ ControllerNode::ControllerNode(InternalPlugin* plugin, void ControllerNode::process(ProcessContext& context) { - NodeImpl::pre_process(context); + BlockImpl::pre_process(context); Buffer* const midi_in = _midi_in_port->buffer(0).get(); LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)midi_in->atom(); @@ -104,7 +104,7 @@ ControllerNode::process(ProcessContext& context) } } - NodeImpl::post_process(context); + BlockImpl::post_process(context); } void diff --git a/src/server/internals/Controller.hpp b/src/server/internals/Controller.hpp index 4a366b08..23401826 100644 --- a/src/server/internals/Controller.hpp +++ b/src/server/internals/Controller.hpp @@ -17,7 +17,7 @@ #ifndef INGEN_INTERNALS_CONTROLLER_HPP #define INGEN_INTERNALS_CONTROLLER_HPP -#include "NodeImpl.hpp" +#include "BlockImpl.hpp" namespace Ingen { namespace Server { @@ -28,14 +28,14 @@ class InternalPlugin; namespace Internals { -/** MIDI control input node. +/** MIDI control input block. * * Creating one of these nodes is how a user makes "MIDI Bindings". Note that * this node will always be monophonic, the poly parameter is ignored. * * \ingroup engine */ -class ControllerNode : public NodeImpl +class ControllerNode : public BlockImpl { public: ControllerNode(InternalPlugin* plugin, diff --git a/src/server/internals/Delay.cpp b/src/server/internals/Delay.cpp index 26799260..1e7ed5a5 100644 --- a/src/server/internals/Delay.cpp +++ b/src/server/internals/Delay.cpp @@ -55,7 +55,7 @@ DelayNode::DelayNode(InternalPlugin* plugin, bool polyphonic, PatchImpl* parent, SampleRate srate) - : NodeImpl(plugin, symbol, polyphonic, parent, srate) + : BlockImpl(plugin, symbol, polyphonic, parent, srate) , _buffer(0) , _buffer_length(0) , _buffer_mask(0) @@ -100,7 +100,7 @@ DelayNode::~DelayNode() void DelayNode::activate(BufferFactory& bufs) { - NodeImpl::activate(bufs); + BlockImpl::activate(bufs); const SampleRate rate = bufs.engine().driver()->sample_rate(); const SampleCount min_size = MAX_DELAY_SECONDS * rate; @@ -144,7 +144,7 @@ DelayNode::process(ProcessContext& context) Buffer* const in_buf = _in_port->buffer(0).get(); Buffer* const out_buf = _out_port->buffer(0).get(); - NodeImpl::pre_process(context); + BlockImpl::pre_process(context); DelayNode* plugin_data = this; @@ -201,7 +201,7 @@ DelayNode::process(ProcessContext& context) _write_phase = write_phase; - NodeImpl::post_process(context); + BlockImpl::post_process(context); } } // namespace Internals diff --git a/src/server/internals/Delay.hpp b/src/server/internals/Delay.hpp index 3c512d2c..8f4b758b 100644 --- a/src/server/internals/Delay.hpp +++ b/src/server/internals/Delay.hpp @@ -19,7 +19,7 @@ #include -#include "NodeImpl.hpp" +#include "BlockImpl.hpp" #include "types.hpp" namespace Ingen { @@ -32,7 +32,7 @@ class BufferFactory; namespace Internals { -class DelayNode : public NodeImpl +class DelayNode : public BlockImpl { public: DelayNode(InternalPlugin* plugin, diff --git a/src/server/internals/Note.cpp b/src/server/internals/Note.cpp index 25e8aee5..00ab0835 100644 --- a/src/server/internals/Note.cpp +++ b/src/server/internals/Note.cpp @@ -52,7 +52,7 @@ NoteNode::NoteNode(InternalPlugin* plugin, bool polyphonic, PatchImpl* parent, SampleRate srate) - : NodeImpl(plugin, symbol, polyphonic, parent, srate) + : BlockImpl(plugin, symbol, polyphonic, parent, srate) , _voices(new Raul::Array(_polyphony)) , _prepared_voices(NULL) , _sustain(false) @@ -103,7 +103,7 @@ NoteNode::prepare_poly(BufferFactory& bufs, uint32_t poly) if (!_polyphonic) return true; - NodeImpl::prepare_poly(bufs, poly); + BlockImpl::prepare_poly(bufs, poly); if (_prepared_voices && poly <= _prepared_voices->size()) return true; @@ -116,7 +116,7 @@ NoteNode::prepare_poly(BufferFactory& bufs, uint32_t poly) bool NoteNode::apply_poly(ProcessContext& context, Raul::Maid& maid, uint32_t poly) { - if (!NodeImpl::apply_poly(context, maid, poly)) + if (!BlockImpl::apply_poly(context, maid, poly)) return false; if (_prepared_voices) { @@ -133,7 +133,7 @@ NoteNode::apply_poly(ProcessContext& context, Raul::Maid& maid, uint32_t poly) void NoteNode::process(ProcessContext& context) { - NodeImpl::pre_process(context); + BlockImpl::pre_process(context); Buffer* const midi_in = _midi_in_port->buffer(0).get(); LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)midi_in->atom(); @@ -173,7 +173,7 @@ NoteNode::process(ProcessContext& context) } } - NodeImpl::post_process(context); + BlockImpl::post_process(context); } void diff --git a/src/server/internals/Note.hpp b/src/server/internals/Note.hpp index 6c7d9a13..290908e8 100644 --- a/src/server/internals/Note.hpp +++ b/src/server/internals/Note.hpp @@ -17,7 +17,7 @@ #ifndef INGEN_INTERNALS_NOTE_HPP #define INGEN_INTERNALS_NOTE_HPP -#include "NodeImpl.hpp" +#include "BlockImpl.hpp" #include "types.hpp" namespace Ingen { @@ -29,13 +29,13 @@ class InternalPlugin; namespace Internals { -/** MIDI note input node. +/** MIDI note input block. * * For pitched instruments like keyboard, etc. * * \ingroup engine */ -class NoteNode : public NodeImpl +class NoteNode : public BlockImpl { public: NoteNode(InternalPlugin* plugin, diff --git a/src/server/internals/Trigger.cpp b/src/server/internals/Trigger.cpp index f7bbd4c5..31943425 100644 --- a/src/server/internals/Trigger.cpp +++ b/src/server/internals/Trigger.cpp @@ -47,7 +47,7 @@ TriggerNode::TriggerNode(InternalPlugin* plugin, bool polyphonic, PatchImpl* parent, SampleRate srate) - : NodeImpl(plugin, symbol, false, parent, srate) + : BlockImpl(plugin, symbol, false, parent, srate) , _learning(false) { const Ingen::URIs& uris = bufs.uris(); @@ -89,7 +89,7 @@ TriggerNode::TriggerNode(InternalPlugin* plugin, void TriggerNode::process(ProcessContext& context) { - NodeImpl::pre_process(context); + BlockImpl::pre_process(context); Buffer* const midi_in = _midi_in_port->buffer(0).get(); LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)midi_in->atom(); @@ -121,7 +121,7 @@ TriggerNode::process(ProcessContext& context) } } - NodeImpl::post_process(context); + BlockImpl::post_process(context); } void diff --git a/src/server/internals/Trigger.hpp b/src/server/internals/Trigger.hpp index 59badc70..750cd287 100644 --- a/src/server/internals/Trigger.hpp +++ b/src/server/internals/Trigger.hpp @@ -17,7 +17,7 @@ #ifndef INGEN_INTERNALS_TRIGGER_HPP #define INGEN_INTERNALS_TRIGGER_HPP -#include "NodeImpl.hpp" +#include "BlockImpl.hpp" namespace Ingen { namespace Server { @@ -28,17 +28,17 @@ class InternalPlugin; namespace Internals { -/** MIDI trigger input node. +/** MIDI trigger input block. * - * Just has a gate, for drums etc. A control port is used to select + * Just has a gate, for drums etc. A control port is used to select * which note number is responded to. * - * Note that this node is always monophonic, the poly parameter is ignored. + * Note that this block is always monophonic, the poly parameter is ignored. * (Should that change?) * * \ingroup engine */ -class TriggerNode : public NodeImpl +class TriggerNode : public BlockImpl { public: TriggerNode(InternalPlugin* plugin, diff --git a/src/server/wscript b/src/server/wscript index 5c98d189..9664545a 100644 --- a/src/server/wscript +++ b/src/server/wscript @@ -3,6 +3,8 @@ from waflib.extras import autowaf as autowaf def build(bld): core_source = ''' + BlockFactory.cpp + BlockImpl.cpp Broadcaster.cpp Buffer.cpp BufferFactory.cpp @@ -15,11 +17,9 @@ def build(bld): GraphObjectImpl.cpp InputPort.cpp InternalPlugin.cpp + LV2Block.cpp LV2Info.cpp - LV2Node.cpp LV2Plugin.cpp - NodeFactory.cpp - NodeImpl.cpp OutputPort.cpp PatchImpl.cpp PortImpl.cpp @@ -27,7 +27,7 @@ def build(bld): PreProcessor.cpp Worker.cpp events/Connect.cpp - events/CreateNode.cpp + events/CreateBlock.cpp events/CreatePatch.cpp events/CreatePort.cpp events/Delete.cpp -- cgit v1.2.1