diff options
author | David Robillard <d@drobilla.net> | 2011-04-20 16:26:40 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2011-04-20 16:26:40 +0000 |
commit | 138a87e915ad3aff184730415105f94c874174bf (patch) | |
tree | 0d942bdddfdbcc3d969b4fce5592e770ab851b86 /src/engine | |
parent | 1f1758f4dda0ddaf01c0b1d3a756f9db8ddc979d (diff) | |
download | ingen-138a87e915ad3aff184730415105f94c874174bf.tar.gz ingen-138a87e915ad3aff184730415105f94c874174bf.tar.bz2 ingen-138a87e915ad3aff184730415105f94c874174bf.zip |
Rename Ingen::Engine to Ingen::Server (hopefully avoid odd name clases and fix #675).
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@3184 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/engine')
139 files changed, 0 insertions, 17645 deletions
diff --git a/src/engine/AudioBuffer.cpp b/src/engine/AudioBuffer.cpp deleted file mode 100644 index 172e41ac..00000000 --- a/src/engine/AudioBuffer.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <stdlib.h> -#include <cassert> -#include "raul/log.hpp" -#include "raul/SharedPtr.hpp" -#include "lv2/lv2plug.in/ns/ext/atom/atom.h" -#include "ingen-config.h" -#include "AudioBuffer.hpp" -#include "ProcessContext.hpp" -#include "LV2Features.hpp" - -using namespace std; -using namespace Raul; - -/* TODO: Be sure these functions are vectorized by GCC when its vectorizer - * stops sucking. Probably a good idea to inline them as well */ - -namespace Ingen { -namespace Engine { - -AudioBuffer::AudioBuffer(BufferFactory& bufs, PortType type, size_t size) - : ObjectBuffer(bufs, size) - , _state(OK) - , _set_value(0) - , _set_time(0) -{ - assert(size >= sizeof(LV2_Atom) + sizeof(Sample)); - assert(this->size() >= size); - assert(data()); - _type = type; - - // Control port / Single float object - if (type == PortType::CONTROL) { - atom()->type = 0;//map->float_type; - - // Audio port / Vector of float - } else { - assert(type == PortType::AUDIO); - atom()->type = 0;//map->vector_type; - LV2_Atom_Vector* body = (LV2_Atom_Vector*)atom()->body; - body->elem_count = size / sizeof(Sample); - body->elem_type = 0;//map->float_type; - } - /*debug << "Created Audio Buffer" << endl - << "\tobject @ " << (void*)atom() << endl - << "\tbody @ " << (void*)atom()->body - << "\t(offset " << (char*)atom()->body - (char*)atom() << ")" << endl - << "\tdata @ " << (void*)data() - << "\t(offset " << (char*)data() - (char*)atom() << ")" - << endl;*/ - - clear(); -} - -void -AudioBuffer::resize(size_t size) -{ - if (_type == PortType::AUDIO) { - ObjectBuffer::resize(size + sizeof(LV2_Atom_Vector)); - vector()->elem_count = size / sizeof(Sample); - } - clear(); -} - -/** Empty (ie zero) the buffer. - */ -void -AudioBuffer::clear() -{ - assert(nframes() != 0); - set_block(0, 0, nframes() - 1); - _state = OK; -} - -/** Set value of buffer to @a val after @a start_sample. - * - * The Buffer will handle setting the intial portion of the buffer to the - * value on the next cycle automatically (if @a start_sample is > 0), as - * long as pre_process() is called every cycle. - */ -void -AudioBuffer::set_value(Sample val, FrameTime cycle_start, FrameTime time) -{ - if (is_control()) - time = cycle_start; - - const FrameTime offset = time - cycle_start; - assert(nframes() != 0); - assert(offset <= nframes()); - - if (offset < nframes()) { - set_block(val, offset, nframes() - 1); - - if (offset == 0) - _state = OK; - else - _state = HALF_SET_CYCLE_1; - } // else trigger at very end of block - - _set_time = time; - _set_value = val; -} - -/** Set a block of buffer to @a val. - * - * @a start_sample and @a end_sample define the inclusive range to be set. - */ -void -AudioBuffer::set_block(Sample val, size_t start_offset, size_t end_offset) -{ - assert(end_offset >= start_offset); - assert(end_offset < nframes()); - - Sample* const buf = data(); - assert(buf); - - for (size_t i = start_offset; i <= end_offset; ++i) - buf[i] = val; -} - -/** Copy a block of @a src into buffer. - * - * @a start_sample and @a end_sample define the inclusive range to be set. - * This function only copies the same range in one buffer to another. - */ -void -AudioBuffer::copy(const Sample* src, size_t start_sample, size_t end_sample) -{ - assert(end_sample >= start_sample); - assert(nframes() != 0); - - Sample* const buf = data(); - assert(buf); - - const size_t copy_end = std::min(end_sample, (size_t)nframes() - 1); - for (size_t i = start_sample; i <= copy_end; ++i) - buf[i] = src[i]; -} - -void -AudioBuffer::copy(Context& context, const Buffer* src) -{ - const AudioBuffer* src_abuf = dynamic_cast<const AudioBuffer*>(src); - if (!src_abuf) { - clear(); - return; - } - - // Control => Control - if (src_abuf->is_control() == is_control()) { - ObjectBuffer::copy(context, src); - - // Audio => Audio - } else if (!src_abuf->is_control() && !is_control()) { - copy(src_abuf->data(), - context.offset(), context.offset() + context.nframes() - 1); - - // Audio => Control - } else if (!src_abuf->is_control() && is_control()) { - data()[0] = src_abuf->data()[context.offset()]; - - // Control => Audio - } else if (src_abuf->is_control() && !is_control()) { - data()[context.offset()] = src_abuf->data()[0]; - - // Control => Audio or Audio => Control - } else { - set_block(src_abuf->data()[0], 0, nframes()); - } -} - -void -AudioBuffer::prepare_read(Context& context) -{ - assert(nframes() != 0); - switch (_state) { - case HALF_SET_CYCLE_1: - if (context.start() > _set_time) - _state = HALF_SET_CYCLE_2; - break; - case HALF_SET_CYCLE_2: - set_block(_set_value, 0, nframes() - 1); - _state = OK; - break; - default: - break; - } -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/AudioBuffer.hpp b/src/engine/AudioBuffer.hpp deleted file mode 100644 index d0c562a9..00000000 --- a/src/engine/AudioBuffer.hpp +++ /dev/null @@ -1,109 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_AUDIOBUFFER_HPP -#define INGEN_ENGINE_AUDIOBUFFER_HPP - -#include <cstddef> -#include <cassert> -#include <boost/utility.hpp> -#include "types.hpp" -#include "ObjectBuffer.hpp" -#include "Context.hpp" - -using namespace std; - -namespace Ingen { -namespace Engine { - -class AudioBuffer : public ObjectBuffer -{ -public: - AudioBuffer(BufferFactory& bufs, PortType type, size_t capacity); - - void clear(); - - void set_value(Sample val, FrameTime cycle_start, FrameTime time); - void set_block(Sample val, size_t start_offset, size_t end_offset); - void copy(const Sample* src, size_t start_sample, size_t end_sample); - void copy(Context& context, const Buffer* src); - void accumulate(Context& context, const AudioBuffer* src); - - inline bool is_control() const { return _type.symbol() == PortType::CONTROL; } - - inline Sample* data() const { - return (is_control()) - ? (Sample*)atom()->body - : (Sample*)(atom()->body + sizeof(LV2_Atom_Vector)); - } - - inline SampleCount nframes() const { - return (is_control()) - ? 1 - : (_size - sizeof(LV2_Atom) - sizeof(LV2_Atom_Vector)) / sizeof(Sample); - } - - inline Sample& value_at(size_t offset) const - { assert(offset < nframes()); return data()[offset]; } - - void prepare_read(Context& context); - void prepare_write(Context& context) {} - - void resize(size_t size); - -private: - enum State { OK, HALF_SET_CYCLE_1, HALF_SET_CYCLE_2 }; - - LV2_Atom_Vector* vector() { return(LV2_Atom_Vector*)atom()->body; } - - State _state; ///< State of buffer for setting values next cycle - Sample _set_value; ///< Value set by set_value (for completing the set next cycle) - FrameTime _set_time; ///< Time _set_value was set (to reset next cycle) -}; - -/** Accumulate a block of @a src into buffer. - */ -inline void -AudioBuffer::accumulate(Context& context, const AudioBuffer* const src) -{ - Sample* const buf = data(); - const Sample* const src_buf = src->data(); - - if (is_control()) { - if (src->is_control()) { // control => control - buf[0] += src_buf[0]; - } else { // audio => control - buf[0] += src_buf[context.offset()]; - } - } else { - const SampleCount end = context.offset() + context.nframes(); - if (src->is_control()) { // control => audio - for (SampleCount i = context.offset(); i < end; ++i) { - buf[i] += src_buf[0]; - } - } else { // audio => audio - for (SampleCount i = context.offset(); i < end; ++i) { - buf[i] += src_buf[i]; - } - } - } -} - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_AUDIOBUFFER_HPP diff --git a/src/engine/Buffer.hpp b/src/engine/Buffer.hpp deleted file mode 100644 index 56682228..00000000 --- a/src/engine/Buffer.hpp +++ /dev/null @@ -1,97 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_BUFFER_HPP -#define INGEN_ENGINE_BUFFER_HPP - -#include <cstddef> -#include <cassert> -#include <boost/utility.hpp> -#include <boost/intrusive_ptr.hpp> -#include "raul/Deletable.hpp" -#include "raul/SharedPtr.hpp" -#include "ingen/PortType.hpp" -#include "types.hpp" -#include "BufferFactory.hpp" - -namespace Ingen { -namespace Engine { - -class Context; -class Engine; -class BufferFactory; - -class Buffer : public boost::noncopyable, public Raul::Deletable -{ -public: - Buffer(BufferFactory& bufs, PortType type, size_t size) - : _factory(bufs) - , _type(type) - , _size(size) - , _next(NULL) - , _refs(0) - {} - - /** Clear contents and reset state */ - virtual void clear() = 0; - - virtual void resize(size_t size) { _size = size; } - - virtual void* port_data(PortType port_type, SampleCount offset=0) = 0; - virtual const void* port_data(PortType port_type, SampleCount offset=0) const = 0; - - /** Rewind (ie reset read pointer), but leave contents unchanged */ - virtual void rewind() const {} - - virtual void copy(Context& context, const Buffer* src) = 0; - - virtual void prepare_read(Context& context) {} - virtual void prepare_write(Context& context) {} - - PortType type() const { return _type; } - size_t size() const { return _size; } - - inline void ref() { ++_refs; } - - inline void deref() { - assert(_refs > 0); - if ((--_refs) == 0) - _factory.recycle(this); - } - -protected: - BufferFactory& _factory; - PortType _type; - size_t _size; - - friend class BufferFactory; - virtual ~Buffer() {} - -private: - Buffer* _next; ///< Intrusive linked list for BufferFactory - size_t _refs; ///< Intrusive reference count for intrusive_ptr -}; - -} // namespace Engine -} // namespace Ingen - -namespace boost { -inline void intrusive_ptr_add_ref(Ingen::Engine::Buffer* b) { b->ref(); } -inline void intrusive_ptr_release(Ingen::Engine::Buffer* b) { b->deref(); } -} - -#endif // INGEN_ENGINE_BUFFER_HPP diff --git a/src/engine/BufferFactory.cpp b/src/engine/BufferFactory.cpp deleted file mode 100644 index 7aac798a..00000000 --- a/src/engine/BufferFactory.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <algorithm> -#include "raul/log.hpp" -#include "shared/LV2URIMap.hpp" -#include "AudioBuffer.hpp" -#include "EventBuffer.hpp" -#include "ObjectBuffer.hpp" -#include "BufferFactory.hpp" -#include "Engine.hpp" -#include "Driver.hpp" -#include "ThreadManager.hpp" - -using namespace Raul; - -namespace Ingen { -namespace Engine { - -static const size_t EVENT_BYTES_PER_FRAME = 4; // FIXME - -BufferFactory::BufferFactory(Engine& engine, - SharedPtr<Ingen::Shared::LV2URIMap> uris) - : _engine(engine) - , _uris(uris) - , _silent_buffer(NULL) -{ - assert(_uris); -} - -BufferFactory::~BufferFactory() -{ - free_list(_free_audio.get()); - free_list(_free_control.get()); - free_list(_free_event.get()); - free_list(_free_object.get()); -} - -void -BufferFactory::free_list(Buffer* head) -{ - Buffer* next = head->_next; - delete head; - if (next) - free_list(next); -} - -void -BufferFactory::set_block_length(SampleCount block_length) -{ - _silent_buffer = create(PortType::AUDIO, audio_buffer_size(block_length)); -} - -size_t -BufferFactory::audio_buffer_size(SampleCount nframes) -{ - return sizeof(LV2_Atom) + sizeof(LV2_Atom_Vector) + (nframes * sizeof(float)); -} - -size_t -BufferFactory::default_buffer_size(PortType type) -{ - switch (type.symbol()) { - case PortType::AUDIO: - return audio_buffer_size(_engine.driver()->block_length()); - case PortType::CONTROL: - return sizeof(LV2_Atom) + sizeof(float); - case PortType::EVENTS: - return _engine.driver()->block_length() * EVENT_BYTES_PER_FRAME; - default: - return 1024; // Who knows - } -} - -BufferFactory::Ref -BufferFactory::get(PortType type, size_t size, bool force_create) -{ - Raul::AtomicPtr<Buffer>& head_ptr = free_list(type); - Buffer* try_head = NULL; - - if (!force_create) { - Buffer* next; - do { - try_head = head_ptr.get(); - if (!try_head) - break; - next = try_head->_next; - } while (!head_ptr.compare_and_exchange(try_head, next)); - } - - if (!try_head) { - if (!ThreadManager::thread_is(THREAD_PROCESS)) { - return create(type, size); - } else { - assert(false); - error << "Failed to obtain buffer" << endl; - return Ref(); - } - } - - try_head->_next = NULL; - return Ref(try_head); -} - -BufferFactory::Ref -BufferFactory::create(PortType type, size_t size) -{ - ThreadManager::assert_not_thread(THREAD_PROCESS); - - Buffer* buffer = NULL; - - if (size == 0) - size = default_buffer_size(type); - - if (type.is_control()) { - AudioBuffer* ret = new AudioBuffer(*this, type, size); - ret->atom()->type = _uris->atom_Vector.id; - ((LV2_Atom_Vector*)ret->atom()->body)->elem_type = _uris->atom_Float32.id; - buffer = ret; - } else if (type.is_audio()) { - AudioBuffer* ret = new AudioBuffer(*this, type, size); - ret->atom()->type = _uris->atom_Float32.id; - buffer = ret; - } else if (type.is_events()) { - buffer = new EventBuffer(*this, size); - } else if (type.is_value() || type.is_message()) { - buffer = new ObjectBuffer(*this, std::max(size, sizeof(LV2_Atom) + sizeof(void*))); - } else { - error << "Failed to create buffer of unknown type" << endl; - return Ref(); - } - - assert(buffer); - return Ref(buffer); -} - -void -BufferFactory::recycle(Buffer* buf) -{ - Raul::AtomicPtr<Buffer>& head_ptr = free_list(buf->type()); - Buffer* try_head; - do { - try_head = head_ptr.get(); - buf->_next = try_head; - } while (!head_ptr.compare_and_exchange(try_head, buf)); -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/BufferFactory.hpp b/src/engine/BufferFactory.hpp deleted file mode 100644 index 5d6ebf7c..00000000 --- a/src/engine/BufferFactory.hpp +++ /dev/null @@ -1,92 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2009-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_BUFFERFACTORY_HPP -#define INGEN_ENGINE_BUFFERFACTORY_HPP - -#include <map> -#include <boost/intrusive_ptr.hpp> -#include "ingen/PortType.hpp" -#include "glibmm/thread.h" -#include "raul/RingBuffer.hpp" -#include "raul/AtomicPtr.hpp" -#include "types.hpp" - -namespace Ingen { - -namespace Shared { class LV2URIMap; } - -namespace Engine { - -class Engine; -class Buffer; - -class BufferFactory { -public: - BufferFactory(Engine& engine, - SharedPtr<Ingen::Shared::LV2URIMap> uris); - - ~BufferFactory(); - - typedef boost::intrusive_ptr<Buffer> Ref; - - static size_t audio_buffer_size(SampleCount nframes); - size_t default_buffer_size(PortType type); - - Ref get(PortType type, size_t size=0, bool force_create=false); - - Ref silent_buffer() { return _silent_buffer; } - - void set_block_length(SampleCount block_length); - - Ingen::Shared::LV2URIMap& uris() { assert(_uris); return *_uris.get(); } - -private: - friend class Buffer; - void recycle(Buffer* buf); - - Ref create(PortType type, size_t size=0); - - inline Raul::AtomicPtr<Buffer>& free_list(PortType type) { - switch (type.symbol()) { - case PortType::AUDIO: return _free_audio; - case PortType::CONTROL: return _free_control; - case PortType::EVENTS: return _free_event; - case PortType::VALUE: - case PortType::MESSAGE: return _free_object; - default: throw; - } - } - - void free_list(Buffer* head); - - Raul::AtomicPtr<Buffer> _free_audio; - Raul::AtomicPtr<Buffer> _free_control; - Raul::AtomicPtr<Buffer> _free_event; - Raul::AtomicPtr<Buffer> _free_object; - - Glib::Mutex _mutex; - Engine& _engine; - SharedPtr<Ingen::Shared::LV2URIMap> _uris; - - Ref _silent_buffer; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_BUFFERFACTORY_HPP diff --git a/src/engine/ClientBroadcaster.cpp b/src/engine/ClientBroadcaster.cpp deleted file mode 100644 index 46c50ea6..00000000 --- a/src/engine/ClientBroadcaster.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <cassert> -#include <unistd.h> -#include "raul/log.hpp" -#include "ingen/ClientInterface.hpp" -#include "ClientBroadcaster.hpp" -#include "PluginImpl.hpp" -#include "ConnectionImpl.hpp" -#include "EngineStore.hpp" -#include "ObjectSender.hpp" -#include "util.hpp" - -#define LOG(s) s << "[ClientBroadcaster] " - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -/** Register a client to receive messages over the notification band. - */ -void -ClientBroadcaster::register_client(const URI& uri, ClientInterface* client) -{ - Clients::iterator i = _clients.find(uri); - - if (i == _clients.end()) { - _clients[uri] = client; - LOG(info) << "Registered client: " << uri << endl; - } else { - LOG(warn) << "Client already registered: " << uri << endl; - } -} - -/** Remove a client from the list of registered clients. - * - * @return true if client was found and removed. - */ -bool -ClientBroadcaster::unregister_client(const URI& uri) -{ - size_t erased = _clients.erase(uri); - - if (erased > 0) - LOG(info) << "Unregistered client: " << uri << endl; - else - LOG(warn) << "Failed to find client to unregister: " << uri << endl; - - return (erased > 0); -} - -/** Looks up the client with the given source @a uri (which is used as the - * unique identifier for registered clients). - */ -ClientInterface* -ClientBroadcaster::client(const URI& uri) -{ - Clients::iterator i = _clients.find(uri); - if (i != _clients.end()) { - return (*i).second; - } else { - return NULL; - } -} - -void -ClientBroadcaster::send_plugins(const NodeFactory::Plugins& plugins) -{ - for (Clients::const_iterator c = _clients.begin(); c != _clients.end(); ++c) - send_plugins_to((*c).second, plugins); -} - -void -ClientBroadcaster::send_plugins_to(ClientInterface* client, const NodeFactory::Plugins& plugins) -{ - client->bundle_begin(); - - for (NodeFactory::Plugins::const_iterator i = plugins.begin(); i != plugins.end(); ++i) { - const PluginImpl* const plugin = i->second; - client->put(plugin->uri(), plugin->properties()); - } - - client->bundle_end(); -} - -/** Send an object to all clients. - * - * @param o Object to send - * @param recursive If true send all children of object - */ -void -ClientBroadcaster::send_object(const GraphObjectImpl* o, bool recursive) -{ - for (Clients::const_iterator i = _clients.begin(); i != _clients.end(); ++i) - ObjectSender::send_object((*i).second, o, recursive); -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/ClientBroadcaster.hpp b/src/engine/ClientBroadcaster.hpp deleted file mode 100644 index c72cdeec..00000000 --- a/src/engine/ClientBroadcaster.hpp +++ /dev/null @@ -1,131 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_CLIENTBROADCASTER_HPP -#define INGEN_ENGINE_CLIENTBROADCASTER_HPP - -#include <string> -#include <list> -#include <map> -#include <pthread.h> -#include "raul/SharedPtr.hpp" -#include "ingen/ClientInterface.hpp" -#include "NodeFactory.hpp" - -using namespace std; - -namespace Ingen { -namespace Engine { - -class GraphObjectImpl; -class NodeImpl; -class PortImpl; -class PluginImpl; -class PatchImpl; -class ConnectionImpl; - -/** Broadcaster for all clients. - * - * This is a ClientInterface that forwards all messages to all registered - * clients (for updating all clients on state changes in the engine). - * - * \ingroup engine - */ -class ClientBroadcaster : public ClientInterface -{ -public: - void register_client(const Raul::URI& uri, ClientInterface* client); - bool unregister_client(const Raul::URI& uri); - - ClientInterface* client(const Raul::URI& uri); - - void send_plugins(const NodeFactory::Plugins& plugin_list); - void send_plugins_to(ClientInterface*, const NodeFactory::Plugins& plugin_list); - - void send_object(const GraphObjectImpl* p, bool recursive); - -#define BROADCAST(msg, ...) \ - for (Clients::const_iterator i = _clients.begin(); i != _clients.end(); ++i) \ - (*i).second->msg(__VA_ARGS__) - - // CommonInterface - - void bundle_begin() { BROADCAST(bundle_begin); } - void bundle_end() { BROADCAST(bundle_end); } - - void put(const Raul::URI& uri, - const Resource::Properties& properties, - Resource::Graph ctx=Resource::DEFAULT) { - BROADCAST(put, uri, properties); - } - - void delta(const Raul::URI& uri, - const Resource::Properties& remove, - const Resource::Properties& add) { - BROADCAST(delta, uri, remove, add); - } - - void move(const Raul::Path& old_path, - const Raul::Path& new_path) { - BROADCAST(move, old_path, new_path); - } - - void del(const Raul::URI& uri) { - BROADCAST(del, uri); - } - - void connect(const Raul::Path& src_port_path, - const Raul::Path& dst_port_path) { - BROADCAST(connect, src_port_path, dst_port_path); - } - - void disconnect(const Raul::URI& src, - const Raul::URI& dst) { - BROADCAST(disconnect, src, dst); - } - - void disconnect_all(const Raul::Path& parent_patch_path, - const Raul::Path& path) { - BROADCAST(disconnect_all, parent_patch_path, path); - } - - void set_property(const Raul::URI& subject, - const Raul::URI& predicate, - const Raul::Atom& value) { - BROADCAST(set_property, subject, predicate, value); - } - - // ClientInterface - - Raul::URI uri() const { return "http://drobilla.net/ns/ingen#broadcaster"; } ///< N/A - - void response_ok(int32_t id) {} ///< N/A - void response_error(int32_t id, const std::string& msg) {} ///< N/A - - void error(const std::string& msg) { BROADCAST(error, msg); } - void activity(const Raul::Path& path) { BROADCAST(activity, path); } - -private: - typedef std::map<Raul::URI, ClientInterface*> Clients; - Clients _clients; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_CLIENTBROADCASTER_HPP - diff --git a/src/engine/CompiledPatch.hpp b/src/engine/CompiledPatch.hpp deleted file mode 100644 index 274816fb..00000000 --- a/src/engine/CompiledPatch.hpp +++ /dev/null @@ -1,76 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_COMPILEDPATCH_HPP -#define INGEN_ENGINE_COMPILEDPATCH_HPP - -#include <vector> -#include "raul/List.hpp" -#include "raul/Deletable.hpp" -#include <boost/utility.hpp> - -namespace Ingen { -namespace Engine { - -class ConnectionImpl; - -/** All information required about a node to execute it in an audio thread. - */ -struct CompiledNode { - CompiledNode(NodeImpl* n, size_t np, Raul::List<NodeImpl*>* d) - : _node(n), _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 (Raul::List<NodeImpl*>::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<NodeImpl*>& dependants() const { return _dependants; } - -private: - NodeImpl* _node; - size_t _n_providers; ///< Number of input ready signals to trigger run - std::vector<NodeImpl*> _dependants; ///< Nodes 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 - * before its providers, using this order as well as semaphores. - */ -struct CompiledPatch : public std::vector<CompiledNode> - , public Raul::Deletable - , public boost::noncopyable -{ - typedef std::vector<ConnectionImpl*> QueuedConnections; - - /** All (audio context => other context) connections */ - std::vector<ConnectionImpl*> queued_connections; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_COMPILEDPATCH_HPP diff --git a/src/engine/ConnectionImpl.cpp b/src/engine/ConnectionImpl.cpp deleted file mode 100644 index 90ac75ea..00000000 --- a/src/engine/ConnectionImpl.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <algorithm> -#include "raul/log.hpp" -#include "raul/Maid.hpp" -#include "raul/IntrusivePtr.hpp" -#include "shared/LV2URIMap.hpp" -#include "AudioBuffer.hpp" -#include "BufferFactory.hpp" -#include "ConnectionImpl.hpp" -#include "Engine.hpp" -#include "EventBuffer.hpp" -#include "InputPort.hpp" -#include "MessageContext.hpp" -#include "OutputPort.hpp" -#include "PortImpl.hpp" -#include "ProcessContext.hpp" -#include "mix.hpp" -#include "util.hpp" - -namespace Ingen { -namespace Engine { - -/** Constructor for a connection from a node's output port. - * - * This handles both polyphonic and monophonic nodes, transparently to the - * user (InputPort). - */ -ConnectionImpl::ConnectionImpl(BufferFactory& bufs, PortImpl* src_port, PortImpl* dst_port) - : _queue(NULL) - , _bufs(bufs) - , _src_port(src_port) - , _dst_port(dst_port) - , _pending_disconnection(false) -{ - assert(src_port); - assert(dst_port); - assert(src_port != dst_port); - assert(src_port->path() != dst_port->path()); - - if (must_queue()) - _queue = new Raul::RingBuffer(src_port->buffer_size() * 2); -} - -void -ConnectionImpl::dump() const -{ - debug << _src_port->path() << " -> " << _dst_port->path() - << (must_mix() ? " (MIX) " : " (DIRECT) ") - << (must_queue() ? " (QUEUE)" : " (NOQUEUE) ") - << "POLY: " << _src_port->poly() << " => " << _dst_port->poly() << endl; -} - -void -ConnectionImpl::get_sources(Context& context, uint32_t voice, - IntrusivePtr<Buffer>* srcs, uint32_t max_num_srcs, uint32_t& num_srcs) -{ - if (must_queue() && _queue->read_space() > 0) { - LV2_Atom obj; - _queue->peek(sizeof(LV2_Atom), &obj); - IntrusivePtr<Buffer> buf = context.engine().buffer_factory()->get( - dst_port()->buffer_type(), sizeof(LV2_Atom) + obj.size); - void* data = buf->port_data(PortType::MESSAGE, context.offset()); - _queue->full_read(sizeof(LV2_Atom) + obj.size, (LV2_Atom*)data); - srcs[num_srcs++] = buf; - } else if (must_mix()) { - // Mixing down voices: every src voice mixed into every dst voice - for (uint32_t v = 0; v < _src_port->poly(); ++v) { - assert(num_srcs < max_num_srcs); - srcs[num_srcs++] = _src_port->buffer(v).get(); - } - } else { - // Matching polyphony: each src voice mixed into corresponding dst voice - assert(_src_port->poly() == _dst_port->poly()); - assert(num_srcs < max_num_srcs); - srcs[num_srcs++] = _src_port->buffer(voice).get(); - } -} - -void -ConnectionImpl::queue(Context& context) -{ - if (!must_queue()) - return; - - IntrusivePtr<EventBuffer> src_buf = PtrCast<EventBuffer>(_src_port->buffer(0)); - if (!src_buf) { - error << "Queued connection but source is not an EventBuffer" << endl; - return; - } - - for (src_buf->rewind(); src_buf->is_valid(); src_buf->increment()) { - LV2_Event* ev = src_buf->get_event(); - LV2_Atom* obj = LV2_ATOM_FROM_EVENT(ev); - /*debug << _src_port->path() << " -> " << _dst_port->path() - << " QUEUE OBJECT TYPE " << obj->type << ":"; - for (size_t i = 0; i < obj->size; ++i) - debug << " " << std::hex << (int)obj->body[i]; - debug << endl;*/ - - _queue->write(sizeof(LV2_Atom) + obj->size, obj); - context.engine().message_context()->run(_dst_port->parent_node(), context.start() + ev->frames); - } -} - -bool -ConnectionImpl::can_connect(const OutputPort* src, const InputPort* dst) -{ - const Ingen::Shared::LV2URIMap& uris = src->bufs().uris(); - return ( - // (Audio | Control) => (Audio | Control) - ( (src->is_a(PortType::CONTROL) || src->is_a(PortType::AUDIO)) - && (dst->is_a(PortType::CONTROL) || dst->is_a(PortType::AUDIO))) - - // (Events | Message) => (Events | Message) - || ( (src->is_a(PortType::EVENTS) || src->is_a(PortType::MESSAGE)) - && (dst->is_a(PortType::EVENTS) || dst->is_a(PortType::MESSAGE))) - - // (Message | Value) => (Message | Value) - || ( (src->is_a(PortType::MESSAGE) || src->is_a(PortType::VALUE)) - && (dst->is_a(PortType::MESSAGE) || dst->is_a(PortType::VALUE))) - - // Control => atom:Float32 Value - || (src->is_a(PortType::CONTROL) && dst->supports(uris.atom_Float32)) - - // Audio => atom:Vector Value - || (src->is_a(PortType::AUDIO) && dst->supports(uris.atom_Vector)) - - // atom:Float32 Value => Control - || (src->supports(uris.atom_Float32) && dst->is_a(PortType::CONTROL)) - - // atom:Vector Value => Audio - || (src->supports(uris.atom_Vector) && dst->is_a(PortType::AUDIO))); -} - -} // namespace Engine -} // namespace Ingen - diff --git a/src/engine/ConnectionImpl.hpp b/src/engine/ConnectionImpl.hpp deleted file mode 100644 index d28196fc..00000000 --- a/src/engine/ConnectionImpl.hpp +++ /dev/null @@ -1,110 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_CONNECTIONIMPL_HPP -#define INGEN_ENGINE_CONNECTIONIMPL_HPP - -#include <cstdlib> -#include <boost/utility.hpp> -#include "raul/log.hpp" -#include "raul/Deletable.hpp" -#include "raul/IntrusivePtr.hpp" -#include "ingen/PortType.hpp" -#include "ingen/Connection.hpp" -#include "lv2/lv2plug.in/ns/ext/atom/atom.h" -#include "PortImpl.hpp" - -using namespace std; - -namespace Ingen { -namespace Engine { - -class PortImpl; -class OutputPort; -class InputPort; -class Buffer; -class BufferFactory; - -/** Represents a single inbound connection for an InputPort. - * - * This can be a group of ports (ie coming from a polyphonic Node) 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 - * connection itself). - * - * \ingroup engine - */ -class ConnectionImpl : public Raul::Deletable, public Connection -{ -public: - ConnectionImpl(BufferFactory& bufs, PortImpl* src_port, PortImpl* dst_port); - - PortImpl* src_port() const { return _src_port; } - PortImpl* dst_port() const { return _dst_port; } - - const Raul::Path src_port_path() const { return _src_port->path(); } - const Raul::Path dst_port_path() const { return _dst_port->path(); } - - /** Used by some (recursive) events to prevent double disconnections */ - bool pending_disconnection() { return _pending_disconnection; } - void pending_disconnection(bool b) { _pending_disconnection = b; } - - void queue(Context& context); - - void get_sources(Context& context, uint32_t voice, - IntrusivePtr<Buffer>* srcs, uint32_t max_num_srcs, uint32_t& num_srcs); - - /** Get the buffer for a particular voice. - * A Connection is smart - it knows the destination port requesting the - * buffer, and will return accordingly (e.g. the same buffer for every - * voice in a mono->poly connection). - */ - inline BufferFactory::Ref buffer(uint32_t voice) const { - assert(!must_mix()); - assert(!must_queue()); - assert(_src_port->poly() == 1 || _src_port->poly() > voice); - if (_src_port->poly() == 1) { - return _src_port->buffer(0); - } else { - return _src_port->buffer(voice); - } - } - - /** Returns true if this connection must mix down voices into a local buffer */ - inline bool must_mix() const { return _src_port->poly() > _dst_port->poly(); } - - /** Returns true if this connection crosses contexts and must buffer */ - inline bool must_queue() const { return _src_port->context() != _dst_port->context(); } - - static bool can_connect(const OutputPort* src, const InputPort* dst); - -protected: - void dump() const; - - Raul::RingBuffer* _queue; - - BufferFactory& _bufs; - PortImpl* const _src_port; - PortImpl* const _dst_port; - bool _pending_disconnection; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_CONNECTIONIMPL_HPP diff --git a/src/engine/Context.hpp b/src/engine/Context.hpp deleted file mode 100644 index 5ffb8a93..00000000 --- a/src/engine/Context.hpp +++ /dev/null @@ -1,107 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_CONTEXT_HPP -#define INGEN_ENGINE_CONTEXT_HPP - -#include "shared/World.hpp" - -#include "Engine.hpp" -#include "EventSink.hpp" -#include "types.hpp" - -namespace Ingen { -namespace Engine { - -class Engine; - -/** Graph execution context. - * - * This is used to pass whatever information a GraphObject might need to - * process; such as the current time, a sink for generated events, etc. - * - * Note the logical distinction between nframes (jack relative) and start/end - * (timeline relative). If transport speed != 1.0, then end-start != nframes - * (though currently this is never the case, it may be if ingen incorporates - * tempo and varispeed). - * - * \ingroup engine - */ -class Context -{ -public: - enum ID { - AUDIO, - MESSAGE - }; - - Context(Engine& engine, ID id) - : _engine(engine) - , _id(id) - , _event_sink(engine, engine.event_queue_size()) - , _start(0) - , _end(0) - , _nframes(0) - , _offset(0) - , _realtime(true) - {} - - virtual ~Context() {} - - ID id() const { return _id; } - - void locate(FrameTime s, SampleCount nframes, SampleCount offset) { - _start = s; - _end = s + nframes; - _nframes = nframes; - _offset = offset; - } - - void locate(const Context& other) { - _start = other._start; - _end = other._end; - _nframes = other._nframes; - _offset = other._offset; - } - - inline Engine& engine() const { return _engine; } - inline FrameTime start() const { return _start; } - inline FrameTime end() const { return _end; } - inline SampleCount nframes() const { return _nframes; } - inline SampleCount offset() const { return _offset; } - inline bool realtime() const { return _realtime; } - - inline const EventSink& event_sink() const { return _event_sink; } - inline EventSink& event_sink() { return _event_sink; } - -protected: - Engine& _engine; ///< Engine we're running in - ID _id; ///< Fast ID for this context - - EventSink _event_sink; ///< Sink for events generated in a realtime context - FrameTime _start; ///< Start frame of this cycle, timeline relative - FrameTime _end; ///< End frame of this cycle, timeline relative - SampleCount _nframes; ///< Length of this cycle in frames - SampleCount _offset; ///< Start offset relative to start of driver buffers - bool _realtime; ///< True iff context is hard realtime -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_CONTEXT_HPP - diff --git a/src/engine/ControlBindings.cpp b/src/engine/ControlBindings.cpp deleted file mode 100644 index 6c5b2f95..00000000 --- a/src/engine/ControlBindings.cpp +++ /dev/null @@ -1,384 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2009-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <math.h> -#include "raul/log.hpp" -#include "raul/midi_events.h" -#include "shared/LV2URIMap.hpp" -#include "shared/World.hpp" -#include "events/SendPortValue.hpp" -#include "events/SendBinding.hpp" -#include "AudioBuffer.hpp" -#include "ControlBindings.hpp" -#include "Engine.hpp" -#include "EventBuffer.hpp" -#include "PortImpl.hpp" -#include "ProcessContext.hpp" -#include "ThreadManager.hpp" - -#define LOG(s) s << "[ControlBindings] " - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -ControlBindings::ControlBindings(Engine& engine) - : _engine(engine) - , _learn_port(NULL) - , _bindings(new Bindings()) - , _feedback(new EventBuffer(*_engine.buffer_factory(), 1024)) // FIXME: size -{ -} - -ControlBindings::~ControlBindings() -{ - delete _feedback; -} - -ControlBindings::Key -ControlBindings::port_binding(PortImpl* port) -{ - const Ingen::Shared::LV2URIMap& uris = *_engine.world()->uris().get(); - const Raul::Atom& binding = port->get_property(uris.ingen_controlBinding); - Key key; - if (binding.type() == Atom::DICT) { - const Atom::DictValue& dict = binding.get_dict(); - Atom::DictValue::const_iterator t = dict.find(uris.rdf_type); - Atom::DictValue::const_iterator n; - if (t == dict.end()) { - return key; - } else if (t->second == uris.midi_Bender) { - key = Key(MIDI_BENDER); - } else if (t->second == uris.midi_ChannelPressure) { - key = Key(MIDI_CHANNEL_PRESSURE); - } else if (t->second == uris.midi_Controller) { - if ((n = dict.find(uris.midi_controllerNumber)) != dict.end()) - key = Key(MIDI_CC, n->second.get_int32()); - } else if (t->second == uris.midi_Note) { - if ((n = dict.find(uris.midi_noteNumber)) != dict.end()) - key = Key(MIDI_NOTE, n->second.get_int32()); - } - } - return key; -} - -ControlBindings::Key -ControlBindings::midi_event_key(uint16_t size, uint8_t* buf, uint16_t& value) -{ - switch (buf[0] & 0xF0) { - case MIDI_CMD_CONTROL: - value = static_cast<const int8_t>(buf[2]); - return Key(MIDI_CC, static_cast<const int8_t>(buf[1])); - case MIDI_CMD_BENDER: - value = (static_cast<int8_t>(buf[2]) << 7) + static_cast<int8_t>(buf[1]); - return Key(MIDI_BENDER); - case MIDI_CMD_CHANNEL_PRESSURE: - value = static_cast<const int8_t>(buf[1]); - return Key(MIDI_CHANNEL_PRESSURE); - case MIDI_CMD_NOTE_ON: - value = 1.0f; - return Key(MIDI_NOTE, static_cast<const int8_t>(buf[1])); - default: - return Key(); - } -} - -void -ControlBindings::port_binding_changed(ProcessContext& context, PortImpl* port) -{ - Key key = port_binding(port); - if (key) - _bindings->insert(make_pair(key, port)); -} - -void -ControlBindings::port_value_changed(ProcessContext& context, PortImpl* port) -{ - const Ingen::Shared::LV2URIMap& uris = *_engine.world()->uris().get(); - Key key = port_binding(port); - if (key) { - int16_t value = port_value_to_control(port, key.type); - uint16_t size = 0; - uint8_t buf[4]; - switch (key.type) { - case MIDI_CC: - size = 3; - buf[0] = MIDI_CMD_CONTROL; - buf[1] = key.num; - buf[2] = static_cast<int8_t>(value); - break; - case MIDI_CHANNEL_PRESSURE: - size = 2; - buf[0] = MIDI_CMD_CHANNEL_PRESSURE; - buf[1] = static_cast<int8_t>(value); - break; - case MIDI_BENDER: - size = 3; - buf[0] = MIDI_CMD_BENDER; - buf[1] = (value & 0x007F); - buf[2] = (value & 0x7F00) >> 7; - break; - case MIDI_NOTE: - size = 3; - if (value == 1) - buf[0] = MIDI_CMD_NOTE_ON; - else if (value == 0) - buf[0] = MIDI_CMD_NOTE_OFF; - buf[1] = key.num; - buf[2] = 0x64; // MIDI spec default - break; - default: - break; - } - if (size > 0) { - _feedback->append(0, 0, - uris.global_to_event(uris.midi_MidiEvent.id).second, - size, buf); - } - } -} - -void -ControlBindings::learn(PortImpl* port) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - _learn_port = port; -} - -Raul::Atom -ControlBindings::control_to_port_value(PortImpl* port, Type type, int16_t value) -{ - const Ingen::Shared::LV2URIMap& uris = *_engine.world()->uris().get(); - - // TODO: cache these to avoid the lookup - float min = port->get_property(uris.lv2_minimum).get_float(); - float max = port->get_property(uris.lv2_maximum).get_float(); - bool toggled = port->has_property(uris.lv2_portProperty, uris.lv2_toggled); - - float normal = 0.0f; - switch (type) { - case MIDI_CC: - case MIDI_CHANNEL_PRESSURE: - normal = (float)value / 127.0f; - break; - case MIDI_BENDER: - normal = (float)value / 16383.0f; - break; - case MIDI_NOTE: - normal = (value == 0.0f) ? 0.0f : 1.0f; - break; - default: - break; - } - - float scaled_value = normal * (max - min) + min; - if (toggled) - scaled_value = (scaled_value < 0.5) ? 0.0 : 1.0; - - return Raul::Atom(scaled_value); -} - -int16_t -ControlBindings::port_value_to_control(PortImpl* port, Type type) -{ - if (port->value().type() != Atom::FLOAT) - return 0; - - const Ingen::Shared::LV2URIMap& uris = *_engine.world()->uris().get(); - - // TODO: cache these to avoid the lookup - float min = port->get_property(uris.lv2_minimum).get_float(); - float max = port->get_property(uris.lv2_maximum).get_float(); - //bool toggled = port->has_property(uris.lv2_portProperty, uris.lv2_toggled); - float value = port->value().get_float(); - float normal = (value - min) / (max - min); - - if (normal < 0.0f) { - warn << "Value " << value << " (normal " << normal << ") for " - << port->path() << " out of range" << endl; - normal = 0.0f; - } - - if (normal > 1.0f) { - warn << "Value " << value << " (normal " << normal << ") for " - << port->path() << " out of range" << endl; - normal = 1.0f; - } - - switch (type) { - case MIDI_CC: - case MIDI_CHANNEL_PRESSURE: - return lrintf(normal * 127.0f); - case MIDI_BENDER: - return lrintf(normal * 16383.0f); - case MIDI_NOTE: - return (value > 0.0f) ? 1 : 0; - default: - return 0; - } -} - -void -ControlBindings::set_port_value(ProcessContext& context, PortImpl* port, Type type, int16_t value) -{ - const Raul::Atom port_value(control_to_port_value(port, type, value)); - port->set_value(port_value); - - assert(port_value.type() == Atom::FLOAT); - assert(dynamic_cast<AudioBuffer*>(port->buffer(0).get())); - - for (uint32_t v = 0; v < port->poly(); ++v) - reinterpret_cast<AudioBuffer*>(port->buffer(v).get())->set_value( - port_value.get_float(), context.start(), context.start()); - - const Events::SendPortValue ev(context.engine(), context.start(), port, true, 0, port_value); - context.event_sink().write(sizeof(ev), &ev); -} - -bool -ControlBindings::bind(ProcessContext& context, Key key) -{ - const Ingen::Shared::LV2URIMap& uris = *context.engine().world()->uris().get(); - assert(_learn_port); - if (key.type == MIDI_NOTE) { - bool toggled = _learn_port->has_property(uris.lv2_portProperty, uris.lv2_toggled); - if (!toggled) - return false; - } - - _bindings->insert(make_pair(key, _learn_port)); - - const Events::SendBinding ev(context.engine(), context.start(), _learn_port, key.type, key.num); - context.event_sink().write(sizeof(ev), &ev); - - _learn_port = NULL; - return true; -} - -SharedPtr<ControlBindings::Bindings> -ControlBindings::remove(const Raul::Path& path) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - - SharedPtr<Bindings> old_bindings(_bindings); - SharedPtr<Bindings> copy(new Bindings(*_bindings.get())); - - for (Bindings::iterator i = copy->begin(); i != copy->end();) { - Bindings::iterator next = i; - ++next; - - if (i->second->path() == path || i->second->path().is_child_of(path)) - copy->erase(i); - - i = next; - } - - _bindings = copy; - return old_bindings; -} - -SharedPtr<ControlBindings::Bindings> -ControlBindings::remove(PortImpl* port) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - - SharedPtr<Bindings> old_bindings(_bindings); - SharedPtr<Bindings> copy(new Bindings(*_bindings.get())); - - for (Bindings::iterator i = copy->begin(); i != copy->end();) { - Bindings::iterator next = i; - ++next; - - if (i->second == port) - copy->erase(i); - - i = next; - } - - _bindings = copy; - return old_bindings; -} - -void -ControlBindings::pre_process(ProcessContext& context, EventBuffer* buffer) -{ - uint32_t frames = 0; - uint32_t subframes = 0; - uint16_t type = 0; - uint16_t size = 0; - uint8_t* buf = NULL; - uint16_t value = 0; - - SharedPtr<Bindings> bindings = _bindings; - _feedback->clear(); - - const Ingen::Shared::LV2URIMap& uris = *context.engine().world()->uris().get(); - - // TODO: cache - const uint32_t midi_event_type = uris.global_to_event(uris.midi_MidiEvent.id).second; - - // Learn from input if necessary - if (_learn_port) { - for (buffer->rewind(); - buffer->get_event(&frames, &subframes, &type, &size, &buf); - buffer->increment()) { - if (type != midi_event_type) - continue; - - const Key key = midi_event_key(size, buf, value); - if (key && bind(context, key)) - break; - } - } - - // If bindings are empty, no sense reading input - if (bindings->empty()) - return; - - // Read input and apply control values - for (buffer->rewind(); - buffer->get_event(&frames, &subframes, &type, &size, &buf); - buffer->increment()) { - if (type != midi_event_type) - continue; - - const Key key = midi_event_key(size, buf, value); - if (!key) - continue; - - Bindings::const_iterator i = bindings->find(key); - if (i == bindings->end()) - continue; - - set_port_value(context, i->second, key.type, value); - } -} - -void -ControlBindings::post_process(ProcessContext& context, EventBuffer* buffer) -{ - if (_feedback->event_count() > 0) { - // TODO: merge buffer's existing contents (anything send to it in the patch) - _feedback->rewind(); - buffer->copy(context, _feedback); - } -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/ControlBindings.hpp b/src/engine/ControlBindings.hpp deleted file mode 100644 index 2b2946ec..00000000 --- a/src/engine/ControlBindings.hpp +++ /dev/null @@ -1,102 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2009-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_CONTROLBINDINGS_HPP -#define INGEN_ENGINE_CONTROLBINDINGS_HPP - -#include <stdint.h> -#include <map> -#include "raul/SharedPtr.hpp" -#include "raul/Path.hpp" -#include "shared/LV2URIMap.hpp" -#include "BufferFactory.hpp" - -namespace Ingen { -namespace Engine { - -class Engine; -class ProcessContext; -class EventBuffer; -class PortImpl; - -class ControlBindings { -public: - enum Type { - NULL_CONTROL, - MIDI_BENDER, - MIDI_CC, - MIDI_RPN, - MIDI_NRPN, - MIDI_CHANNEL_PRESSURE, - MIDI_NOTE - }; - - struct Key { - Key(Type t=NULL_CONTROL, int16_t n=0) : type(t), num(n) {} - inline bool operator<(const Key& other) const { - return (type == other.type) ? (num < other.num) : (type < other.type); - } - inline operator bool() const { return type != NULL_CONTROL; } - Type type; - int16_t num; - }; - - typedef std::map<Key, PortImpl*> Bindings; - - explicit ControlBindings(Engine& engine); - ~ControlBindings(); - - void learn(PortImpl* port); - - void port_binding_changed(ProcessContext& context, PortImpl* port); - void port_value_changed(ProcessContext& context, PortImpl* port); - void pre_process(ProcessContext& context, EventBuffer* control_in); - void post_process(ProcessContext& context, EventBuffer* control_out); - - /** Remove all bindings for @a path or children of @a path. - * The caller must safely drop the returned reference in the - * post-processing thread after at least one process thread has run. - */ - SharedPtr<Bindings> remove(const Raul::Path& path); - - /** Remove binding for a particular port. - * The caller must safely drop the returned reference in the - * post-processing thread after at least one process thread has run. - */ - SharedPtr<Bindings> remove(PortImpl* port); - -private: - Key port_binding(PortImpl* port); - Key midi_event_key(uint16_t size, uint8_t* buf, uint16_t& value); - - void set_port_value(ProcessContext& context, PortImpl* port, Type type, int16_t value); - bool bind(ProcessContext& context, Key key); - - Raul::Atom control_to_port_value(PortImpl* port, Type type, int16_t value); - int16_t port_value_to_control(PortImpl* port, Type type); - - Engine& _engine; - PortImpl* _learn_port; - - SharedPtr<Bindings> _bindings; - EventBuffer* _feedback; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_CONTROLBINDINGS_HPP diff --git a/src/engine/Driver.hpp b/src/engine/Driver.hpp deleted file mode 100644 index f47f2b44..00000000 --- a/src/engine/Driver.hpp +++ /dev/null @@ -1,123 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_DRIVER_HPP -#define INGEN_ENGINE_DRIVER_HPP - -#include <string> -#include <boost/utility.hpp> -#include "raul/Deletable.hpp" -#include "ingen/PortType.hpp" -#include "ingen/EventType.hpp" -#include "DuplexPort.hpp" - -namespace Raul { class Path; } - -namespace Ingen { -namespace Engine { - -class DuplexPort; -class ProcessContext; - -/** Representation of a "system" (eg outside Ingen) port. - * - * This is the class through which the rest of the engine manages everything - * related to driver ports. Derived classes are expected to have a pointer to - * their driver (to be able to perform the operation necessary). - * - * \ingroup engine - */ -class DriverPort : boost::noncopyable, public Raul::Deletable { -public: - virtual ~DriverPort() {} - - /** Set the name of the system port according to new path */ - virtual void move(const Raul::Path& path) = 0; - - /** Create system port */ - virtual void create() = 0; - - /** Destroy system port */ - virtual void destroy() = 0; - - bool is_input() const { return _patch_port->is_input(); } - DuplexPort* patch_port() const { return _patch_port; } - -protected: - explicit DriverPort(DuplexPort* port) : _patch_port(port) {} - - DuplexPort* _patch_port; -}; - -/** Driver abstract 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 DriverPorts, and handle writing/reading data to/from them. - * - * \ingroup engine - */ -class Driver : boost::noncopyable { -public: - virtual ~Driver() {} - - /** Activate driver (begin processing graph and events). */ - virtual void activate() {} - - /** Deactivate driver (stop processing graph and events). */ - virtual void deactivate() {} - - /** Create a port ready to be inserted with add_input (non realtime). - * May return NULL if the Driver can not create the port for some reason. - */ - virtual DriverPort* create_port(DuplexPort* patch_port) = 0; - - /** Return the DriverPort for a particular path, iff one exists. */ - virtual DriverPort* driver_port(const Raul::Path& path) = 0; - - /** Add a system visible port (e.g. a port on the root patch). */ - virtual void add_port(DriverPort* port) = 0; - - /** Remove a system visible port. */ - virtual Raul::Deletable* remove_port(const Raul::Path& path, - DriverPort** port=NULL) = 0; - - /** Return true iff this driver supports the given type of I/O */ - virtual bool supports(PortType port_type, - EventType event_type) = 0; - - virtual void set_root_patch(PatchImpl* patch) = 0; - virtual PatchImpl* root_patch() = 0; - - /** Return the audio buffer size in frames */ - virtual SampleCount block_length() const = 0; - - /** Return the sample rate in Hz */ - virtual SampleCount sample_rate() const = 0; - - /** Return the current frame time (running counter) */ - virtual SampleCount frame_time() const = 0; - - virtual bool is_realtime() const = 0; - - virtual ProcessContext& context() = 0; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_DRIVER_HPP diff --git a/src/engine/DuplexPort.cpp b/src/engine/DuplexPort.cpp deleted file mode 100644 index ecd8da27..00000000 --- a/src/engine/DuplexPort.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <cstdlib> -#include <cassert> -#include <string> - -#include "shared/LV2URIMap.hpp" - -#include "ConnectionImpl.hpp" -#include "DuplexPort.hpp" -#include "EventBuffer.hpp" -#include "NodeImpl.hpp" -#include "OutputPort.hpp" -#include "ProcessContext.hpp" -#include "util.hpp" - -using namespace std; - -namespace Ingen { -namespace Engine { - -DuplexPort::DuplexPort( - BufferFactory& bufs, - NodeImpl* parent, - const string& name, - uint32_t index, - bool polyphonic, - uint32_t poly, - PortType type, - const Raul::Atom& value, - size_t buffer_size, - bool is_output) - : PortImpl(bufs, parent, name, index, poly, type, value, buffer_size) - , InputPort(bufs, parent, name, index, poly, type, value, buffer_size) - , OutputPort(bufs, parent, name, index, poly, type, value, buffer_size) - , _is_output(is_output) -{ - assert(PortImpl::_parent == parent); - set_property(bufs.uris().ingen_polyphonic, polyphonic); -} - -bool -DuplexPort::get_buffers(BufferFactory& bufs, Raul::Array<BufferFactory::Ref>* buffers, uint32_t poly) -{ - if (_is_output) - return InputPort::get_buffers(bufs, buffers, poly); - else - return OutputPort::get_buffers(bufs, buffers, poly); -} - -/** Prepare for the execution of parent patch */ -void -DuplexPort::pre_process(Context& context) -{ - // If we're a patch output, we're an input from the internal perspective. - // Prepare buffers for write (so plugins can deliver to them) - if (_is_output) { - for (uint32_t v = 0; v < _poly; ++v) - _buffers->at(v)->prepare_write(context); - - // If we're a patch input, were an output from the internal perspective. - // Do whatever a normal node's input port does to prepare input for reading. - } else { - InputPort::pre_process(context); - } -} - -/** Finalize after the execution of parent patch (deliver outputs) */ -void -DuplexPort::post_process(Context& context) -{ - // If we're a patch output, we're an input from the internal perspective. - // Mix down input delivered by plugins so output (external perspective) is ready. - if (_is_output) { - InputPort::pre_process(context); - - if (_broadcast) - broadcast_value(context, false); - } -} - -} // namespace Engine -} // namespace Ingen - diff --git a/src/engine/DuplexPort.hpp b/src/engine/DuplexPort.hpp deleted file mode 100644 index 4341c6e3..00000000 --- a/src/engine/DuplexPort.hpp +++ /dev/null @@ -1,70 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_DUPLEXPORT_HPP -#define INGEN_ENGINE_DUPLEXPORT_HPP - -#include <string> -#include "Buffer.hpp" -#include "InputPort.hpp" -#include "OutputPort.hpp" - -namespace Ingen { -namespace Engine { - -class NodeImpl; - -/** A duplex port (which is both an InputPort and an OutputPort) - * - * This is used for Patch ports, since they need to appear as both an input - * and an output port based on context. Eg. a patch output appears as an - * input inside the patch, so nodes inside the patch can feed it data. - * - * \ingroup engine - */ -class DuplexPort : public InputPort, public OutputPort -{ -public: - DuplexPort(BufferFactory& bufs, - NodeImpl* parent, - const std::string& name, - uint32_t index, - bool polyphonic, - uint32_t poly, - PortType type, - const Raul::Atom& value, - size_t buffer_size, - bool is_output); - - virtual ~DuplexPort() {} - - bool get_buffers(BufferFactory& bufs, Raul::Array<BufferFactory::Ref>* buffers, uint32_t poly); - - void pre_process(Context& context); - void post_process(Context& context); - - bool is_input() const { return !_is_output; } - bool is_output() const { return _is_output; } - -protected: - bool _is_output; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_DUPLEXPORT_HPP diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp deleted file mode 100644 index 357604ed..00000000 --- a/src/engine/Engine.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <cassert> -#include <sys/mman.h> -#include <unistd.h> -#include "raul/log.hpp" -#include "raul/Deletable.hpp" -#include "raul/Maid.hpp" -#include "raul/SharedPtr.hpp" -#include "lv2/lv2plug.in/ns/ext/uri-map/uri-map.h" -#include "ingen/EventType.hpp" -#include "events/CreatePatch.hpp" -#include "events/CreatePort.hpp" -#include "shared/World.hpp" -#include "shared/LV2Features.hpp" -#include "shared/LV2URIMap.hpp" -#include "shared/Store.hpp" -#include "BufferFactory.hpp" -#include "ClientBroadcaster.hpp" -#include "ControlBindings.hpp" -#include "Driver.hpp" -#include "Engine.hpp" -#include "EngineStore.hpp" -#include "Event.hpp" -#include "EventSource.hpp" -#include "MessageContext.hpp" -#include "NodeFactory.hpp" -#include "PatchImpl.hpp" -#include "PostProcessor.hpp" -#include "ProcessContext.hpp" -#include "QueuedEngineInterface.hpp" -#include "ThreadManager.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -bool ThreadManager::single_threaded = true; - -Engine::Engine(Ingen::Shared::World* a_world) - : _world(a_world) - , _broadcaster(new ClientBroadcaster()) - , _buffer_factory(new BufferFactory(*this, a_world->uris())) - , _control_bindings(new ControlBindings(*this)) - , _maid(new Raul::Maid(event_queue_size())) - , _message_context(new MessageContext(*this)) - , _node_factory(new NodeFactory(a_world)) - , _post_processor(new PostProcessor(*this, event_queue_size())) -{ - if (a_world->store()) { - assert(PtrCast<EngineStore>(a_world->store())); - } else { - a_world->set_store(SharedPtr<Ingen::Shared::Store>(new EngineStore())); - } -} - -Engine::~Engine() -{ - deactivate(); - - SharedPtr<EngineStore> store = engine_store(); - if (store) - for (EngineStore::iterator i = store->begin(); i != store->end(); ++i) - if ( ! PtrCast<GraphObjectImpl>(i->second)->parent() ) - i->second.reset(); - - delete _maid; - delete _post_processor; - delete _node_factory; - delete _broadcaster; - - munlockall(); -} - -SharedPtr<EngineStore> -Engine::engine_store() const -{ - return PtrCast<EngineStore>(_world->store()); -} - -size_t -Engine::event_queue_size() const -{ - return world()->conf()->option("queue-size").get_int32(); -} - -void -Engine::quit() -{ - _quit_flag = true; -} - -bool -Engine::main_iteration() -{ - _post_processor->process(); - _maid->cleanup(); - return !_quit_flag; -} - -void -Engine::add_event_source(SharedPtr<EventSource> source) -{ - _event_sources.insert(source); -} - -void -Engine::set_driver(SharedPtr<Driver> driver) -{ - _driver = driver; -} - -static void -execute_and_delete_event(ProcessContext& context, QueuedEvent* ev) -{ - ev->pre_process(); - ev->execute(context); - ev->post_process(); - delete ev; -} - -bool -Engine::activate() -{ - assert(_driver); - ThreadManager::single_threaded = true; - - _buffer_factory->set_block_length(_driver->block_length()); - - _message_context->Thread::start(); - - const Ingen::Shared::LV2URIMap& uris = *world()->uris().get(); - - // Create root patch - PatchImpl* root_patch = _driver->root_patch(); - if (!root_patch) { - root_patch = new PatchImpl(*this, "root", 1, NULL, _driver->sample_rate(), 1); - root_patch->set_property(uris.rdf_type, - Resource::Property(uris.ingen_Patch, Resource::INTERNAL)); - root_patch->set_property(uris.ingen_polyphony, - Resource::Property(Raul::Atom(int32_t(1)), - Resource::INTERNAL)); - root_patch->activate(*_buffer_factory); - _world->store()->add(root_patch); - root_patch->compiled_patch(root_patch->compile()); - _driver->set_root_patch(root_patch); - - ProcessContext context(*this); - - Resource::Properties control_properties; - control_properties.insert(make_pair(uris.lv2_name, "Control")); - control_properties.insert(make_pair(uris.rdf_type, uris.ev_EventPort)); - - // Add control input - Resource::Properties in_properties(control_properties); - in_properties.insert(make_pair(uris.rdf_type, uris.lv2_InputPort)); - in_properties.insert(make_pair(uris.lv2_index, 0)); - in_properties.insert(make_pair(uris.ingenui_canvas_x, - Resource::Property(32.0f, Resource::EXTERNAL))); - in_properties.insert(make_pair(uris.ingenui_canvas_y, - Resource::Property(32.0f, Resource::EXTERNAL))); - - execute_and_delete_event(context, new Events::CreatePort( - *this, SharedPtr<Request>(), 0, - "/control_in", uris.ev_EventPort, false, in_properties)); - - // Add control out - Resource::Properties out_properties(control_properties); - out_properties.insert(make_pair(uris.rdf_type, uris.lv2_OutputPort)); - out_properties.insert(make_pair(uris.lv2_index, 1)); - out_properties.insert(make_pair(uris.ingenui_canvas_x, - Resource::Property(128.0f, Resource::EXTERNAL))); - out_properties.insert(make_pair(uris.ingenui_canvas_y, - Resource::Property(32.0f, Resource::EXTERNAL))); - - execute_and_delete_event(context, new Events::CreatePort( - *this, SharedPtr<Request>(), 0, - "/control_out", uris.ev_EventPort, true, out_properties)); - } - - _driver->activate(); - root_patch->enable(); - - ThreadManager::single_threaded = false; - - return true; -} - -void -Engine::deactivate() -{ - _driver->deactivate(); - _driver->root_patch()->deactivate(); - - ThreadManager::single_threaded = true; -} - -void -Engine::process_events(ProcessContext& context) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - - for (EventSources::iterator i = _event_sources.begin(); i != _event_sources.end(); ++i) - (*i)->process(*_post_processor, context); -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/Engine.hpp b/src/engine/Engine.hpp deleted file mode 100644 index ffcd5dc9..00000000 --- a/src/engine/Engine.hpp +++ /dev/null @@ -1,115 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_ENGINE_HPP -#define INGEN_ENGINE_ENGINE_HPP - -#include <set> -#include <vector> - -#include <boost/utility.hpp> - -#include "raul/SharedPtr.hpp" - -#include "ingen/EngineBase.hpp" - -namespace Raul { class Maid; } - -namespace Ingen { - -namespace Shared { class World; } - -namespace Engine { - -class BufferFactory; -class ClientBroadcaster; -class ControlBindings; -class Driver; -class EngineStore; -class EventSource; -class MessageContext; -class NodeFactory; -class PostProcessor; -class ProcessContext; - -/** - The engine which executes the process graph. - - This is a simple class that provides pointers to the various components - that make up the engine implementation. In processes with a local engine, - it can be accessed via the Ingen::Shared::World. - - @ingroup engine -*/ -class Engine : public boost::noncopyable, public EngineBase -{ -public: - explicit Engine(Ingen::Shared::World* world); - - virtual ~Engine(); - - virtual bool activate(); - - virtual void deactivate(); - - virtual void quit(); - - virtual bool main_iteration(); - - void set_driver(SharedPtr<Driver> driver); - - void add_event_source(SharedPtr<EventSource> source); - - void process_events(ProcessContext& context); - - Ingen::Shared::World* world() const { return _world; } - - ClientBroadcaster* broadcaster() const { return _broadcaster; } - BufferFactory* buffer_factory() const { return _buffer_factory; } - ControlBindings* control_bindings() const { return _control_bindings; } - Driver* driver() const { return _driver.get(); } - Raul::Maid* maid() const { return _maid; } - MessageContext* message_context() const { return _message_context; } - NodeFactory* node_factory() const { return _node_factory; } - PostProcessor* post_processor() const { return _post_processor; } - - SharedPtr<EngineStore> engine_store() const; - - size_t event_queue_size() const; - -private: - Ingen::Shared::World* _world; - - ClientBroadcaster* _broadcaster; - BufferFactory* _buffer_factory; - ControlBindings* _control_bindings; - SharedPtr<Driver> _driver; - Raul::Maid* _maid; - MessageContext* _message_context; - NodeFactory* _node_factory; - PostProcessor* _post_processor; - - typedef std::set< SharedPtr<EventSource> > EventSources; - EventSources _event_sources; - - bool _quit_flag; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_ENGINE_HPP diff --git a/src/engine/EngineStore.cpp b/src/engine/EngineStore.cpp deleted file mode 100644 index 010edbc0..00000000 --- a/src/engine/EngineStore.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <utility> -#include <vector> -#include "raul/log.hpp" -#include "raul/List.hpp" -#include "raul/PathTable.hpp" -#include "raul/TableImpl.hpp" -#include "EngineStore.hpp" -#include "PatchImpl.hpp" -#include "NodeImpl.hpp" -#include "PortImpl.hpp" -#include "ThreadManager.hpp" - -#define LOG(s) s << "[EngineStore] " - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -/** Find the Patch at the given path. - */ -PatchImpl* -EngineStore::find_patch(const Path& path) -{ - GraphObjectImpl* const object = find_object(path); - return dynamic_cast<PatchImpl*>(object); -} - -/** Find the Node at the given path. - */ -NodeImpl* -EngineStore::find_node(const Path& path) -{ - GraphObjectImpl* const object = find_object(path); - return dynamic_cast<NodeImpl*>(object); -} - -/** Find the Port at the given path. - */ -PortImpl* -EngineStore::find_port(const Path& path) -{ - GraphObjectImpl* const object = find_object(path); - return dynamic_cast<PortImpl*>(object); -} - -/** Find the Object at the given path. - */ -GraphObjectImpl* -EngineStore::find_object(const Path& path) -{ - iterator i = find(path); - return ((i == end()) ? NULL : dynamic_cast<GraphObjectImpl*>(i->second.get())); -} - -/** Add an object to the store. Not realtime safe. - */ -void -EngineStore::add(GraphObject* obj) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - Store::add(obj); -} - -/** Add a family of objects to the store. Not realtime safe. - */ -void -EngineStore::add(const Objects& table) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - cram(table); -} - -/** Remove an object from the store. - * - * Returned is a vector containing all descendants of the object removed - * including the object itself, in lexicographically sorted order by Path. - */ -SharedPtr<EngineStore::Objects> -EngineStore::remove(const Path& path) -{ - return remove(find(path)); -} - -/** Remove an object from the store. - * - * Returned is a vector containing all descendants of the object removed - * including the object itself, in lexicographically sorted order by Path. - */ -SharedPtr<EngineStore::Objects> -EngineStore::remove(iterator object) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - - if (object != end()) { - iterator descendants_end = find_descendants_end(object); - SharedPtr<Objects> removed = yank(object, descendants_end); - - return removed; - - } else { - LOG(warn) << "Removing " << object->first << " failed." << endl; - return SharedPtr<EngineStore>(); - } -} - -/** Remove all children of an object from the store. - * - * Returned is a vector containing all descendants of the object removed - * in lexicographically sorted order by Path. - */ -SharedPtr<EngineStore::Objects> -EngineStore::remove_children(const Path& path) -{ - return remove_children(find(path)); -} - -/** Remove all children of an object from the store. - * - * Returned is a vector containing all descendants of the object removed - * in lexicographically sorted order by Path. - */ -SharedPtr<EngineStore::Objects> -EngineStore::remove_children(iterator object) -{ - if (object != end()) { - iterator descendants_end = find_descendants_end(object); - if (descendants_end != object) { - iterator first_child = object; - ++first_child; - return yank(first_child, descendants_end); - } - } else { - LOG(warn) << "Removing children of " << object->first << " failed." << endl; - return SharedPtr<EngineStore::Objects>(); - } - - return SharedPtr<EngineStore::Objects>(); -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/EngineStore.hpp b/src/engine/EngineStore.hpp deleted file mode 100644 index c6d1e024..00000000 --- a/src/engine/EngineStore.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_OBJECTSTORE_HPP -#define INGEN_ENGINE_OBJECTSTORE_HPP - -#include "raul/SharedPtr.hpp" - -#include "shared/Store.hpp" - -namespace Ingen { - -class GraphObject; - -namespace Engine { - -class PatchImpl; -class NodeImpl; -class PortImpl; -class GraphObjectImpl; - -/** Storage for all GraphObjects (tree of GraphObject's sorted by path). - * - * All looking up in pre_process() methods (and anything else that isn't in-band - * with the audio thread) should use this (to read and modify the GraphObject - * tree). - * - * Searching with find*() is fast (O(log(n)) binary search on contiguous - * memory) and realtime safe, but modification (add or remove) are neither. - */ -class EngineStore : public Ingen::Shared::Store -{ -public: - PatchImpl* find_patch(const Raul::Path& path); - NodeImpl* find_node(const Raul::Path& path); - PortImpl* find_port(const Raul::Path& path); - GraphObjectImpl* find_object(const Raul::Path& path); - - void add(Ingen::GraphObject* o); - void add(const Objects& family); - - SharedPtr<Objects> remove(const Raul::Path& path); - SharedPtr<Objects> remove(Objects::iterator i); - SharedPtr<Objects> remove_children(const Raul::Path& path); - SharedPtr<Objects> remove_children(Objects::iterator i); -}; - -} // namespace Engine -} // namespace Ingen - -#endif // OBJECTSTORE diff --git a/src/engine/Event.cpp b/src/engine/Event.cpp deleted file mode 100644 index 76af56c0..00000000 --- a/src/engine/Event.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "Driver.hpp" -#include "Engine.hpp" -#include "Event.hpp" -#include "ProcessContext.hpp" -#include "ThreadManager.hpp" - -/*! \page methods Method Documentation - * - * <p>All changes in Ingen (both engine and client) occur as a result of - * a small set of methods defined in terms of RDF and matching the - * HTTP and WebDAV standards as closely as possible.</p> - */ - -namespace Ingen { -namespace Engine { - -void -Event::execute(ProcessContext& context) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - assert(!_executed); - assert(_time <= context.end()); - - // Missed the event, jitter, damnit. - if (_time < context.start()) - _time = context.start(); - - _executed = true; -} - -void -Event::post_process() -{ - ThreadManager::assert_not_thread(THREAD_PROCESS); -} - -} // namespace Engine -} // namespace Ingen - diff --git a/src/engine/Event.hpp b/src/engine/Event.hpp deleted file mode 100644 index d6664683..00000000 --- a/src/engine/Event.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_EVENT_HPP -#define INGEN_ENGINE_EVENT_HPP - -#include <cassert> -#include "raul/SharedPtr.hpp" -#include "raul/Deletable.hpp" -#include "raul/Path.hpp" -#include "types.hpp" - -namespace Ingen { -namespace Engine { - -class Engine; -class Request; -class ProcessContext; - -/** Base class for all events (both realtime and QueuedEvent). - * - * This is for time-critical events like note ons. There is no non-realtime - * pre-execute method as in QueuedEvent's, any lookups etc need to be done in the - * realtime execute() method. - * - * QueuedEvent extends this class with a pre_process() method for any work that needs - * to be done before processing in the realtime audio thread. - * - * \ingroup engine - */ -class Event : public Raul::Deletable -{ -public: - virtual ~Event() {} - - /** Execute this event in the audio thread (MUST be realtime safe). */ - virtual void execute(ProcessContext& context); - - /** Perform any actions after execution (ie send replies to commands) - * (no realtime requirements). */ - virtual void post_process(); - - inline SampleCount time() const { return _time; } - - int error() { return _error; } - -protected: - Event(Engine& engine, SharedPtr<Request> request, FrameTime time) - : _engine(engine) - , _request(request) - , _time(time) - , _error(0) // success - , _executed(false) - {} - - Engine& _engine; - SharedPtr<Request> _request; - FrameTime _time; - int _error; - bool _executed; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_EVENT_HPP diff --git a/src/engine/EventBuffer.cpp b/src/engine/EventBuffer.cpp deleted file mode 100644 index 50f938ce..00000000 --- a/src/engine/EventBuffer.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define __STDC_LIMIT_MACROS 1 -#include <stdint.h> -#include "raul/log.hpp" -#include "lv2/lv2plug.in/ns/ext/event/event.h" -#include "lv2/lv2plug.in/ns/ext/event/event-helpers.h" -#include "ingen-config.h" -#include "EventBuffer.hpp" -#include "ProcessContext.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -/** Allocate a new event buffer. - * \a capacity is in bytes (not number of events). - */ -EventBuffer::EventBuffer(BufferFactory& bufs, size_t capacity) - : Buffer(bufs, PortType(PortType::EVENTS), capacity) - , _latest_frames(0) - , _latest_subframes(0) -{ - if (capacity > UINT32_MAX) { - error << "Event buffer size " << capacity << " too large, aborting." << endl; - throw std::bad_alloc(); - } - -#ifdef HAVE_POSIX_MEMALIGN - int ret = posix_memalign((void**)&_data, 16, sizeof(LV2_Event_Buffer) + capacity); -#else - _data = (LV2_Event_Buffer*)malloc(sizeof(LV2_Event_Buffer) + capacity); - int ret = (_data != NULL) ? 0 : -1; -#endif - - if (ret != 0) { - error << "Failed to allocate event buffer. Aborting." << endl; - exit(EXIT_FAILURE); - } - - _data->header_size = sizeof(LV2_Event_Buffer); - _data->data = reinterpret_cast<uint8_t*>(_data + _data->header_size); - _data->stamp_type = 0; - _data->event_count = 0; - _data->capacity = (uint32_t)capacity; - _data->size = 0; - - clear(); -} - -EventBuffer::~EventBuffer() -{ - free(_data); -} - -void -EventBuffer::prepare_read(Context& context) -{ - rewind(); -} - -void -EventBuffer::prepare_write(Context& context) -{ - if (context.offset() == 0) - clear(); -} - -void -EventBuffer::copy(Context& context, const Buffer* src_buf) -{ - const EventBuffer* src = dynamic_cast<const EventBuffer*>(src_buf); - if (src->_data == _data) - return; - - assert(src->_data->header_size == _data->header_size); - assert(capacity() >= _data->header_size + src->_data->size); - - rewind(); - - memcpy(_data, src->_data, _data->header_size + src->_data->size); - - _iter = src->_iter; - _iter.buf = _data; - - _latest_frames = src->_latest_frames; - _latest_subframes = src->_latest_subframes; - - assert(event_count() == src->event_count()); -} - -/** Increment the read position by one event. - * - * \return true if increment was successful, or false if end of buffer reached. - */ -bool -EventBuffer::increment() const -{ - if (lv2_event_is_valid(&_iter)) { - lv2_event_increment(&_iter); - return true; - } else { - return false; - } -} - -/** \return true iff the cursor is valid (ie get_event is safe) - */ -bool -EventBuffer::is_valid() const -{ - return lv2_event_is_valid(&_iter); -} - -/** Read an event from the current position in the buffer - * - * \return true if read was successful, or false if end of buffer reached - */ -bool -EventBuffer::get_event(uint32_t* frames, - uint32_t* subframes, - uint16_t* type, - uint16_t* size, - uint8_t** data) const -{ - if (lv2_event_is_valid(&_iter)) { - LV2_Event* ev = lv2_event_get(&_iter, data); - *frames = ev->frames; - *subframes = ev->subframes; - *type = ev->type; - *size = ev->size; - return true; - } else { - return false; - } -} - -/** Get the object currently pointed to, or NULL if invalid. - */ -LV2_Atom* -EventBuffer::get_atom() const -{ - if (lv2_event_is_valid(&_iter)) { - uint8_t* data; - LV2_Event* ev = lv2_event_get(&_iter, &data); - return LV2_ATOM_FROM_EVENT(ev); - } - return NULL; -} - -/** Get the event currently pointed to, or NULL if invalid. - */ -LV2_Event* -EventBuffer::get_event() const -{ - if (lv2_event_is_valid(&_iter)) { - uint8_t* data; - return lv2_event_get(&_iter, &data); - } - return NULL; -} - -/** Append an event to the buffer. - * - * \a timestamp must be >= the latest event in the buffer. - * - * \return true on success - */ -bool -EventBuffer::append(uint32_t frames, - uint32_t subframes, - uint16_t type, - uint16_t size, - const uint8_t* data) -{ -#ifndef NDEBUG - if (lv2_event_is_valid(&_iter)) { - LV2_Event* last_event = lv2_event_get(&_iter, NULL); - assert(last_event->frames < frames - || (last_event->frames == frames && last_event->subframes <= subframes)); - } -#endif - - /*debug << "Appending event type " << type << ", size " << size - << " @ " << frames << "." << subframes << endl;*/ - - if (!lv2_event_write(&_iter, frames, subframes, type, size, data)) { - error << "Failed to write event." << endl; - return false; - } else { - _latest_frames = frames; - _latest_subframes = subframes; - return true; - } -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/EventBuffer.hpp b/src/engine/EventBuffer.hpp deleted file mode 100644 index 16f5afbe..00000000 --- a/src/engine/EventBuffer.hpp +++ /dev/null @@ -1,86 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_EVENTBUFFER_HPP -#define INGEN_ENGINE_EVENTBUFFER_HPP - -#include "lv2/lv2plug.in/ns/ext/atom/atom.h" -#include "lv2/lv2plug.in/ns/ext/event/event.h" -#include "lv2/lv2plug.in/ns/ext/event/event-helpers.h" -#include "ingen/PortType.hpp" -#include "Buffer.hpp" - -namespace Ingen { -namespace Engine { - -class EventBuffer : public Buffer { -public: - EventBuffer(BufferFactory& bufs, size_t capacity); - ~EventBuffer(); - - void* port_data(PortType port_type, SampleCount offset=0) { return _data; } - const void* port_data(PortType port_type, SampleCount offset=0) const { return _data; } - - inline void rewind() const { lv2_event_begin(&_iter, _data); } - - inline void clear() { - _latest_frames = 0; - _latest_subframes = 0; - _data->event_count = 0; - _data->size = 0; - rewind(); - } - - void prepare_read(Context& context); - void prepare_write(Context& context); - - void copy(Context& context, const Buffer* src); - - inline size_t event_count() const { return _data->event_count; } - inline uint32_t capacity() const { return _data->capacity; } - inline uint32_t latest_frames() const { return _latest_frames; } - inline uint32_t latest_subframes() const { return _latest_subframes; } - - bool increment() const; - bool is_valid() const; - - bool get_event(uint32_t* frames, - uint32_t* subframes, - uint16_t* type, - uint16_t* size, - uint8_t** data) const; - - LV2_Atom* get_atom() const; - LV2_Event* get_event() const; - - bool append(uint32_t frames, - uint32_t subframes, - uint16_t type, - uint16_t size, - const uint8_t* data); - -private: - LV2_Event_Buffer* _data; ///< Contents - mutable LV2_Event_Iterator _iter; ///< Iterator into _data - uint32_t _latest_frames; ///< Latest time of all events (frames) - uint32_t _latest_subframes; ///< Latest time of all events (subframes) -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_EVENTBUFFER_HPP diff --git a/src/engine/EventSink.cpp b/src/engine/EventSink.cpp deleted file mode 100644 index bf31beaa..00000000 --- a/src/engine/EventSink.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "EventSink.hpp" -#include "PortImpl.hpp" - -using namespace std; - -namespace Ingen { -namespace Engine { - -/** \a size is not size_t because an event will never be even remotely close - * to UINT32_MAX in size, so uint32_t saves wasted space on 64-bit. - */ -bool -EventSink::write(uint32_t size, const Event* ev) -{ - if (size > _events.write_space()) - return false; - - _events.write(sizeof(uint32_t), (uint8_t*)&size); - _events.write(size, (uint8_t*)ev); - - return true; -} - -/** Read the next event into event_buffer. - * - * \a event_buffer can be casted to Event* and virtual methods called. - */ -bool -EventSink::read(uint32_t event_buffer_size, uint8_t* event_buffer) -{ - uint32_t read_size; - bool success = _events.full_read(sizeof(uint32_t), (uint8_t*)&read_size); - if (!success) - return false; - - assert(read_size <= event_buffer_size); - - if (read_size > 0) - return _events.full_read(read_size, event_buffer); - else - return false; -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/EventSink.hpp b/src/engine/EventSink.hpp deleted file mode 100644 index 50edea77..00000000 --- a/src/engine/EventSink.hpp +++ /dev/null @@ -1,59 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_EVENTSINK_HPP -#define INGEN_ENGINE_EVENTSINK_HPP - -#include <stdint.h> -#include <list> -#include <utility> -#include "raul/RingBuffer.hpp" - -namespace Ingen { -namespace Engine { - -class PortImpl; -class Engine; -class Event; - -/** Sink for events generated in the audio thread. - * - * Implemented as a flat ringbuffer of events, which are constructed directly - * in the ringbuffer rather than allocated on the heap (in order to make - * writing realtime safe). - * - * \ingroup engine - */ -class EventSink -{ -public: - EventSink(Engine& engine, size_t capacity) : _engine(engine), _events(capacity) {} - - bool write(uint32_t size, const Event* ev); - - bool read(uint32_t event_buffer_size, uint8_t* event_buffer); - -private: - Engine& _engine; - Raul::RingBuffer _events; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_EVENTSINK_HPP - diff --git a/src/engine/EventSource.cpp b/src/engine/EventSource.cpp deleted file mode 100644 index 33ab94ab..00000000 --- a/src/engine/EventSource.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2008-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <sys/mman.h> -#include "EventSource.hpp" -#include "QueuedEvent.hpp" -#include "PostProcessor.hpp" -#include "ThreadManager.hpp" -#include "ProcessContext.hpp" - -using namespace std; - -namespace Ingen { -namespace Engine { - -EventSource::EventSource(size_t queue_size) - : _blocking_semaphore(0) -{ - Thread::set_context(THREAD_PRE_PROCESS); - set_name("EventSource"); -} - -EventSource::~EventSource() -{ - Thread::stop(); -} - -/** Push an unprepared event onto the queue. - */ -void -EventSource::push_queued(QueuedEvent* const ev) -{ - assert(!ev->is_prepared()); - Raul::List<Event*>::Node* node = new Raul::List<Event*>::Node(ev); - _events.push_back(node); - if (_prepared_back.get() == NULL) - _prepared_back = node; - - whip(); -} - -/** Process all events for a cycle. - * - * Executed events will be pushed to @a dest. - */ -void -EventSource::process(PostProcessor& dest, ProcessContext& context, bool limit) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - - if (_events.empty()) - return; - - /* Limit the maximum number of queued events to process per cycle. This - * makes the process callback (more) realtime-safe by preventing being - * choked by events coming in faster than they can be processed. - * FIXME: test this and figure out a good value */ - const size_t MAX_QUEUED_EVENTS = context.nframes() / 32; - - size_t num_events_processed = 0; - - Raul::List<Event*>::Node* head = _events.head(); - Raul::List<Event*>::Node* tail = head; - - if (!head) - return; - - QueuedEvent* ev = (QueuedEvent*)head->elem(); - - while (ev && ev->is_prepared() && ev->time() < context.end()) { - ev->execute(context); - tail = head; - head = head->next(); - ++num_events_processed; - if (limit && num_events_processed > MAX_QUEUED_EVENTS) - break; - ev = (head ? (QueuedEvent*)head->elem() : NULL); - } - - if (num_events_processed > 0) { - Raul::List<Event*> front; - _events.chop_front(front, num_events_processed, tail); - dest.append(&front); - } -} - -/** Pre-process a single event */ -void -EventSource::_whipped() -{ - Raul::List<Event*>::Node* pb = _prepared_back.get(); - if (!pb) - return; - - QueuedEvent* const ev = (QueuedEvent*)pb->elem(); - assert(ev); - - assert(!ev->is_prepared()); - ev->pre_process(); - assert(ev->is_prepared()); - - assert(_prepared_back.get() == pb); - _prepared_back = pb->next(); - - // If event was blocking, wait for event to being run through the - // process thread before preparing the next event - if (ev->is_blocking()) - _blocking_semaphore.wait(); -} - -} // namespace Engine -} // namespace Ingen - diff --git a/src/engine/EventSource.hpp b/src/engine/EventSource.hpp deleted file mode 100644 index 52bb08f6..00000000 --- a/src/engine/EventSource.hpp +++ /dev/null @@ -1,73 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_EVENTSOURCE_HPP -#define INGEN_ENGINE_EVENTSOURCE_HPP - -#include "raul/Semaphore.hpp" -#include "raul/Slave.hpp" -#include "raul/List.hpp" - -namespace Ingen { -namespace Engine { - -class Event; -class QueuedEvent; -class PostProcessor; -class ProcessContext; - -/** Source for events to run in the audio thread. - * - * The Driver gets events from an EventSource in the process callback - * (realtime audio thread) and executes them, then they are sent to the - * PostProcessor and finalised (post-processing thread). - */ -class EventSource : protected Raul::Slave -{ -public: - explicit EventSource(size_t queue_size); - virtual ~EventSource(); - - void process(PostProcessor& dest, ProcessContext& context, bool limit=true); - - bool empty() { return _events.empty(); } - - /** Signal that a blocking event is finished. - * - * This MUST be called by blocking events in their post_process() method - * to resume pre-processing of events. - */ - inline void unblock() { _blocking_semaphore.post(); } - -protected: - void push_queued(QueuedEvent* const ev); - - inline bool unprepared_events() { return (_prepared_back.get() != NULL); } - - virtual void _whipped(); ///< Prepare 1 event - -private: - Raul::List<Event*> _events; - Raul::AtomicPtr<Raul::List<Event*>::Node> _prepared_back; - Raul::Semaphore _blocking_semaphore; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_EVENTSOURCE_HPP - diff --git a/src/engine/GraphObjectImpl.cpp b/src/engine/GraphObjectImpl.cpp deleted file mode 100644 index 6b8e8a08..00000000 --- a/src/engine/GraphObjectImpl.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <string> - -#include "GraphObjectImpl.hpp" -#include "PatchImpl.hpp" -#include "EngineStore.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -GraphObjectImpl::GraphObjectImpl(Ingen::Shared::LV2URIMap& uris, - GraphObjectImpl* parent, - const Symbol& symbol) - : ResourceImpl(uris, parent ? parent->path().child(symbol) : Raul::Path::root()) - , _parent(parent) - , _path(parent ? parent->path().child(symbol) : "/") - , _symbol(symbol) -{ -} - -void -GraphObjectImpl::add_meta_property(const Raul::URI& key, const Atom& value) -{ - add_property(key, Resource::Property(value, Resource::INTERNAL)); -} - -void -GraphObjectImpl::set_meta_property(const Raul::URI& key, const Atom& value) -{ - set_property(key, Resource::Property(value, Resource::INTERNAL)); -} - -const Atom& -GraphObjectImpl::get_property(const Raul::URI& key) const -{ - static const Atom null_atom; - Resource::Properties::const_iterator i = properties().find(key); - return (i != properties().end()) ? i->second : null_atom; -} - -PatchImpl* -GraphObjectImpl::parent_patch() const -{ - return dynamic_cast<PatchImpl*>((NodeImpl*)_parent); -} - -SharedPtr<GraphObject> -GraphObjectImpl::find_child(const std::string& name) const -{ - throw; -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/GraphObjectImpl.hpp b/src/engine/GraphObjectImpl.hpp deleted file mode 100644 index 88e18ff4..00000000 --- a/src/engine/GraphObjectImpl.hpp +++ /dev/null @@ -1,113 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_GRAPHOBJECTIMPL_HPP -#define INGEN_ENGINE_GRAPHOBJECTIMPL_HPP - -#include <string> -#include <map> -#include <cstddef> -#include <cassert> -#include "raul/Deletable.hpp" -#include "raul/Path.hpp" -#include "raul/SharedPtr.hpp" -#include "ingen/GraphObject.hpp" -#include "shared/ResourceImpl.hpp" - -namespace Raul { class Maid; } - -namespace Ingen { - -namespace Shared { class LV2URIMap; } - -namespace Engine { - -class PatchImpl; -class Context; -class ProcessContext; -class BufferFactory; - -/** An object on the audio graph - Patch, Node, Port, etc. - * - * 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 - * arbitrary values in (which the engine puts no significance to whatsoever). - * - * \ingroup engine - */ -class GraphObjectImpl : virtual public GraphObject - , public Ingen::Shared::ResourceImpl -{ -public: - virtual ~GraphObjectImpl() {} - - const Raul::URI& uri() const { return _path; } - const Raul::Symbol& symbol() const { return _symbol; } - - GraphObject* graph_parent() const { return _parent; } - GraphObjectImpl* parent() const { return _parent; } - - //virtual void process(ProcessContext& context) = 0; - - /** Rename */ - virtual void set_path(const Raul::Path& new_path) { - _path = new_path; - _symbol = new_path.symbol(); - } - - const Raul::Atom& get_property(const Raul::URI& key) const; - void add_meta_property(const Raul::URI& key, const Raul::Atom& value); - void set_meta_property(const Raul::URI& key, const Raul::Atom& value); - - /** The Patch this object is a child of. */ - virtual PatchImpl* parent_patch() const; - - /** Raul::Path is dynamically generated from parent to ease renaming */ - const Raul::Path& path() const { return _path; } - - SharedPtr<GraphObject> find_child(const std::string& name) const; - - /** Prepare for a new (external) polyphony value. - * - * Preprocessor thread, poly is actually applied by apply_poly. - * \return true on success. - */ - virtual bool prepare_poly(BufferFactory& bufs, uint32_t poly) = 0; - - /** Apply a new (external) polyphony value. - * - * Audio thread. - * - * \param poly Must be <= the most recent value passed to prepare_poly. - * \param maid Any objects no longer needed will be pushed to this - */ - virtual bool apply_poly(Raul::Maid& maid, uint32_t poly) = 0; - -protected: - GraphObjectImpl(Ingen::Shared::LV2URIMap& uris, - GraphObjectImpl* parent, - const Raul::Symbol& symbol); - - GraphObjectImpl* _parent; - Raul::Path _path; - Raul::Symbol _symbol; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_GRAPHOBJECTIMPL_HPP diff --git a/src/engine/HTTPClientSender.cpp b/src/engine/HTTPClientSender.cpp deleted file mode 100644 index 21dc11a3..00000000 --- a/src/engine/HTTPClientSender.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2008-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <string> -#include <libsoup/soup.h> -#include "raul/log.hpp" -#include "raul/Atom.hpp" -#include "raul/AtomRDF.hpp" -#include "serialisation/Serialiser.hpp" -#include "shared/World.hpp" -#include "HTTPClientSender.hpp" -#include "Engine.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -void -HTTPClientSender::response_ok(int32_t id) -{ -} - -void -HTTPClientSender::response_error(int32_t id, const std::string& msg) -{ - warn << "HTTP Error " << id << " (" << msg << ")" << endl; -} - -void -HTTPClientSender::error(const std::string& msg) -{ - warn << "HTTP send error " << msg << endl; -} - -void -HTTPClientSender::put(const URI& uri, - const Resource::Properties& properties, - Resource::Graph ctx) -{ - const std::string request_uri = (Raul::Path::is_path(uri)) - ? _url + "/patch" + uri.substr(uri.find("/")) - : uri.str(); - - - Sord::Model model(*_engine.world()->rdf_world()); - for (Resource::Properties::const_iterator i = properties.begin(); - i != properties.end(); ++i) - model.add_statement( - Sord::URI(*_engine.world()->rdf_world(), request_uri), - AtomRDF::atom_to_node(model, i->first.str()), - AtomRDF::atom_to_node(model, i->second)); - - const string str = model.write_to_string("turtle"); - send_chunk(str); -} - -void -HTTPClientSender::delta(const URI& uri, - const Resource::Properties& remove, - const Resource::Properties& add) -{ -} - -void -HTTPClientSender::del(const URI& uri) -{ - send_chunk(string("<").append(uri.str()).append("> a <http://www.w3.org/2002/07/owl#Nothing> .")); -} - -void -HTTPClientSender::connect(const Path& src_path, const Path& dst_path) -{ - const string msg = string( - "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n" - "@prefix ingen: <http://drobilla.net/ns/ingen#> .\n").append( - "<> ingen:connection [\n" - "\tingen:destination <").append(dst_path.str()).append("> ;\n" - "\tingen:source <").append(src_path.str()).append(">\n] .\n"); - send_chunk(msg); -} - -void -HTTPClientSender::disconnect(const URI& src, - const URI& dst) -{ -} - -void -HTTPClientSender::disconnect_all(const Raul::Path& parent_patch_path, - const Raul::Path& path) -{ -} - -void -HTTPClientSender::set_property(const URI& subject, const URI& key, const Atom& value) -{ -#if 0 - Sord::Node node = AtomRDF::atom_to_node(*_engine.world()->rdf_world(), value); - const string msg = string( - "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n" - "@prefix ingen: <http://drobilla.net/ns/ingen#> .\n" - "@prefix ingenui: <http://drobilla.net/ns/ingenuity#> .\n").append( - subject.str()).append("> ingen:property [\n" - "rdf:predicate ").append(key.str()).append(" ;\n" - "rdf:value ").append(node.to_string()).append("\n] .\n"); - send_chunk(msg); -#endif -} - -void -HTTPClientSender::activity(const Path& path) -{ - const string msg = string( - "@prefix ingen: <http://drobilla.net/ns/ingen#> .\n\n<").append( - path.str()).append("> ingen:activity true .\n"); - send_chunk(msg); -} - -void -HTTPClientSender::move(const Path& old_path, const Path& new_path) -{ - string msg = string( - "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n" - "@prefix ingen: <http://drobilla.net/ns/ingen#> .\n\n<").append( - old_path.str()).append("> rdf:subject <").append(new_path.str()).append("> .\n"); - send_chunk(msg); -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/HTTPClientSender.hpp b/src/engine/HTTPClientSender.hpp deleted file mode 100644 index 5b3cdc73..00000000 --- a/src/engine/HTTPClientSender.hpp +++ /dev/null @@ -1,107 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2008-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_HTTPCLIENTSENDER_HPP -#define INGEN_ENGINE_HTTPCLIENTSENDER_HPP - -#include <cassert> -#include <string> -#include <pthread.h> -#include "raul/Thread.hpp" -#include "ingen/ClientInterface.hpp" -#include "shared/HTTPSender.hpp" - -namespace Ingen { - -class EngineInterface; - -namespace Engine { - -class Engine; - -/** Implements ClientInterface for HTTP clients. - * Sends changes as RDF deltas over an HTTP stream - * (a single message with chunked encoding response). - * - * \ingroup engine - */ -class HTTPClientSender - : public ClientInterface - , public Ingen::Shared::HTTPSender -{ -public: - explicit HTTPClientSender(Engine& engine) - : _engine(engine) - , _enabled(true) - {} - - bool enabled() const { return _enabled; } - - void enable() { _enabled = true; } - void disable() { _enabled = false; } - - void bundle_begin() { HTTPSender::bundle_begin(); } - void bundle_end() { HTTPSender::bundle_end(); } - - Raul::URI uri() const { return "http://example.org/"; } - - /* *** ClientInterface Implementation Below *** */ - - void response_ok(int32_t id); - void response_error(int32_t id, const std::string& msg); - - void error(const std::string& msg); - - virtual void put(const Raul::URI& path, - const Resource::Properties& properties, - Resource::Graph ctx); - - virtual void delta(const Raul::URI& path, - const Resource::Properties& remove, - const Resource::Properties& add); - - virtual void del(const Raul::URI& uri); - - virtual void move(const Raul::Path& old_path, - const Raul::Path& new_path); - - virtual void connect(const Raul::Path& src_port_path, - const Raul::Path& dst_port_path); - - virtual void disconnect(const Raul::URI& src, - const Raul::URI& dst); - - virtual void disconnect_all(const Raul::Path& parent_patch_path, - const Raul::Path& path); - - virtual void set_property(const Raul::URI& subject_path, - const Raul::URI& predicate, - const Raul::Atom& value); - - virtual void activity(const Raul::Path& path); - -private: - Engine& _engine; - std::string _url; - bool _enabled; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_HTTPCLIENTSENDER_HPP - diff --git a/src/engine/HTTPEngineReceiver.cpp b/src/engine/HTTPEngineReceiver.cpp deleted file mode 100644 index 910be584..00000000 --- a/src/engine/HTTPEngineReceiver.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <cstdio> -#include <cstdlib> -#include <string> - -#include <boost/format.hpp> - -#include <libsoup/soup.h> - -#include "raul/SharedPtr.hpp" -#include "raul/log.hpp" - -#include "ingen/ClientInterface.hpp" -#include "shared/Module.hpp" -#include "serialisation/Parser.hpp" -#include "serialisation/Serialiser.hpp" - -#include "ClientBroadcaster.hpp" -#include "Engine.hpp" -#include "EngineStore.hpp" -#include "EventSource.hpp" -#include "HTTPClientSender.hpp" -#include "HTTPEngineReceiver.hpp" -#include "ThreadManager.hpp" - -#define LOG(s) s << "[HTTPEngineReceiver] " - -using namespace std; -using namespace Raul; - -namespace Ingen { - -using namespace Serialisation; - -namespace Engine { - -HTTPEngineReceiver::HTTPEngineReceiver(Engine& engine, uint16_t port) - : QueuedEngineInterface(engine, 64) // FIXME - , _server(soup_server_new(SOUP_SERVER_PORT, port, NULL)) -{ - _receive_thread = new ReceiveThread(*this); - - soup_server_add_handler(_server, NULL, message_callback, this, NULL); - - LOG(info) << "Started HTTP server on port " << soup_server_get_port(_server) << endl; - - if (!engine.world()->parser() || !engine.world()->serialiser()) - engine.world()->load_module("serialisation"); - - Thread::set_name("HTTPEngineReceiver"); - start(); - _receive_thread->set_name("HTTPEngineReceiver Listener"); - _receive_thread->start(); -} - -HTTPEngineReceiver::~HTTPEngineReceiver() -{ - _receive_thread->stop(); - stop(); - delete _receive_thread; - - if (_server) { - soup_server_quit(_server); - _server = NULL; - } -} - -void -HTTPEngineReceiver::message_callback(SoupServer* server, - SoupMessage* msg, - const char* path_str, - GHashTable* query, - SoupClientContext* client, - void* data) -{ - HTTPEngineReceiver* me = (HTTPEngineReceiver*)data; - - using namespace Ingen::Shared; - - SharedPtr<Store> store = me->_engine.world()->store(); - if (!store) { - soup_message_set_status(msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); - return; - } - - string path = path_str; - if (path[path.length() - 1] == '/') { - path = path.substr(0, path.length()-1); - } - - SharedPtr<Serialiser> serialiser = me->_engine.world()->serialiser(); - - const string base_uri = "path:/"; - const char* mime_type = "text/plain"; - - // Special GET paths - if (msg->method == SOUP_METHOD_GET) { - if (path == Path::root().str() || path.empty()) { - const string r = string("@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n") - .append("\n<> rdfs:seeAlso <plugins> ;") - .append("\n rdfs:seeAlso <stream> ;") - .append("\n rdfs:seeAlso <patch> ."); - soup_message_set_status(msg, SOUP_STATUS_OK); - soup_message_set_response(msg, mime_type, SOUP_MEMORY_COPY, r.c_str(), r.length()); - return; - - } else if (msg->method == SOUP_METHOD_GET && path.substr(0, 8) == "/plugins") { - // FIXME: kludge - #if 0 - me->get("ingen:plugins"); - me->_receive_thread->whip(); - - serialiser->start_to_string("/", base_uri); - for (NodeFactory::Plugins::const_iterator p = me->_engine.node_factory()->plugins().begin(); - p != me->_engine.node_factory()->plugins().end(); ++p) - serialiser->serialise_plugin(*(Shared::Plugin*)p->second); - const string r = serialiser->finish(); - soup_message_set_status(msg, SOUP_STATUS_OK); - soup_message_set_response(msg, mime_type, SOUP_MEMORY_COPY, r.c_str(), r.length()); - #endif - return; - - } else if (path.substr(0, 6) == "/patch") { - path = '/' + path.substr(6); - if (path.substr(0, 2) == "//") - path = path.substr(1); - - } else if (path.substr(0, 7) == "/stream") { - HTTPClientSender* client = new HTTPClientSender(me->_engine); - me->register_client(client); - - // Respond with port number of stream for client - const int port = client->listen_port(); - char buf[32]; - snprintf(buf, sizeof(buf), "%d", port); - soup_message_set_status(msg, SOUP_STATUS_OK); - soup_message_set_response(msg, mime_type, SOUP_MEMORY_COPY, buf, strlen(buf)); - return; - } - } - - if (!Path::is_valid(path)) { - LOG(error) << "Bad HTTP path: " << path << endl; - soup_message_set_status(msg, SOUP_STATUS_BAD_REQUEST); - const string& err = (boost::format("Bad path: %1%") % path).str(); - soup_message_set_response(msg, "text/plain", SOUP_MEMORY_COPY, - err.c_str(), err.length()); - return; - } - - if (msg->method == SOUP_METHOD_GET) { - Glib::RWLock::ReaderLock lock(store->lock()); - - // Find object - Store::const_iterator start = store->find(path); - if (start == store->end()) { - soup_message_set_status(msg, SOUP_STATUS_NOT_FOUND); - const string& err = (boost::format("No such object: %1%") % path).str(); - soup_message_set_response(msg, "text/plain", SOUP_MEMORY_COPY, - err.c_str(), err.length()); - return; - } - - // Get serialiser - SharedPtr<Serialiser> serialiser = me->_engine.world()->serialiser(); - if (!serialiser) { - soup_message_set_status(msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); - soup_message_set_response(msg, "text/plain", SOUP_MEMORY_STATIC, - "No serialiser available\n", 24); - return; - } - - // Serialise object - const string response = serialiser->to_string(start->second, - "http://localhost:16180/patch", GraphObject::Properties()); - - soup_message_set_status(msg, SOUP_STATUS_OK); - soup_message_set_response(msg, mime_type, SOUP_MEMORY_COPY, - response.c_str(), response.length()); - - } else if (msg->method == SOUP_METHOD_PUT) { - Glib::RWLock::WriterLock lock(store->lock()); - - // Get parser - SharedPtr<Parser> parser = me->_engine.world()->parser(); - if (!parser) { - soup_message_set_status(msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); - return; - } - - parser->parse_string(me->_engine.world(), me, msg->request_body->data, base_uri); - soup_message_set_status(msg, SOUP_STATUS_OK); - - } else if (msg->method == SOUP_METHOD_DELETE) { - me->del(path); - soup_message_set_status(msg, SOUP_STATUS_OK); - - } else { - soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED); - } -} - -/** Override the semaphore driven _run method of QueuedEngineInterface - * to wait on HTTP requests and process them immediately in this thread. - */ -void -HTTPEngineReceiver::ReceiveThread::_run() -{ - soup_server_run(_receiver._server); -} - -} // namespace Engine -} // namespace Ingen - diff --git a/src/engine/HTTPEngineReceiver.hpp b/src/engine/HTTPEngineReceiver.hpp deleted file mode 100644 index 0241270a..00000000 --- a/src/engine/HTTPEngineReceiver.hpp +++ /dev/null @@ -1,64 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2008-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_HTTPENGINERECEIVER_HPP -#define INGEN_ENGINE_HTTPENGINERECEIVER_HPP - -#include <stdint.h> - -#include <string> - -#include "QueuedEngineInterface.hpp" - -typedef struct _SoupServer SoupServer; -typedef struct _SoupMessage SoupMessage; -typedef struct SoupClientContext SoupClientContext; - -namespace Ingen { -namespace Engine { - -class HTTPEngineReceiver : public QueuedEngineInterface -{ -public: - HTTPEngineReceiver(Engine& engine, uint16_t port); - ~HTTPEngineReceiver(); - -private: - struct ReceiveThread : public Raul::Thread { - explicit ReceiveThread(HTTPEngineReceiver& receiver) : _receiver(receiver) {} - virtual void _run(); - virtual void whip() { - while (_receiver.unprepared_events()) - _receiver.whip(); - } - private: - HTTPEngineReceiver& _receiver; - }; - - friend class ReceiveThread; - - static void message_callback(SoupServer* server, SoupMessage* msg, const char* path, - GHashTable *query, SoupClientContext* client, void* data); - - ReceiveThread* _receive_thread; - SoupServer* _server; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_HTTPENGINERECEIVER_HPP diff --git a/src/engine/InputPort.cpp b/src/engine/InputPort.cpp deleted file mode 100644 index 80058632..00000000 --- a/src/engine/InputPort.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "InputPort.hpp" -#include <cstdlib> -#include <cassert> -#include "ingen/Patch.hpp" -#include "shared/LV2URIMap.hpp" -#include "AudioBuffer.hpp" -#include "BufferFactory.hpp" -#include "ConnectionImpl.hpp" -#include "EventBuffer.hpp" -#include "NodeImpl.hpp" -#include "OutputPort.hpp" -#include "ProcessContext.hpp" -#include "ThreadManager.hpp" -#include "mix.hpp" -#include "util.hpp" - -using namespace std; - -namespace Ingen { -namespace Engine { - -InputPort::InputPort(BufferFactory& bufs, - NodeImpl* parent, - const Raul::Symbol& symbol, - uint32_t index, - uint32_t poly, - PortType type, - const Raul::Atom& value, - size_t buffer_size) - : PortImpl(bufs, parent, symbol, index, poly, type, value, buffer_size) - , _num_connections(0) -{ - const Ingen::Shared::LV2URIMap& uris = bufs.uris(); - - if (!dynamic_cast<Patch*>(parent)) - add_property(uris.rdf_type, uris.lv2_InputPort); - - // Set default control range - if (type == PortType::CONTROL) { - set_property(uris.lv2_minimum, 0.0f); - set_property(uris.lv2_maximum, 1.0f); - } -} - -bool -InputPort::apply_poly(Maid& maid, uint32_t poly) -{ - bool ret = PortImpl::apply_poly(maid, poly); - if (!ret) - poly = 1; - - assert(_buffers->size() >= poly); - - return true; -} - -/** Set \a buffers appropriately if this port has \a num_connections connections. - * \return true iff buffers are locally owned by the port - */ -bool -InputPort::get_buffers(BufferFactory& bufs, - Raul::Array<BufferFactory::Ref>* buffers, - uint32_t poly) -{ - size_t num_connections = (ThreadManager::thread_is(THREAD_PROCESS)) - ? _connections.size() : _num_connections; - - if (buffer_type() == PortType::AUDIO && num_connections == 0) { - // Audio input with no connections, use shared zero buffer - for (uint32_t v = 0; v < poly; ++v) - buffers->at(v) = bufs.silent_buffer(); - return false; - - } else if (num_connections == 1) { - if (ThreadManager::thread_is(THREAD_PROCESS)) { - if (!_connections.front()->must_mix() && !_connections.front()->must_queue()) { - // Single non-mixing conneciton, use buffers directly - for (uint32_t v = 0; v < poly; ++v) - buffers->at(v) = _connections.front()->buffer(v); - return false; - } - } - } - - // Otherwise, allocate local buffers - for (uint32_t v = 0; v < poly; ++v) { - buffers->at(v) = _bufs.get(buffer_type(), _buffer_size); - buffers->at(v)->clear(); - } - return true; -} - -/** Add a connection. Realtime safe. - * - * The buffer of this port will be set directly to the connection's buffer - * if there is only one connection, since no copying/mixing needs to take place. - * - * Note that setup_buffers must be called after this before the change - * will audibly take effect. - */ -void -InputPort::add_connection(Connections::Node* const c) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - - _connections.push_back(c); - - // Automatically broadcast connected control inputs - if (is_a(PortType::CONTROL)) - _broadcast = true; -} - -/** Remove a connection. Realtime safe. - * - * Note that setup_buffers must be called after this before the change - * will audibly take effect. - */ -InputPort::Connections::Node* -InputPort::remove_connection(ProcessContext& context, const OutputPort* src_port) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - - Connections::Node* connection = NULL; - for (Connections::iterator i = _connections.begin(); i != _connections.end();) { - Connections::iterator next = i; - ++next; - - if ((*i)->src_port() == src_port) { - connection = _connections.erase(i); - break; - } - - i = next; - } - - if ( ! connection) { - error << "[InputPort::remove_connection] Connection not found!" << endl; - return NULL; - } - - // Turn off broadcasting if we're no longer connected - if (is_a(PortType::CONTROL) && _connections.size() == 0) - _broadcast = false; - - return connection; -} - -/** Prepare buffer for access, mixing if necessary. Realtime safe. - */ -void -InputPort::pre_process(Context& context) -{ - // If value has been set (e.g. events pushed) by the user, don't smash it - if (_set_by_user) - return; - - uint32_t max_num_srcs = 0; - for (Connections::iterator c = _connections.begin(); c != _connections.end(); ++c) - max_num_srcs += (*c)->src_port()->poly(); - - IntrusivePtr<Buffer> srcs[max_num_srcs]; - - if (_connections.empty()) { - for (uint32_t v = 0; v < _poly; ++v) { - buffer(v)->prepare_read(context); - } - } else if (direct_connect()) { - for (uint32_t v = 0; v < _poly; ++v) { - _buffers->at(v) = _connections.front()->buffer(v); - _buffers->at(v)->prepare_read(context); - } - } else { - for (uint32_t v = 0; v < _poly; ++v) { - uint32_t num_srcs = 0; - for (Connections::iterator c = _connections.begin(); c != _connections.end(); ++c) - (*c)->get_sources(context, v, srcs, max_num_srcs, num_srcs); - - mix(context, buffer(v).get(), srcs, num_srcs); - buffer(v)->prepare_read(context); - } - } - - if (_broadcast) - broadcast_value(context, false); -} - -void -InputPort::post_process(Context& context) -{ - if (_set_by_user) { - if (buffer_type() == PortType::EVENTS) { - // Clear events received via a SetPortValue - for (uint32_t v = 0; v < _poly; ++v) { - buffer(v)->clear(); - } - } - _set_by_user = false; - } -} - -bool -InputPort::direct_connect() const -{ - return (context() == Context::AUDIO) - && _connections.size() == 1 - && !_connections.front()->must_mix() - && !_connections.front()->must_queue(); -} - -} // namespace Engine -} // namespace Ingen - diff --git a/src/engine/InputPort.hpp b/src/engine/InputPort.hpp deleted file mode 100644 index 04fd2653..00000000 --- a/src/engine/InputPort.hpp +++ /dev/null @@ -1,93 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_INPUTPORT_HPP -#define INGEN_ENGINE_INPUTPORT_HPP - -#include <string> -#include <cstdlib> -#include <cassert> -#include "raul/List.hpp" -#include "raul/SharedPtr.hpp" -#include "PortImpl.hpp" - -namespace Ingen { -namespace Engine { - -class ConnectionImpl; -class Context; -class NodeImpl; -class OutputPort; -class ProcessContext; - -/** An input port on a Node or Patch. - * - * All ports have a Buffer, but the actual contents (data) of that buffer may be - * set directly to the incoming connection's buffer if there's only one inbound - * connection, to eliminate the need to copy/mix. - * - * If a port has multiple connections, they will be mixed down into the local - * buffer and it will be used. - * - * \ingroup engine - */ -class InputPort : virtual public PortImpl -{ -public: - InputPort(BufferFactory& bufs, - NodeImpl* parent, - const Raul::Symbol& symbol, - uint32_t index, - uint32_t poly, - PortType type, - const Raul::Atom& value, - size_t buffer_size=0); - - virtual ~InputPort() {} - - typedef Raul::List< SharedPtr<ConnectionImpl> > Connections; - - void add_connection(Connections::Node* c); - Connections::Node* remove_connection(ProcessContext& context, const OutputPort* src_port); - - bool apply_poly(Raul::Maid& maid, uint32_t poly); - - bool get_buffers(BufferFactory& bufs, - Raul::Array<BufferFactory::Ref>* buffers, - uint32_t poly); - - void pre_process(Context& context); - void post_process(Context& context); - - size_t num_connections() const { return _num_connections; } ///< Pre-process thread - void increment_num_connections() { ++_num_connections; } - void decrement_num_connections() { --_num_connections; } - - bool is_input() const { return true; } - bool is_output() const { return false; } - - bool direct_connect() const; - -protected: - size_t _num_connections; ///< Pre-process thread - Connections _connections; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_INPUTPORT_HPP diff --git a/src/engine/InternalPlugin.cpp b/src/engine/InternalPlugin.cpp deleted file mode 100644 index f8022e71..00000000 --- a/src/engine/InternalPlugin.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <cassert> -#include <string> -#include "shared/LV2URIMap.hpp" -#include "internals/Controller.hpp" -#include "internals/Delay.hpp" -#include "internals/Note.hpp" -#include "internals/Trigger.hpp" -#include "Driver.hpp" -#include "Engine.hpp" -#include "InternalPlugin.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -using namespace Internals; - -InternalPlugin::InternalPlugin(Shared::LV2URIMap& uris, - const std::string& uri, const std::string& symbol) - : PluginImpl(uris, Plugin::Internal, uri) - , _symbol(symbol) -{ - set_property(uris.rdf_type, uris.ingen_Internal); -} - -NodeImpl* -InternalPlugin::instantiate(BufferFactory& bufs, - const string& name, - bool polyphonic, - PatchImpl* parent, - Engine& engine) -{ - assert(_type == Internal); - - const SampleCount srate = engine.driver()->sample_rate(); - - const string uri_str = uri().str(); - - if (uri_str == NS_INTERNALS "Controller") { - return new ControllerNode(this, bufs, name, polyphonic, parent, srate); - } else if (uri_str == NS_INTERNALS "Delay") { - return new DelayNode(this, bufs, name, polyphonic, parent, srate); - } else if (uri_str == NS_INTERNALS "Note") { - return new NoteNode(this, bufs, name, polyphonic, parent, srate); - } else if (uri_str == NS_INTERNALS "Trigger") { - return new TriggerNode(this, bufs, name, polyphonic, parent, srate); - } else { - return NULL; - } -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/InternalPlugin.hpp b/src/engine/InternalPlugin.hpp deleted file mode 100644 index 6301b999..00000000 --- a/src/engine/InternalPlugin.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_INTERNALPLUGIN_HPP -#define INGEN_ENGINE_INTERNALPLUGIN_HPP - -#include "ingen-config.h" - -#include <cstdlib> -#include <string> - -#include <boost/utility.hpp> -#include <glibmm/module.h> - -#include "PluginImpl.hpp" - -#define NS_INTERNALS "http://drobilla.net/ns/ingen-internals#" - -namespace Ingen { -namespace Engine { - -class NodeImpl; -class BufferFactory; - -/** Implementation of an Internal plugin. - */ -class InternalPlugin : public PluginImpl -{ -public: - InternalPlugin(Shared::LV2URIMap& uris, - const std::string& uri, const std::string& symbol); - - NodeImpl* instantiate(BufferFactory& bufs, - const std::string& name, - bool polyphonic, - PatchImpl* parent, - Engine& engine); - - const std::string symbol() const { return _symbol; } - -private: - const std::string _symbol; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_INTERNALPLUGIN_HPP - diff --git a/src/engine/JackDriver.cpp b/src/engine/JackDriver.cpp deleted file mode 100644 index 6a118778..00000000 --- a/src/engine/JackDriver.cpp +++ /dev/null @@ -1,561 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "ingen-config.h" - -#include <cstdlib> -#include <string> - -#include <jack/midiport.h> -#ifdef INGEN_JACK_SESSION -#include <jack/session.h> -#include <boost/format.hpp> -#include "serialisation/Serialiser.hpp" -#endif - -#include "raul/log.hpp" -#include "raul/List.hpp" - -#include "lv2/lv2plug.in/ns/ext/event/event.h" - -#include "AudioBuffer.hpp" -#include "ControlBindings.hpp" -#include "DuplexPort.hpp" -#include "Engine.hpp" -#include "Event.hpp" -#include "EventBuffer.hpp" -#include "EventSource.hpp" -#include "JackDriver.hpp" -#include "MessageContext.hpp" -#include "PatchImpl.hpp" -#include "PortImpl.hpp" -#include "PostProcessor.hpp" -#include "ProcessSlave.hpp" -#include "QueuedEvent.hpp" -#include "ThreadManager.hpp" -#include "shared/World.hpp" -#include "shared/LV2Features.hpp" -#include "shared/LV2URIMap.hpp" -#include "util.hpp" - -#define LOG(s) s << "[JackDriver] " - -using namespace std; -using namespace Raul; - -typedef jack_default_audio_sample_t jack_sample_t; - -namespace Ingen { -namespace Engine { - -//// JackPort //// - -JackPort::JackPort(JackDriver* driver, DuplexPort* patch_port) - : DriverPort(patch_port) - , Raul::List<JackPort*>::Node(this) - , _driver(driver) - , _jack_port(NULL) -{ - patch_port->setup_buffers(*driver->_engine.buffer_factory(), patch_port->poly()); - create(); -} - -JackPort::~JackPort() -{ - assert(_jack_port == NULL); -} - -void -JackPort::create() -{ - _jack_port = jack_port_register( - _driver->jack_client(), - ingen_jack_port_name(_patch_port->path()).c_str(), - (_patch_port->buffer_type() == PortType::AUDIO) - ? JACK_DEFAULT_AUDIO_TYPE : JACK_DEFAULT_MIDI_TYPE, - (_patch_port->is_input()) - ? JackPortIsInput : JackPortIsOutput, - 0); - - if (_jack_port == NULL) { - error << "[JackPort] Failed to register port " << _patch_port->path() << endl; - throw JackDriver::PortRegistrationFailedException(); - } -} - -void -JackPort::destroy() -{ - assert(_jack_port); - if (jack_port_unregister(_driver->jack_client(), _jack_port)) - error << "[JackPort] Unable to unregister port" << endl; - _jack_port = NULL; -} - -void -JackPort::move(const Raul::Path& path) -{ - jack_port_set_name(_jack_port, ingen_jack_port_name(path).c_str()); -} - -void -JackPort::pre_process(ProcessContext& context) -{ - if (!is_input()) - return; - - const SampleCount nframes = context.nframes(); - - if (_patch_port->buffer_type() == PortType::AUDIO) { - jack_sample_t* jack_buf = (jack_sample_t*)jack_port_get_buffer(_jack_port, nframes); - AudioBuffer* patch_buf = (AudioBuffer*)_patch_port->buffer(0).get(); - - patch_buf->copy(jack_buf, 0, nframes - 1); - - } else if (_patch_port->buffer_type() == PortType::EVENTS) { - void* jack_buf = jack_port_get_buffer(_jack_port, nframes); - EventBuffer* patch_buf = (EventBuffer*)_patch_port->buffer(0).get(); - - const jack_nframes_t event_count = jack_midi_get_event_count(jack_buf); - - patch_buf->prepare_write(context); - - // Copy events from Jack port buffer into patch port buffer - for (jack_nframes_t i = 0; i < event_count; ++i) { - jack_midi_event_t ev; - jack_midi_event_get(&ev, jack_buf, i); - - if (!patch_buf->append(ev.time, 0, - _driver->_midi_event_type, - ev.size, ev.buffer)) - LOG(warn) << "Failed to write MIDI to port buffer, event(s) lost!" << endl; - } - } -} - -void -JackPort::post_process(ProcessContext& context) -{ - if (is_input()) - return; - - const SampleCount nframes = context.nframes(); - - if (_patch_port->buffer_type() == PortType::AUDIO) { - jack_sample_t* jack_buf = (jack_sample_t*)jack_port_get_buffer(_jack_port, nframes); - AudioBuffer* patch_buf = (AudioBuffer*)_patch_port->buffer(0).get(); - - memcpy(jack_buf, patch_buf->data(), nframes * sizeof(Sample)); - - } else if (_patch_port->buffer_type() == PortType::EVENTS) { - void* jack_buf = jack_port_get_buffer(_jack_port, context.nframes()); - EventBuffer* patch_buf = (EventBuffer*)_patch_port->buffer(0).get(); - - patch_buf->prepare_read(context); - jack_midi_clear_buffer(jack_buf); - - uint32_t frames = 0; - uint32_t subframes = 0; - uint16_t type = 0; - uint16_t size = 0; - uint8_t* data = NULL; - - // Copy events from Jack port buffer into patch port buffer - for (patch_buf->rewind(); patch_buf->is_valid(); patch_buf->increment()) { - patch_buf->get_event(&frames, &subframes, &type, &size, &data); - jack_midi_event_write(jack_buf, frames, data, size); - } - } -} - -//// JackDriver //// - -JackDriver::JackDriver(Engine& engine) - : _engine(engine) - , _jack_thread(NULL) - , _sem(0) - , _flag(0) - , _client(NULL) - , _block_length(0) - , _sample_rate(0) - , _is_activated(false) - , _process_context(engine) - , _root_patch(NULL) -{ - _midi_event_type = _engine.world()->uris()->uri_to_id( - LV2_EVENT_URI, "http://lv2plug.in/ns/ext/midi#MidiEvent"); -} - -JackDriver::~JackDriver() -{ - deactivate(); - - if (_client) - jack_client_close(_client); -} - -bool -JackDriver::supports(PortType port_type, EventType event_type) -{ - return (port_type == PortType::AUDIO - || (port_type == PortType::EVENTS && event_type == EventType::MIDI)); -} - -bool -JackDriver::attach(const std::string& server_name, - const std::string& client_name, - void* jack_client) -{ - assert(!_client); - if (!jack_client) { - #ifdef INGEN_JACK_SESSION - const std::string uuid = _engine.world()->jack_uuid(); - if (!uuid.empty()) { - _client = jack_client_open(client_name.c_str(), - JackSessionID, NULL, - uuid.c_str()); - LOG(info) << "Connected to JACK server as client `" - << client_name.c_str() << "' UUID `" << uuid << "'" << endl; - } - #endif - - // Try supplied server name - if (!_client && !server_name.empty()) { - if ((_client = jack_client_open(client_name.c_str(), - JackServerName, NULL, - server_name.c_str()))) { - LOG(info) << "Connected to JACK server `" << server_name << "'" << endl; - } - } - - // Either server name not specified, or supplied server name does not exist - // Connect to default server - if (!_client) { - if ((_client = jack_client_open(client_name.c_str(), JackNullOption, NULL))) - LOG(info) << "Connected to default JACK server" << endl; - } - - // Still failed - if (!_client) { - LOG(error) << "Unable to connect to Jack" << endl; - return false; - } - } else { - _client = (jack_client_t*)jack_client; - } - - _block_length = jack_get_buffer_size(_client); - _sample_rate = jack_get_sample_rate(_client); - - jack_on_shutdown(_client, shutdown_cb, this); - - jack_set_thread_init_callback(_client, thread_init_cb, this); - jack_set_sample_rate_callback(_client, sample_rate_cb, this); - jack_set_buffer_size_callback(_client, block_length_cb, this); -#ifdef INGEN_JACK_SESSION - jack_set_session_callback(_client, session_cb, this); -#endif - - for (Raul::List<JackPort*>::iterator i = _ports.begin(); i != _ports.end(); ++i) - (*i)->create(); - - return true; -} - -void -JackDriver::activate() -{ - Shared::World* world = _engine.world(); - - if (_is_activated) { - LOG(warn) << "Jack driver already activated." << endl; - return; - } - - if (!_client) - attach(world->conf()->option("jack-server").get_string(), - world->conf()->option("jack-client").get_string(), NULL); - - jack_set_process_callback(_client, process_cb, this); - - _is_activated = true; - - _process_context.activate(world->conf()->option("parallelism").get_int32(), - is_realtime()); - - if (jack_activate(_client)) { - LOG(error) << "Could not activate Jack client, aborting." << endl; - exit(EXIT_FAILURE); - } else { - LOG(info) << "Activated Jack client." << endl; - } -} - -void -JackDriver::deactivate() -{ - if (_is_activated) { - _flag = 1; - _is_activated = false; - _sem.wait(); - - for (Raul::List<JackPort*>::iterator i = _ports.begin(); i != _ports.end(); ++i) - (*i)->destroy(); - - if (_client) { - jack_deactivate(_client); - jack_client_close(_client); - _client = NULL; - } - - _jack_thread->stop(); - LOG(info) << "Deactivated Jack client" << endl; - } -} - -/** Add a Jack port. - * - * Realtime safe, this is to be called at the beginning of a process cycle to - * insert (and actually begin using) a new port. - * - * See create_port() and remove_port(). - */ -void -JackDriver::add_port(DriverPort* port) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - assert(dynamic_cast<JackPort*>(port)); - _ports.push_back((JackPort*)port); -} - -/** Remove a Jack port. - * - * Realtime safe. This is to be called at the beginning of a process cycle to - * remove the port from the lists read by the audio thread, so the port - * will no longer be used and can be removed afterwards. - * - * It is the callers responsibility to delete the returned port. - */ -Raul::Deletable* -JackDriver::remove_port(const Path& path, DriverPort** port) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - - for (Raul::List<JackPort*>::iterator i = _ports.begin(); i != _ports.end(); ++i) { - if ((*i)->patch_port()->path() == path) { - Raul::List<JackPort*>::Node* node = _ports.erase(i); - if (port) - *port = node->elem(); - return node; - } - } - - LOG(warn) << "Unable to find port " << path << endl; - return NULL; -} - -DriverPort* -JackDriver::port(const Path& path) -{ - for (Raul::List<JackPort*>::iterator i = _ports.begin(); i != _ports.end(); ++i) - if ((*i)->patch_port()->path() == path) - return (*i); - - return NULL; -} - -DriverPort* -JackDriver::create_port(DuplexPort* patch_port) -{ - try { - if (patch_port->buffer_type() == PortType::AUDIO - || patch_port->buffer_type() == PortType::EVENTS) - return new JackPort(this, patch_port); - else - return NULL; - } catch (...) { - return NULL; - } -} - -DriverPort* -JackDriver::driver_port(const Path& path) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - - for (Raul::List<JackPort*>::iterator i = _ports.begin(); i != _ports.end(); ++i) - if ((*i)->patch_port()->path() == path) - return (*i); - - return NULL; -} - -/**** Jack Callbacks ****/ - -/** Jack process callback, drives entire audio thread. - * - * \callgraph - */ -int -JackDriver::_process_cb(jack_nframes_t nframes) -{ - if (nframes == 0 || ! _is_activated) { - if (_flag == 1) - _sem.post(); - return 0; - } - - // FIXME: all of this time stuff is screwy - - // FIXME: support nframes != buffer_size, even though that never damn well happens - //assert(nframes == _block_length); - - // Note that Jack can not call this function for a cycle, if overloaded - const jack_nframes_t start_of_current_cycle = jack_last_frame_time(_client); - - _transport_state = jack_transport_query(_client, &_position); - - _process_context.locate(start_of_current_cycle, nframes, 0); - - for (ProcessContext::Slaves::iterator i = _process_context.slaves().begin(); - i != _process_context.slaves().end(); ++i) { - (*i)->context().locate(start_of_current_cycle, nframes, 0); - } - - // Read input - for (Raul::List<JackPort*>::iterator i = _ports.begin(); i != _ports.end(); ++i) - (*i)->pre_process(_process_context); - - // Apply control bindings to input - _engine.control_bindings()->pre_process(_process_context, - PtrCast<EventBuffer>(_root_patch->port_impl(0)->buffer(0)).get()); - - _engine.post_processor()->set_end_time(_process_context.end()); - - // Process events that came in during the last cycle - // (Aiming for jitter-free 1 block event latency, ideally) - _engine.process_events(_process_context); - - // Run root patch - if (_root_patch) { - _root_patch->process(_process_context); -#if 0 - static const SampleCount control_block_size = nframes / 2; - for (jack_nframes_t i = 0; i < nframes; i += control_block_size) { - const SampleCount block_size = (i + control_block_size < nframes) - ? control_block_size - : nframes - i; - _process_context.locate(start_of_current_cycle + i, block_size, i); - _root_patch->process(_process_context); - } -#endif - } - - // Emit control binding feedback - _engine.control_bindings()->post_process(_process_context, - PtrCast<EventBuffer>(_root_patch->port_impl(1)->buffer(0)).get()); - - // Signal message context to run if necessary - if (_engine.message_context()->has_requests()) - _engine.message_context()->signal(_process_context); - - // Write output - for (Raul::List<JackPort*>::iterator i = _ports.begin(); i != _ports.end(); ++i) - (*i)->post_process(_process_context); - - return 0; -} - -void -JackDriver::_thread_init_cb() -{ - // Initialize thread specific data - _jack_thread = Thread::create_for_this_thread("Jack"); - assert(&Thread::get() == _jack_thread); - _jack_thread->set_context(THREAD_PROCESS); - ThreadManager::assert_thread(THREAD_PROCESS); -} - -void -JackDriver::_shutdown_cb() -{ - LOG(info) << "Jack shutdown. Exiting." << endl; - _is_activated = false; - delete _jack_thread; - _jack_thread = NULL; - _client = NULL; -} - -int -JackDriver::_sample_rate_cb(jack_nframes_t nframes) -{ - if (_is_activated) { - LOG(error) << "On-the-fly sample rate changing not supported (yet). Aborting." << endl; - exit(EXIT_FAILURE); - } else { - _sample_rate = nframes; - } - return 0; -} - -int -JackDriver::_block_length_cb(jack_nframes_t nframes) -{ - if (_root_patch) { - _block_length = nframes; - _root_patch->set_buffer_size(context(), *_engine.buffer_factory(), PortType::AUDIO, - _engine.buffer_factory()->audio_buffer_size(nframes)); - } - return 0; -} - -#ifdef INGEN_JACK_SESSION -void -JackDriver::_session_cb(jack_session_event_t* event) -{ - LOG(info) << "Jack session save to " << event->session_dir << endl; - - const string cmd = (boost::format("ingen -eg -n %1% -u %2% -l ${SESSION_DIR}") - % jack_get_client_name(_client) - % event->client_uuid).str(); - - SharedPtr<Serialisation::Serialiser> serialiser = _engine.world()->serialiser(); - if (serialiser) { - SharedPtr<Patch> root(_engine.driver()->root_patch(), NullDeleter<Patch>); - serialiser->write_bundle(root, string("file://") + event->session_dir); - } - - event->command_line = strdup(cmd.c_str()); - jack_session_reply(_client, event); - - switch (event->type) { - case JackSessionSave: - break; - case JackSessionSaveAndQuit: - LOG(warn) << "Jack session quit" << endl; - _engine.quit(); - break; - case JackSessionSaveTemplate: - break; - } - - jack_session_event_free(event); -} -#endif - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/JackDriver.hpp b/src/engine/JackDriver.hpp deleted file mode 100644 index 702692b8..00000000 --- a/src/engine/JackDriver.hpp +++ /dev/null @@ -1,183 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_JACKAUDIODRIVER_HPP -#define INGEN_ENGINE_JACKAUDIODRIVER_HPP - -#include "ingen-config.h" - -#include <string> - -#include <jack/jack.h> -#include <jack/transport.h> -#ifdef INGEN_JACK_SESSION -#include <jack/session.h> -#endif - -#include "raul/AtomicInt.hpp" -#include "raul/List.hpp" -#include "raul/Semaphore.hpp" -#include "raul/Thread.hpp" - -#include "Buffer.hpp" -#include "Driver.hpp" -#include "ProcessContext.hpp" - -namespace Raul { class Path; } - -namespace Ingen { -namespace Engine { - -class Engine; -class PatchImpl; -class PortImpl; -class DuplexPort; -class JackDriver; - -/** Used internally by JackDriver to represent a Jack port. - * - * A Jack port always has a one-to-one association with a Patch port. - */ -class JackPort : public DriverPort, public Raul::List<JackPort*>::Node -{ -public: - JackPort(JackDriver* driver, DuplexPort* patch_port); - ~JackPort(); - - void create(); - void destroy(); - - void move(const Raul::Path& path); - - void pre_process(ProcessContext& context); - void post_process(ProcessContext& context); - - jack_port_t* jack_port() const { return _jack_port; } - -private: - JackDriver* _driver; - jack_port_t* _jack_port; -}; - -/** The Jack Driver. - * - * The process callback here drives the entire audio thread by "pulling" - * events from queues, processing them, running the patches, and passing - * events along to the PostProcessor. - * - * \ingroup engine - */ -class JackDriver : public Driver -{ -public: - explicit JackDriver(Engine& engine); - ~JackDriver(); - - bool supports(PortType port_type, EventType event_type); - - bool attach(const std::string& server_name, - const std::string& client_name, - void* jack_client); - - void activate(); - void deactivate(); - void enable(); - void disable(); - - DriverPort* port(const Raul::Path& path); - DriverPort* create_port(DuplexPort* patch_port); - - void add_port(DriverPort* port); - DriverPort* driver_port(const Raul::Path& path); - - Raul::Deletable* remove_port(const Raul::Path& path, DriverPort** port=NULL); - - PatchImpl* root_patch() { return _root_patch; } - void set_root_patch(PatchImpl* patch) { _root_patch = patch; } - - ProcessContext& context() { return _process_context; } - - /** Transport state for this frame. - * Intended to only be called from the audio thread. */ - inline const jack_position_t* position() { return &_position; } - inline jack_transport_state_t transport_state() { return _transport_state; } - - bool is_realtime() const { return jack_is_realtime(_client); } - - jack_client_t* jack_client() const { return _client; } - SampleCount block_length() const { return _block_length; } - SampleCount sample_rate() const { return _sample_rate; } - - inline SampleCount frame_time() const { return _client ? jack_frame_time(_client) : 0; } - - class PortRegistrationFailedException : public std::exception {}; - -private: - friend class JackPort; - - // Static JACK callbacks which call the non-static callbacks (methods) - inline static void thread_init_cb(void* const jack_driver) { - return ((JackDriver*)jack_driver)->_thread_init_cb(); - } - inline static void shutdown_cb(void* const jack_driver) { - return ((JackDriver*)jack_driver)->_shutdown_cb(); - } - inline static int process_cb(jack_nframes_t nframes, void* const jack_driver) { - return ((JackDriver*)jack_driver)->_process_cb(nframes); - } - inline static int block_length_cb(jack_nframes_t nframes, void* const jack_driver) { - return ((JackDriver*)jack_driver)->_block_length_cb(nframes); - } - inline static int sample_rate_cb(jack_nframes_t nframes, void* const jack_driver) { - return ((JackDriver*)jack_driver)->_sample_rate_cb(nframes); - } -#ifdef INGEN_JACK_SESSION - inline static void session_cb(jack_session_event_t* event, void* jack_driver) { - ((JackDriver*)jack_driver)->_session_cb(event); - } -#endif - - // Non static callbacks (methods) - void _thread_init_cb(); - void _shutdown_cb(); - int _process_cb(jack_nframes_t nframes); - int _block_length_cb(jack_nframes_t nframes); - int _sample_rate_cb(jack_nframes_t nframes); -#ifdef INGEN_JACK_SESSION - void _session_cb(jack_session_event_t* event); -#endif - - Engine& _engine; - Raul::Thread* _jack_thread; - Raul::Semaphore _sem; - Raul::AtomicInt _flag; - jack_client_t* _client; - jack_nframes_t _block_length; - jack_nframes_t _sample_rate; - uint32_t _midi_event_type; - bool _is_activated; - jack_position_t _position; - jack_transport_state_t _transport_state; - Raul::List<JackPort*> _ports; - ProcessContext _process_context; - PatchImpl* _root_patch; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_JACKAUDIODRIVER_HPP diff --git a/src/engine/LV2BlobFeature.hpp b/src/engine/LV2BlobFeature.hpp deleted file mode 100644 index a23a3953..00000000 --- a/src/engine/LV2BlobFeature.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2009-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_LV2BLOBFEATURE_HPP -#define INGEN_ENGINE_LV2BLOBFEATURE_HPP - -#include "shared/LV2Features.hpp" - -namespace Ingen { -namespace Engine { - -struct BlobFeature : public Ingen::Shared::LV2Features::Feature { - BlobFeature() { - LV2_Blob_Support* data = (LV2_Blob_Support*)malloc(sizeof(LV2_Blob_Support)); - data->data = NULL; - data->ref_size = sizeof(LV2_Blob); - data->ref_get = &ref_get; - data->ref_copy = &ref_copy; - data->ref_reset = &ref_reset; - data->blob_new = &blob_new; - _feature.URI = LV2_BLOB_SUPPORT_URI; - _feature.data = data; - } - - static LV2_Blob ref_get(LV2_Blob_Support_Data data, - LV2_Atom_Reference* ref) { return 0; } - - static void ref_copy(LV2_Blob_Support_Data data, - LV2_Atom_Reference* dst, - LV2_Atom_Reference* src) {} - - static void ref_reset(LV2_Blob_Support_Data data, - LV2_Atom_Reference* ref) {} - - static void blob_new(LV2_Blob_Support_Data data, - LV2_Atom_Reference* reference, - LV2_Blob_Destroy destroy, - uint32_t type, - size_t size) {} - - SharedPtr<LV2_Feature> feature(Shared::World*, Node*) { - return SharedPtr<LV2_Feature>(&_feature, NullDeleter<LV2_Feature>); - } - -private: - LV2_Feature _feature; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_LV2BLOBFEATURE_HPP diff --git a/src/engine/LV2EventFeature.hpp b/src/engine/LV2EventFeature.hpp deleted file mode 100644 index c9ac1c32..00000000 --- a/src/engine/LV2EventFeature.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2009-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_LV2EVENTFEATURE_HPP -#define INGEN_ENGINE_LV2EVENTFEATURE_HPP - -#include "lv2/lv2plug.in/ns/ext/event/event.h" -#include "shared/LV2Features.hpp" - -namespace Ingen { -namespace Engine { - -struct EventFeature : public Ingen::Shared::LV2Features::Feature { - EventFeature() { - LV2_Event_Feature* data = (LV2_Event_Feature*)malloc(sizeof(LV2_Event_Feature)); - data->lv2_event_ref = &event_ref; - data->lv2_event_unref = &event_unref; - data->callback_data = this; - _feature.URI = LV2_EVENT_URI; - _feature.data = data; - } - - static uint32_t event_ref(LV2_Event_Callback_Data callback_data, - LV2_Event* event) { return 0; } - - static uint32_t event_unref(LV2_Event_Callback_Data callback_data, - LV2_Event* event) { return 0; } - - SharedPtr<LV2_Feature> feature(Shared::World*, Node*) { - return SharedPtr<LV2_Feature>(&_feature, NullDeleter<LV2_Feature>); - } - -private: - LV2_Feature _feature; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_LV2EVENTFEATURE_HPP diff --git a/src/engine/LV2Info.cpp b/src/engine/LV2Info.cpp deleted file mode 100644 index 4fd7885f..00000000 --- a/src/engine/LV2Info.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2008-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define __STDC_LIMIT_MACROS 1 - -#include <stdint.h> - -#include <cassert> - -#include "lv2/lv2plug.in/ns/ext/atom/atom.h" -#include "lv2/lv2plug.in/ns/ext/contexts/contexts.h" - -#include "shared/World.hpp" - -#include "LV2BlobFeature.hpp" -#include "LV2EventFeature.hpp" -#include "LV2Features.hpp" -#include "LV2Info.hpp" -#include "LV2RequestRunFeature.hpp" -#include "LV2ResizeFeature.hpp" - -using namespace std; - -namespace Ingen { -namespace Engine { - -LV2Info::LV2Info(Ingen::Shared::World* world) - : input_class(slv2_value_new_uri(world->slv2_world(), SLV2_PORT_CLASS_INPUT)) - , output_class(slv2_value_new_uri(world->slv2_world(), SLV2_PORT_CLASS_OUTPUT)) - , control_class(slv2_value_new_uri(world->slv2_world(), SLV2_PORT_CLASS_CONTROL)) - , audio_class(slv2_value_new_uri(world->slv2_world(), SLV2_PORT_CLASS_AUDIO)) - , event_class(slv2_value_new_uri(world->slv2_world(), SLV2_PORT_CLASS_EVENT)) - , value_port_class(slv2_value_new_uri(world->slv2_world(), - "http://lv2plug.in/ns/ext/atom#ValuePort")) - , message_port_class(slv2_value_new_uri(world->slv2_world(), - "http://lv2plug.in/ns/ext/atom#MessagePort")) - , _world(world) -{ - assert(world); - - world->lv2_features()->add_feature(LV2_EVENT_URI, - SharedPtr<Shared::LV2Features::Feature>(new EventFeature())); - world->lv2_features()->add_feature(LV2_BLOB_SUPPORT_URI, - SharedPtr<Shared::LV2Features::Feature>(new BlobFeature())); - world->lv2_features()->add_feature(LV2_RESIZE_PORT_URI, - SharedPtr<Shared::LV2Features::Feature>(new ResizeFeature())); - world->lv2_features()->add_feature(LV2_CONTEXTS_URI "#RequestRunFeature", - SharedPtr<Shared::LV2Features::Feature>(new RequestRunFeature())); -} - -LV2Info::~LV2Info() -{ - slv2_value_free(input_class); - slv2_value_free(output_class); - slv2_value_free(control_class); - slv2_value_free(audio_class); - slv2_value_free(event_class); - slv2_value_free(value_port_class); - slv2_value_free(message_port_class); -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/LV2Info.hpp b/src/engine/LV2Info.hpp deleted file mode 100644 index 292eb012..00000000 --- a/src/engine/LV2Info.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2008-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_LV2INFO_HPP -#define INGEN_ENGINE_LV2INFO_HPP - -#include "ingen-config.h" -#ifndef HAVE_SLV2 -#error "This file requires SLV2, but HAVE_SLV2 is not defined. Please report." -#endif - -#include <map> -#include <string> -#include "slv2/slv2.h" -#include "shared/World.hpp" - -namespace Ingen { - -class Node; - -namespace Engine { - -/** Stuff that may need to be passed to an LV2 plugin (i.e. LV2 features). - */ -class LV2Info { -public: - explicit LV2Info(Ingen::Shared::World* world); - ~LV2Info(); - - SLV2Value input_class; - SLV2Value output_class; - SLV2Value control_class; - SLV2Value audio_class; - SLV2Value event_class; - SLV2Value value_port_class; - SLV2Value message_port_class; - - Ingen::Shared::World& world() { return *_world; } - SLV2World lv2_world() { return _world->slv2_world(); } - -private: - Ingen::Shared::World* _world; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_LV2INFO_HPP diff --git a/src/engine/LV2Node.cpp b/src/engine/LV2Node.cpp deleted file mode 100644 index ea292b97..00000000 --- a/src/engine/LV2Node.cpp +++ /dev/null @@ -1,410 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <float.h> -#include <stdint.h> - -#include <cassert> -#include <cmath> -#include <string> - -#include "raul/log.hpp" -#include "raul/Maid.hpp" -#include "raul/Array.hpp" - -#include "AudioBuffer.hpp" -#include "EventBuffer.hpp" -#include "InputPort.hpp" -#include "LV2Node.hpp" -#include "LV2Plugin.hpp" -#include "LV2URIMap.hpp" -#include "MessageContext.hpp" -#include "OutputPort.hpp" -#include "ProcessContext.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -/** Partially construct a LV2Node. - * - * Object is not usable until instantiate() is called with success. - * (It _will_ crash!) - */ -LV2Node::LV2Node(LV2Plugin* plugin, - const string& name, - bool polyphonic, - PatchImpl* parent, - SampleRate srate) - : NodeImpl(plugin, name, polyphonic, parent, srate) - , _lv2_plugin(plugin) - , _instances(NULL) - , _prepared_instances(NULL) - , _message_funcs(NULL) -{ - assert(_lv2_plugin); -} - -LV2Node::~LV2Node() -{ - delete _instances; -} - -bool -LV2Node::prepare_poly(BufferFactory& bufs, uint32_t poly) -{ - if (!_polyphonic) - poly = 1; - - NodeImpl::prepare_poly(bufs, poly); - - if (_polyphony == poly) - return true; - - SharedPtr<LV2Info> info = _lv2_plugin->lv2_info(); - _prepared_instances = new Instances(poly, *_instances, SharedPtr<void>()); - for (uint32_t i = _polyphony; i < _prepared_instances->size(); ++i) { - _prepared_instances->at(i) = SharedPtr<void>( - slv2_plugin_instantiate( - _lv2_plugin->slv2_plugin(), _srate, _features->array()), - slv2_instance_free); - - if (!_prepared_instances->at(i)) { - error << "Failed to instantiate plugin" << endl; - return false; - } - - // Initialize the values of new ports - for (uint32_t j = 0; j < num_ports(); ++j) { - PortImpl* const port = _ports->at(j); - Buffer* const buffer = port->prepared_buffer(i).get(); - if (buffer) { - if (port->is_a(PortType::CONTROL)) { - ((AudioBuffer*)buffer)->set_value(port->value().get_float(), 0, 0); - } else { - buffer->clear(); - } - } - } - - if (_activated) - slv2_instance_activate((SLV2Instance)(*_prepared_instances)[i].get()); - } - - return true; -} - -bool -LV2Node::apply_poly(Raul::Maid& maid, uint32_t poly) -{ - if (!_polyphonic) - poly = 1; - - if (_prepared_instances) { - maid.push(_instances); - _instances = _prepared_instances; - _prepared_instances = NULL; - } - assert(poly <= _instances->size()); - - return NodeImpl::apply_poly(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::Shared::LV2URIMap& uris = bufs.uris(); - SharedPtr<LV2Info> info = _lv2_plugin->lv2_info(); - SLV2Plugin plug = _lv2_plugin->slv2_plugin(); - - uint32_t num_ports = slv2_plugin_get_num_ports(plug); - assert(num_ports > 0); - - _ports = new Raul::Array<PortImpl*>(num_ports, NULL); - _instances = new Instances(_polyphony, SharedPtr<void>()); - - _features = info->world().lv2_features()->lv2_features(&info->world(), this); - - uint32_t port_buffer_size = 0; - SLV2Value ctx_ext_uri = slv2_value_new_uri(info->lv2_world(), - LV2_CONTEXTS_URI "#MessageContext"); - - for (uint32_t i = 0; i < _polyphony; ++i) { - (*_instances)[i] = SharedPtr<void>( - slv2_plugin_instantiate(plug, _srate, _features->array()), - slv2_instance_free); - - if (!instance(i)) { - error << "Failed to instantiate plugin " << _lv2_plugin->uri() - << " voice " << i << endl; - return false; - } - - if (!slv2_plugin_has_feature(plug, ctx_ext_uri)) - continue; - - const void* ctx_ext = slv2_instance_get_extension_data( - instance(i), LV2_CONTEXTS_URI "#MessageContext"); - - if (i == 0 && ctx_ext) { - assert(!_message_funcs); - _message_funcs = (LV2_Contexts_MessageContext*)ctx_ext; - } - } - - slv2_value_free(ctx_ext_uri); - - string port_name; - Path port_path; - - PortImpl* port = 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]; - slv2_plugin_get_port_ranges_float(plug, min_values, max_values, def_values); - - SLV2Value context_pred = slv2_value_new_uri(info->lv2_world(), - "http://lv2plug.in/ns/ext/contexts#context"); - - SLV2Value default_pred = slv2_value_new_uri(info->lv2_world(), - "http://lv2plug.in/ns/lv2core#default"); - - SLV2Value min_size_pred = slv2_value_new_uri(info->lv2_world(), - "http://lv2plug.in/ns/ext/resize-port#minimumSize"); - - SLV2Value port_property_pred = slv2_value_new_uri(info->lv2_world(), - "http://lv2plug.in/ns/lv2core#portProperty"); - - SLV2Value supports_pred = slv2_value_new_uri(info->lv2_world(), - "http://lv2plug.in/ns/ext/atom#supports"); - - //SLV2Value as_large_as_pred = slv2_value_new_uri(info->lv2_world(), - // "http://lv2plug.in/ns/ext/resize-port#asLargeAs"); - - for (uint32_t j = 0; j < num_ports; ++j) { - SLV2Port id = slv2_plugin_get_port_by_index(plug, j); - - // LV2 port symbols are guaranteed to be unique, valid C identifiers - port_name = slv2_value_as_string(slv2_port_get_symbol(plug, id)); - - if (!Symbol::is_valid(port_name)) { - error << "Plugin " << _lv2_plugin->uri() << " port " << j - << " has illegal symbol `" << port_name << "'" << endl; - ret = false; - break; - } - - assert(port_name.find('/') == string::npos); - - port_path = path().child(port_name); - - Raul::Atom val; - PortType data_type = PortType::UNKNOWN; - if (slv2_port_is_a(plug, id, info->control_class)) { - data_type = PortType::CONTROL; - } else if (slv2_port_is_a(plug, id, info->audio_class)) { - data_type = PortType::AUDIO; - } else if (slv2_port_is_a(plug, id, info->event_class)) { - data_type = PortType::EVENTS; - } else if (slv2_port_is_a(plug, id, info->value_port_class)) { - data_type = PortType::VALUE; - } else if (slv2_port_is_a(plug, id, info->message_port_class)) { - data_type = PortType::MESSAGE; - } - - port_buffer_size = bufs.default_buffer_size(data_type); - - if (data_type == PortType::VALUE || data_type == PortType::MESSAGE) { - // Get default value, and its length - SLV2Values defaults = slv2_port_get_value(plug, id, default_pred); - SLV2_FOREACH(i, defaults) { - SLV2Value d = slv2_values_get(defaults, i); - if (slv2_value_is_string(d)) { - const char* str_val = slv2_value_as_string(d); - const size_t str_val_len = strlen(str_val); - val = str_val; - port_buffer_size = str_val_len; - } - } - - // Get minimum size, if set in data - SLV2Values sizes = slv2_port_get_value(plug, id, min_size_pred); - SLV2_FOREACH(i, sizes) { - SLV2Value d = slv2_values_get(sizes, i); - if (slv2_value_is_int(d)) { - size_t size_val = slv2_value_as_int(d); - port_buffer_size = size_val; - } - } - } - - enum { UNKNOWN, INPUT, OUTPUT } direction = UNKNOWN; - if (slv2_port_is_a(plug, id, info->input_class)) { - direction = INPUT; - } else if (slv2_port_is_a(plug, id, info->output_class)) { - direction = OUTPUT; - } - - if (data_type == PortType::UNKNOWN || direction == UNKNOWN) { - warn << "Unknown type or direction for port `" << port_name << "'" << endl; - ret = false; - break; - } - - if (val.type() == Atom::NIL) - val = isnan(def_values[j]) ? 0.0f : def_values[j]; - - if (direction == INPUT) - port = new InputPort(bufs, this, port_name, j, _polyphony, data_type, val); - else - port = new OutputPort(bufs, this, port_name, j, _polyphony, data_type, val); - - if (direction == INPUT && data_type == PortType::CONTROL) { - port->set_value(val); - if (!isnan(min_values[j])) { - port->set_property(uris.lv2_minimum, min_values[j]); - } - if (!isnan(max_values[j])) { - port->set_property(uris.lv2_maximum, max_values[j]); - } - } - - // Set lv2:portProperty properties - SLV2Values properties = slv2_port_get_value(plug, id, port_property_pred); - SLV2_FOREACH(i, properties) { - SLV2Value p = slv2_values_get(properties, i); - if (slv2_value_is_uri(p)) { - port->set_property(uris.lv2_portProperty, Raul::URI(slv2_value_as_uri(p))); - } - } - - // Set atom:supports properties - SLV2Values types = slv2_port_get_value(plug, id, supports_pred); - SLV2_FOREACH(i, types) { - SLV2Value type = slv2_values_get(types, i); - if (slv2_value_is_uri(type)) { - port->add_property(uris.atom_supports, Raul::URI(slv2_value_as_uri(type))); - } - } - - SLV2Values contexts = slv2_port_get_value(plug, id, context_pred); - SLV2_FOREACH(i, contexts) { - SLV2Value c = slv2_values_get(contexts, i); - const char* context = slv2_value_as_string(c); - if (!strcmp(LV2_CONTEXTS_URI "#MessageContext", context)) { - if (!_message_funcs) { - warn << _lv2_plugin->uri() - << " has a message port, but no context extension data." << endl; - } - port->set_context(Context::MESSAGE); - } else { - warn << _lv2_plugin->uri() << " port " << i << " has unknown context " - << slv2_value_as_string(c) - << endl; - } - } - - _ports->at(j) = port; - } - - if (!ret) { - delete _ports; - _ports = NULL; - delete _instances; - _instances = NULL; - } - - delete[] min_values; - delete[] max_values; - delete[] def_values; - slv2_value_free(context_pred); - slv2_value_free(default_pred); - slv2_value_free(min_size_pred); - slv2_value_free(port_property_pred); - - return ret; -} - -void -LV2Node::activate(BufferFactory& bufs) -{ - NodeImpl::activate(bufs); - - for (uint32_t i = 0; i < _polyphony; ++i) - slv2_instance_activate(instance(i)); -} - -void -LV2Node::deactivate() -{ - NodeImpl::deactivate(); - - for (uint32_t i = 0; i < _polyphony; ++i) - slv2_instance_deactivate(instance(i)); -} - -void -LV2Node::message_run(MessageContext& context) -{ - for (size_t i = 0; i < num_ports(); ++i) { - PortImpl* const port = _ports->at(i); - if (port->context() == Context::MESSAGE) - port->pre_process(context); - } - - if (!_valid_ports) - _valid_ports = calloc(num_ports() / 8, 1); - - if (_message_funcs) - (*_message_funcs->run)(instance(0)->lv2_handle, _valid_ports, _valid_ports); -} - -void -LV2Node::process(ProcessContext& context) -{ - NodeImpl::pre_process(context); - - for (uint32_t i = 0; i < _polyphony; ++i) - slv2_instance_run(instance(i), context.nframes()); - - NodeImpl::post_process(context); -} - -void -LV2Node::set_port_buffer(uint32_t voice, uint32_t port_num, - IntrusivePtr<Buffer> buf, SampleCount offset) -{ - NodeImpl::set_port_buffer(voice, port_num, buf, offset); - slv2_instance_connect_port(instance(voice), port_num, - buf ? buf->port_data(_ports->at(port_num)->buffer_type(), offset) : NULL); -} - -} // namespace Engine -} // namespace Ingen - diff --git a/src/engine/LV2Node.hpp b/src/engine/LV2Node.hpp deleted file mode 100644 index 7633f4d7..00000000 --- a/src/engine/LV2Node.hpp +++ /dev/null @@ -1,82 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_LV2NODE_HPP -#define INGEN_ENGINE_LV2NODE_HPP - -#include <string> -#include "slv2/slv2.h" -#include "raul/IntrusivePtr.hpp" -#include "lv2/lv2plug.in/ns/ext/contexts/contexts.h" -#include "types.hpp" -#include "NodeImpl.hpp" -#include "LV2Features.hpp" - -namespace Ingen { -namespace Engine { - -class LV2Plugin; - -/** An instance of a LV2 plugin. - * - * \ingroup engine - */ -class LV2Node : public NodeImpl -{ -public: - LV2Node(LV2Plugin* plugin, - const std::string& name, - bool polyphonic, - PatchImpl* parent, - SampleRate srate); - - ~LV2Node(); - - bool instantiate(BufferFactory& bufs); - - bool prepare_poly(BufferFactory& bufs, uint32_t poly); - bool apply_poly(Raul::Maid& maid, uint32_t poly); - - void activate(BufferFactory& bufs); - void deactivate(); - - void message_run(MessageContext& context); - - void process(ProcessContext& context); - - void set_port_buffer(uint32_t voice, uint32_t port_num, - IntrusivePtr<Buffer> buf, SampleCount offset); - -protected: - inline SLV2Instance instance(uint32_t voice) { return (SLV2Instance)(*_instances)[voice].get(); } - - typedef Raul::Array< SharedPtr<void> > Instances; - - LV2Plugin* _lv2_plugin; - Instances* _instances; - Instances* _prepared_instances; - - LV2_Contexts_MessageContext* _message_funcs; - - SharedPtr<Ingen::Shared::LV2Features::FeatureArray> _features; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_LV2NODE_HPP - diff --git a/src/engine/LV2Plugin.cpp b/src/engine/LV2Plugin.cpp deleted file mode 100644 index 0efc3abf..00000000 --- a/src/engine/LV2Plugin.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <cassert> -#include <string> -#include <glibmm.h> - -#include "sord/sordmm.hpp" - -#include "shared/LV2URIMap.hpp" -#include "Driver.hpp" -#include "Engine.hpp" -#include "LV2Node.hpp" -#include "LV2Plugin.hpp" -#include "NodeImpl.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -LV2Plugin::LV2Plugin(SharedPtr<LV2Info> lv2_info, const std::string& uri) - : PluginImpl(*lv2_info->world().uris().get(), Plugin::LV2, uri) - , _slv2_plugin(NULL) - , _lv2_info(lv2_info) -{ - set_property(_uris.rdf_type, _uris.lv2_Plugin); -} - -const string -LV2Plugin::symbol() const -{ - string working = uri().str(); - if (working[working.length()-1] == '/') - working = working.substr(0, working.length()-1); - - while (working.length() > 0) { - size_t last_slash = working.find_last_of("/"); - const string symbol = working.substr(last_slash+1); - if ( (symbol[0] >= 'a' && symbol[0] <= 'z') - || (symbol[0] >= 'A' && symbol[0] <= 'Z') ) - return Path::nameify(symbol); - else - working = working.substr(0, last_slash); - } - - return "lv2_symbol"; -} - -NodeImpl* -LV2Plugin::instantiate(BufferFactory& bufs, - const string& name, - bool polyphonic, - PatchImpl* parent, - Engine& engine) -{ - const SampleCount srate = engine.driver()->sample_rate(); - - load(); // FIXME: unload at some point - - LV2Node* n = new LV2Node(this, name, polyphonic, parent, srate); - - if ( ! n->instantiate(bufs) ) { - delete n; - n = NULL; - } - - return n; -} - -void -LV2Plugin::slv2_plugin(SLV2Plugin p) -{ - _slv2_plugin = p; -} - -const std::string& -LV2Plugin::library_path() const -{ - static const std::string empty_string; - if (_library_path.empty()) { - SLV2Value v = slv2_plugin_get_library_uri(_slv2_plugin); - if (v) { - _library_path = slv2_uri_to_path(slv2_value_as_uri(v)); - } else { - warn << uri() << " has no library path" << endl; - return empty_string; - } - } - - return _library_path; -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/LV2Plugin.hpp b/src/engine/LV2Plugin.hpp deleted file mode 100644 index 6bc9501a..00000000 --- a/src/engine/LV2Plugin.hpp +++ /dev/null @@ -1,76 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_LV2PLUGIN_HPP -#define INGEN_ENGINE_LV2PLUGIN_HPP - -#include "ingen-config.h" - -#ifndef HAVE_SLV2 -#error "This file requires SLV2, but HAVE_SLV2 is not defined. Please report." -#endif - -#include <cstdlib> -#include <string> - -#include <glibmm/module.h> -#include <boost/utility.hpp> - -#include "slv2/slv2.h" -#include "raul/SharedPtr.hpp" - -#include "PluginImpl.hpp" -#include "LV2Info.hpp" - -namespace Ingen { -namespace Engine { - -class PatchImpl; -class NodeImpl; - -/** Implementation of an LV2 plugin (loaded shared library). - */ -class LV2Plugin : public PluginImpl -{ -public: - LV2Plugin(SharedPtr<LV2Info> lv2_info, const std::string& uri); - - NodeImpl* instantiate(BufferFactory& bufs, - const std::string& name, - bool polyphonic, - PatchImpl* parent, - Engine& engine); - - const std::string symbol() const; - - SharedPtr<LV2Info> lv2_info() const { return _lv2_info; } - - const std::string& library_path() const; - - SLV2Plugin slv2_plugin() const { return _slv2_plugin; } - void slv2_plugin(SLV2Plugin p); - -private: - SLV2Plugin _slv2_plugin; - SharedPtr<LV2Info> _lv2_info; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_LV2PLUGIN_HPP - diff --git a/src/engine/LV2RequestRunFeature.hpp b/src/engine/LV2RequestRunFeature.hpp deleted file mode 100644 index 324676a7..00000000 --- a/src/engine/LV2RequestRunFeature.hpp +++ /dev/null @@ -1,84 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2010-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_LV2_REQUEST_RUN_FEATURE_HPP -#define INGEN_ENGINE_LV2_REQUEST_RUN_FEATURE_HPP - -#include "lv2/lv2plug.in/ns/ext/contexts/contexts.h" - -#include "raul/log.hpp" - -#include "shared/LV2Features.hpp" - -#include "Driver.hpp" -#include "Engine.hpp" -#include "MessageContext.hpp" -#include "NodeImpl.hpp" -#include "PortImpl.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -struct RequestRunFeature : public Ingen::Shared::LV2Features::Feature { - struct Data { - inline Data(Shared::World* w, Node* n) : world(w), node(n) {} - Shared::World* world; - Node* node; - }; - - static void request_run(LV2_Contexts_Request_Run_Data data_ptr, - uint32_t context_uri) { - Data* data = reinterpret_cast<Data*>(data_ptr); - if (!data->world->local_engine()) - return; - - Engine* engine = (Engine*)data->world->local_engine().get(); - engine->message_context()->run( - dynamic_cast<NodeImpl*>(data->node), - engine->driver()->frame_time()); - } - - static void delete_feature(LV2_Feature* feature) { - delete (Data*)feature->data; - free(feature); - } - - SharedPtr<LV2_Feature> feature(Shared::World* world, Node* n) { - NodeImpl* node = dynamic_cast<NodeImpl*>(n); - if (!node) - return SharedPtr<LV2_Feature>(); - - typedef LV2_Contexts_Request_Run_Feature Feature; - Feature* data = (Feature*)malloc(sizeof(Feature)); - data->data = new Data(world, n); - data->request_run = &request_run; - - LV2_Feature* f = (LV2_Feature*)malloc(sizeof(LV2_Feature)); - f->URI = LV2_CONTEXTS_URI "#RequestRunFeature"; - f->data = data; - - return SharedPtr<LV2_Feature>(f, &delete_feature); - } -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_LV2_REQUEST_RUN_FEATURE_HPP diff --git a/src/engine/LV2ResizeFeature.hpp b/src/engine/LV2ResizeFeature.hpp deleted file mode 100644 index 4d303070..00000000 --- a/src/engine/LV2ResizeFeature.hpp +++ /dev/null @@ -1,73 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2009-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_LV2RESIZEFEATURE_HPP -#define INGEN_ENGINE_LV2RESIZEFEATURE_HPP - -#include "raul/log.hpp" -#include "lv2/lv2plug.in/ns/ext/resize-port/resize-port.h" -#include "shared/LV2Features.hpp" -#include "NodeImpl.hpp" -#include "PortImpl.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -struct ResizeFeature : public Ingen::Shared::LV2Features::Feature { - static bool resize_port(LV2_Resize_Port_Feature_Data data, - uint32_t index, - size_t size) { - NodeImpl* node = (NodeImpl*)data; - PortImpl* port = node->port_impl(index); - switch (port->context()) { - case Context::MESSAGE: - port->buffer(0)->resize(size); - port->connect_buffers(); - return true; - default: - // TODO: Implement realtime allocator and support this in audio thread - return false; - } - } - - static void delete_feature(LV2_Feature* feature) { - free(feature->data); - free(feature); - } - - SharedPtr<LV2_Feature> feature(Shared::World* w, Node* n) { - NodeImpl* node = dynamic_cast<NodeImpl*>(n); - if (!node) - return SharedPtr<LV2_Feature>(); - LV2_Resize_Port_Feature* data - = (LV2_Resize_Port_Feature*)malloc(sizeof(LV2_Resize_Port_Feature)); - data->data = node; - data->resize_port = &resize_port; - LV2_Feature* f = (LV2_Feature*)malloc(sizeof(LV2_Feature)); - f->URI = LV2_RESIZE_PORT_URI; - f->data = data; - return SharedPtr<LV2_Feature>(f, &delete_feature); - } -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_LV2RESIZEFEATURE_HPP diff --git a/src/engine/MessageContext.cpp b/src/engine/MessageContext.cpp deleted file mode 100644 index db65472a..00000000 --- a/src/engine/MessageContext.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2008-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <algorithm> -#include "lv2/lv2plug.in/ns/ext/contexts/contexts.h" -#include "raul/log.hpp" -#include "ConnectionImpl.hpp" -#include "Engine.hpp" -#include "MessageContext.hpp" -#include "NodeImpl.hpp" -#include "PatchImpl.hpp" -#include "PortImpl.hpp" -#include "ProcessContext.hpp" -#include "ThreadManager.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -void -MessageContext::run(NodeImpl* node, FrameTime time) -{ - if (ThreadManager::thread_is(THREAD_PROCESS)) { - const Request r(time, node); - _requests.write(sizeof(Request), &r); - // signal() will be called at the end of this process cycle - } else { - assert(node); - Glib::Mutex::Lock lock(_mutex); - _non_rt_request = Request(time, node); - _sem.post(); - _cond.wait(_mutex); - } -} - -void -MessageContext::_run() -{ - Request req; - - while (true) { - _sem.wait(); - - // Enqueue a request from the pre-process thread - { - Glib::Mutex::Lock lock(_mutex); - const Request req = _non_rt_request; - if (req.node) { - _queue.insert(req); - _end_time = std::max(_end_time, req.time); - _cond.broadcast(); // Notify caller we got the message - } - } - - // Enqueue (and thereby sort) requests from audio thread - while (has_requests()) { - _requests.full_read(sizeof(Request), &req); - if (req.node) { - _queue.insert(req); - } else { - _end_time = req.time; - break; - } - } - - // Run events in time increasing order - // Note that executing nodes may insert further events into the queue - while (!_queue.empty()) { - const Request req = *_queue.begin(); - - // Break if all events during this cycle have been consumed - // (the queue may contain generated events with later times) - if (req.time > _end_time) { - break; - } - - _queue.erase(_queue.begin()); - execute(req); - } - } -} - -void -MessageContext::execute(const Request& req) -{ - NodeImpl* node = req.node; - node->message_run(*this); - - void* valid_ports = node->valid_ports(); - PatchImpl* patch = node->parent_patch(); - - for (uint32_t i = 0; i < node->num_ports(); ++i) { - PortImpl* p = node->port_impl(i); - if (p->is_output() && p->context() == Context::MESSAGE && - lv2_contexts_port_is_valid(valid_ports, i)) { - PatchImpl::Connections& wires = patch->connections(); - for (PatchImpl::Connections::iterator c = wires.begin(); c != wires.end(); ++c) { - ConnectionImpl* ci = (ConnectionImpl*)c->second.get(); - if (ci->src_port() == p && ci->dst_port()->context() == Context::MESSAGE) { - _queue.insert(Request(req.time, ci->dst_port()->parent_node())); - } - } - } - } - - node->reset_valid_ports(); -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/MessageContext.hpp b/src/engine/MessageContext.hpp deleted file mode 100644 index ccdda448..00000000 --- a/src/engine/MessageContext.hpp +++ /dev/null @@ -1,114 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_MESSAGECONTEXT_HPP -#define INGEN_ENGINE_MESSAGECONTEXT_HPP - -#include <set> -#include <glibmm/thread.h> -#include "raul/Thread.hpp" -#include "raul/Semaphore.hpp" -#include "raul/AtomicPtr.hpp" -#include "lv2/lv2plug.in/ns/ext/atom/atom.h" -#include "Context.hpp" -#include "ProcessContext.hpp" -#include "ThreadManager.hpp" - -namespace Ingen { -namespace Engine { - -class NodeImpl; - -/** Context of a message_run() call. - * - * The message context is a non-hard-realtime thread used to execute things - * that can take too long to execute in an audio thread, and do sloppy timed - * event propagation and scheduling. Interface to plugins via the - * LV2 contexts extension. - * - * \ingroup engine - */ -class MessageContext : public Context, public Raul::Thread -{ -public: - explicit MessageContext(Engine& engine) - : Context(engine, MESSAGE) - , Raul::Thread("MessageContext") - , _sem(0) - , _requests(engine.event_queue_size()) - , _end_time(0) - { - Thread::set_context(THREAD_MESSAGE); - } - - /** Schedule a message context run at a certain time. - * Safe to call from either process thread or pre-process thread. - */ - void run(NodeImpl* node, FrameTime time); - -protected: - struct Request { - Request(FrameTime t=0, NodeImpl* n=0) : time(t), node(n) {} - FrameTime time; - NodeImpl* node; - }; - -public: - /** Signal the end of a cycle that has produced messages. - * AUDIO THREAD ONLY. - */ - inline void signal(ProcessContext& context) { - ThreadManager::assert_thread(THREAD_PROCESS); - const Request cycle_end_request(context.end(), NULL); - _requests.write(sizeof(Request), &cycle_end_request); - _sem.post(); - } - - /** Return true iff requests are pending. Safe from any thread. */ - inline bool has_requests() const { - return _requests.read_space() >= sizeof(Request); - } - -protected: - /** Thread run method (wait for and execute requests from process thread */ - void _run(); - - /** Execute a request (possibly enqueueing more requests) */ - void execute(const Request& req); - - Raul::Semaphore _sem; - Raul::RingBuffer _requests; - Glib::Mutex _mutex; - Glib::Cond _cond; - Request _non_rt_request; - - struct RequestEarlier { - bool operator()(const Request& r1, const Request& r2) { - return r1.time < r2.time; - } - }; - - typedef std::set<Request, RequestEarlier> Queue; - Queue _queue; - FrameTime _end_time; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_MESSAGECONTEXT_HPP - diff --git a/src/engine/NodeFactory.cpp b/src/engine/NodeFactory.cpp deleted file mode 100644 index 20ad9fc2..00000000 --- a/src/engine/NodeFactory.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <cstdlib> -#include <string> -#include <pthread.h> -#include <dirent.h> -#include <float.h> -#include <cmath> -#include <glibmm/miscutils.h> -#include "sord/sordmm.hpp" -#include "raul/log.hpp" -#include "ingen-config.h" -#include "shared/World.hpp" -#include "internals/Controller.hpp" -#include "internals/Delay.hpp" -#include "internals/Note.hpp" -#include "internals/Trigger.hpp" -#include "Engine.hpp" -#include "InternalPlugin.hpp" -#include "NodeFactory.hpp" -#include "PatchImpl.hpp" -#include "ThreadManager.hpp" -#ifdef HAVE_SLV2 -#include "slv2/slv2.h" -#include "LV2Plugin.hpp" -#include "LV2Node.hpp" -#endif - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -using namespace Internals; - -NodeFactory::NodeFactory(Ingen::Shared::World* world) - : _world(world) - , _has_loaded(false) -#ifdef HAVE_SLV2 - , _lv2_info(new LV2Info(world)) -#endif -{ -} - -NodeFactory::~NodeFactory() -{ - for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) - delete i->second; - - _plugins.clear(); -} - -const NodeFactory::Plugins& -NodeFactory::plugins() -{ - if (!_has_loaded) { - // TODO: Plugin list refreshing - load_plugins(); - } - return _plugins; -} - -PluginImpl* -NodeFactory::plugin(const Raul::URI& uri) -{ - const Plugins::const_iterator i = _plugins.find(uri); - return ((i != _plugins.end()) ? i->second : NULL); -} - -void -NodeFactory::load_plugins() -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - - // Only load if we havn't already, so every client connecting doesn't cause - // this (expensive!) stuff to happen. Not the best solution - would be nice - // if clients could refresh plugins list for whatever reason :/ - if (!_has_loaded) { - _plugins.clear(); // FIXME: assert empty? - - load_internal_plugins(); - -#ifdef HAVE_SLV2 - load_lv2_plugins(); -#endif - - _has_loaded = true; - } -} - -void -NodeFactory::load_internal_plugins() -{ - Ingen::Shared::LV2URIMap& uris = *_world->uris().get(); - 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)); -} - -#ifdef HAVE_SLV2 -/** Loads information about all LV2 plugins into internal plugin database. - */ -void -NodeFactory::load_lv2_plugins() -{ - SLV2Plugins plugins = slv2_world_get_all_plugins(_world->slv2_world()); - - SLV2_FOREACH(i, plugins) { - SLV2Plugin lv2_plug = slv2_plugins_get(plugins, i); - - const string uri(slv2_value_as_uri(slv2_plugin_get_uri(lv2_plug))); - - assert(_plugins.find(uri) == _plugins.end()); - - LV2Plugin* const plugin = new LV2Plugin(_lv2_info, uri); - - plugin->slv2_plugin(lv2_plug); - _plugins.insert(make_pair(uri, plugin)); - } -} -#endif // HAVE_SLV2 - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/NodeFactory.hpp b/src/engine/NodeFactory.hpp deleted file mode 100644 index 3c906663..00000000 --- a/src/engine/NodeFactory.hpp +++ /dev/null @@ -1,76 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_NODEFACTORY_HPP -#define INGEN_ENGINE_NODEFACTORY_HPP - -#include <list> -#include <map> -#include <string> -#include <pthread.h> -#include <glibmm/module.h> -#include "raul/SharedPtr.hpp" -#include "raul/URI.hpp" -#include "shared/World.hpp" -#include "ingen-config.h" - -namespace Ingen { -namespace Engine { - -class NodeImpl; -class PatchImpl; -class PluginImpl; -#ifdef HAVE_SLV2 -class LV2Info; -#endif - -/** Discovers and loads plugin libraries. - * - * \ingroup engine - */ -class NodeFactory -{ -public: - explicit NodeFactory(Ingen::Shared::World* world); - ~NodeFactory(); - - void load_plugins(); - - typedef std::map<Raul::URI, PluginImpl*> Plugins; - const Plugins& plugins(); - - PluginImpl* plugin(const Raul::URI& uri); - -private: -#ifdef HAVE_SLV2 - void load_lv2_plugins(); -#endif - - void load_internal_plugins(); - - Plugins _plugins; - Ingen::Shared::World* _world; - bool _has_loaded; -#ifdef HAVE_SLV2 - SharedPtr<LV2Info> _lv2_info; -#endif -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_NODEFACTORY_HPP diff --git a/src/engine/NodeImpl.cpp b/src/engine/NodeImpl.cpp deleted file mode 100644 index fc08c8de..00000000 --- a/src/engine/NodeImpl.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <cassert> -#include <stdint.h> -#include "lv2/lv2plug.in/ns/ext/contexts/contexts.h" -#include "raul/List.hpp" -#include "raul/Array.hpp" -#include "util.hpp" -#include "AudioBuffer.hpp" -#include "ClientBroadcaster.hpp" -#include "EngineStore.hpp" -#include "NodeImpl.hpp" -#include "PatchImpl.hpp" -#include "PluginImpl.hpp" -#include "PortImpl.hpp" -#include "ThreadManager.hpp" - -using namespace std; - -namespace Ingen { -namespace Engine { - -NodeImpl::NodeImpl(PluginImpl* plugin, const Raul::Symbol& symbol, bool polyphonic, PatchImpl* parent, SampleRate srate) - : GraphObjectImpl(plugin->uris(), parent, symbol) - , _plugin(plugin) - , _polyphonic(polyphonic) - , _polyphony((polyphonic && parent) ? parent->internal_poly() : 1) - , _srate(srate) - , _valid_ports(NULL) - , _input_ready(1) - , _process_lock(0) - , _n_inputs_ready(0) - , _ports(NULL) - , _providers(new Raul::List<NodeImpl*>()) - , _dependants(new Raul::List<NodeImpl*>()) - , _activated(false) - , _traversed(false) -{ - assert(_plugin); - assert(_polyphony > 0); - assert(_parent == NULL || (_polyphony == parent->internal_poly() || _polyphony == 1)); -} - -NodeImpl::~NodeImpl() -{ - if (_activated) - deactivate(); - - delete _providers; - delete _dependants; - delete _ports; - - free(_valid_ports); -} - -Port* -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); - assert(!_activated); - _activated = true; - - for (uint32_t p = 0; p < num_ports(); ++p) { - PortImpl* const port = _ports->at(p); - port->setup_buffers(bufs, port->poly()); - port->connect_buffers(); - for (uint32_t v = 0; v < _polyphony; ++v) { - if (!port->buffer(v)) - continue; - if (port->is_a(PortType::CONTROL)) - ((AudioBuffer*)port->buffer(v).get())->set_value(port->value().get_float(), 0, 0); - else - port->buffer(v)->clear(); - } - } -} - -void -NodeImpl::deactivate() -{ - assert(_activated); - _activated = false; - for (uint32_t i = 0; i < _polyphony; ++i) { - for (unsigned long j = 0; j < num_ports(); ++j) { - PortImpl* const port = _ports->at(j); - if (port->is_output() && port->buffer(i)) - port->buffer(i)->clear(); - } - } -} - -bool -NodeImpl::prepare_poly(BufferFactory& bufs, uint32_t poly) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - - if (!_polyphonic) - poly = 1; - - if (_ports) - for (size_t i = 0; i < _ports->size(); ++i) - _ports->at(i)->prepare_poly(bufs, poly); - - return true; -} - -bool -NodeImpl::apply_poly(Raul::Maid& maid, uint32_t poly) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - - if (!_polyphonic) - poly = 1; - - _polyphony = poly; - - if (_ports) - for (size_t i = 0; i < num_ports(); ++i) - _ports->at(i)->apply_poly(maid, poly); - - return true; -} - -void -NodeImpl::set_buffer_size(Context& context, BufferFactory& bufs, PortType type, size_t size) -{ - if (_ports) - for (size_t i = 0; i < _ports->size(); ++i) - if (_ports->at(i)->buffer_type() == type && _ports->at(i)->context() == context.id()) - _ports->at(i)->set_buffer_size(context, bufs, size); -} - -void -NodeImpl::reset_input_ready() -{ - _n_inputs_ready = 0; - _process_lock = 0; - _input_ready.reset(0); -} - -bool -NodeImpl::process_lock() -{ - return _process_lock.compare_and_exchange(0, 1); -} - -void -NodeImpl::process_unlock() -{ - _process_lock = 0; -} - -void -NodeImpl::wait_for_input(size_t num_providers) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - assert(_process_lock.get() == 1); - - while ((unsigned)_n_inputs_ready.get() < num_providers) - _input_ready.wait(); -} - -void -NodeImpl::signal_input_ready() -{ - ThreadManager::assert_thread(THREAD_PROCESS); - ++_n_inputs_ready; - _input_ready.post(); -} - -/** Prepare to run a cycle (in the audio thread) - */ -void -NodeImpl::pre_process(Context& context) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - - // Mix down input ports - for (uint32_t i = 0; i < num_ports(); ++i) { - PortImpl* const port = _ports->at(i); - if (port->context() == Context::AUDIO) { - port->pre_process(context); - port->connect_buffers(context.offset()); - } - } -} - -/** Prepare to run a cycle (in the audio thread) - */ -void -NodeImpl::post_process(Context& context) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - - // Write output ports - for (size_t i = 0; _ports && i < _ports->size(); ++i) { - PortImpl* const port = _ports->at(i); - if (port->context() == Context::AUDIO) - _ports->at(i)->post_process(context); - } -} - -/** Flag a port as set (for message context) - */ -void -NodeImpl::set_port_valid(uint32_t port_index) -{ - // Allocate enough space for one bit per port - if (!_valid_ports) - _valid_ports = calloc(num_ports() / 8, 1); - lv2_contexts_set_port_valid(_valid_ports, port_index); -} - -void* -NodeImpl::valid_ports() -{ - return _valid_ports; -} - -void -NodeImpl::reset_valid_ports() -{ - if (_valid_ports) - memset(_valid_ports, '\0', num_ports() / 8); -} - -void -NodeImpl::set_port_buffer(uint32_t voice, uint32_t port_num, - BufferFactory::Ref buf, SampleCount offset) -{ - /*std::cout << path() << " set port " << port_num << " voice " << voice - << " buffer " << buf << " offset " << offset << std::endl;*/ -} - -} // namespace Engine -} // namespace Ingen - diff --git a/src/engine/NodeImpl.hpp b/src/engine/NodeImpl.hpp deleted file mode 100644 index d2c49e4f..00000000 --- a/src/engine/NodeImpl.hpp +++ /dev/null @@ -1,223 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_NODEIMPL_HPP -#define INGEN_ENGINE_NODEIMPL_HPP - -#include <string> -#include "raul/Array.hpp" -#include "raul/AtomicInt.hpp" -#include "raul/IntrusivePtr.hpp" -#include "raul/Semaphore.hpp" -#include "ingen/Node.hpp" -#include "GraphObjectImpl.hpp" -#include "types.hpp" - -namespace Raul { template <typename T> class List; class Maid; } - -namespace Ingen { - -class Plugin; -class Port; - -namespace Engine { - -class Buffer; -class BufferFactory; -class Context; -class MessageContext; -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, virtual public Node -{ -public: - NodeImpl(PluginImpl* plugin, - const Raul::Symbol& symbol, - bool poly, - PatchImpl* parent, - SampleRate rate); - - virtual ~NodeImpl(); - - /** 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; } - - /** Parallelism: Reset flags for start of a new cycle. */ - virtual void reset_input_ready(); - - /** Parallelism: Claim this node (to wait on its input). - * Only one thread will ever take this lock on a particular Node. - * \return true if lock was aquired, false otherwise - */ - virtual bool process_lock(); - - /** Parallelism: Unclaim this node (let someone else wait on its input). - * Only a thread which successfully called process_lock may call this. - */ - virtual void process_unlock(); - - /** Parallelism: Wait for signal that input is ready. - * Only a thread which successfully called process_lock may call this. - */ - virtual void wait_for_input(size_t num_providers); - - /** Parallelism: Signal that input is ready. Realtime safe. - * Calling this will wake up the thread which blocked on wait_for_input - * if there is one, and otherwise cause it to return true the next call. - * \return true if lock was aquired and input is ready, false otherwise - */ - virtual void signal_input_ready(); - - /** Parallelism: Return the number of providers that have signalled. */ - virtual unsigned n_inputs_ready() const { return _n_inputs_ready.get(); } - - /** Learn the next incoming MIDI event (for internals) */ - virtual void learn() {} - - /** Run the node for one instant in the message thread. */ - virtual void message_run(MessageContext& context) {} - - /** Flag a port as valid (for message context) */ - virtual void set_port_valid(uint32_t index); - - /** Return a bit vector of which ports are valid */ - virtual void* valid_ports(); - - /** Clear all bits in valid_ports() */ - virtual void reset_valid_ports(); - - /** Do whatever needs doing in the process thread before process() is called */ - virtual void pre_process(Context& context); - - /** Run the node for @a nframes input/output. - * - * @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(Context& 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, - IntrusivePtr<Buffer> buf, - SampleCount offset); - - virtual Port* port(uint32_t index) const; - virtual PortImpl* port_impl(uint32_t index) const { return (*_ports)[index]; } - - /** Nodes that are connected to this Node's inputs. - * (This Node depends on them) - */ - Raul::List<NodeImpl*>* providers() { return _providers; } - void providers(Raul::List<NodeImpl*>* l) { _providers = l; } - - /** Nodes are are connected to this Node's outputs. - * (They depend on this Node) - */ - Raul::List<NodeImpl*>* dependants() { return _dependants; } - void dependants(Raul::List<NodeImpl*>* l) { _dependants = l; } - - /** Flag node as polyphonic. - * - * Note this will not actually allocate voices etc., prepare_poly - * and apply_poly must be called after this function to truly make - * a node polyphonic. - */ - virtual void set_polyphonic(bool p) { _polyphonic = p; } - - virtual bool prepare_poly(BufferFactory& bufs, uint32_t poly); - virtual bool apply_poly(Raul::Maid& maid, uint32_t poly); - - /** Information about the Plugin this Node is an instance of. - * Not the best name - not all nodes come from plugins (ie Patch) - */ - virtual PluginImpl* plugin_impl() const { 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, - PortType type, size_t size); - - /** The Patch this Node belongs to. */ - inline PatchImpl* parent_patch() const { return (PatchImpl*)_parent; } - - SampleRate sample_rate() const { return _srate; } - virtual uint32_t num_ports() const { return _ports ? _ports->size() : 0; } - virtual uint32_t polyphony() const { return _polyphony; } - - /** Used by the process order finding algorithm (ie during connections) */ - bool traversed() const { return _traversed; } - void traversed(bool b) { _traversed = b; } - -protected: - PluginImpl* _plugin; - - bool _polyphonic; - uint32_t _polyphony; - SampleRate _srate; - - void* _valid_ports; ///< Valid port flags for message context - - Raul::Semaphore _input_ready; ///< Parallelism: input ready signal - Raul::AtomicInt _process_lock; ///< Parallelism: Waiting on inputs 'lock' - Raul::AtomicInt _n_inputs_ready; ///< Parallelism: # input ready signals this cycle - Raul::Array<PortImpl*>* _ports; ///< Access in audio thread only - Raul::List<NodeImpl*>* _providers; ///< Nodes connected to this one's input ports - Raul::List<NodeImpl*>* _dependants; ///< Nodes this one's output ports are connected to - - bool _activated; - bool _traversed; ///< Flag for process order algorithm -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_NODEIMPL_HPP diff --git a/src/engine/OSCClientSender.cpp b/src/engine/OSCClientSender.cpp deleted file mode 100644 index bcd3be10..00000000 --- a/src/engine/OSCClientSender.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <unistd.h> - -#include <cassert> -#include <string> - -#include "raul/log.hpp" -#include "raul/AtomLiblo.hpp" - -#include "EngineStore.hpp" -#include "NodeImpl.hpp" -#include "OSCClientSender.hpp" -#include "PatchImpl.hpp" - -#include "PluginImpl.hpp" -#include "PortImpl.hpp" -#include "ingen/ClientInterface.hpp" -#include "util.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -/** @page client_osc_namespace Client OSC Namespace Documentation - * - * <p>These are the commands the client recognizes. All monitoring of - * changes in the engine happens via these commands.</p> - */ - -/** @page client_osc_namespace - * <h2>/ok</h2> - * @arg @p response-id :: Integer - * - * @par - * Successful response to some command. - */ -void -OSCClientSender::response_ok(int32_t id) -{ - if (!_enabled) - return; - - - - if (lo_send(_address, "/ok", "i", id, LO_ARGS_END) < 0) { - Raul::error << "Unable to send OK " << id << "! (" - << lo_address_errstr(_address) << ")" << endl; - } -} - -/** @page client_osc_namespace - * <h2>/error</h2> - * @arg @p response-id :: Integer - * @arg @p message :: String - * - * @par - * Unsuccessful response to some command. - */ -void -OSCClientSender::response_error(int32_t id, const std::string& msg) -{ - if (!_enabled) - return; - - if (lo_send(_address, "/error", "is", id, msg.c_str(), LO_ARGS_END) < 0) { - Raul::error << "Unable to send error " << id << "! (" - << lo_address_errstr(_address) << ")" << endl; - } -} - -/** @page client_osc_namespace - * <h2>/error</h2> - * @arg @p message :: String - * - * @par - * Notification that an error has occurred. This is for notification of errors - * that aren't a direct response to a user command, i.e. "unexpected" errors. - */ -void -OSCClientSender::error(const std::string& msg) -{ - send("/error", "s", msg.c_str(), LO_ARGS_END); -} - -/** @page client_osc_namespace - * <h2>/put</h2> - * @arg @p path :: String - * @arg @p predicate :: URI String - * @arg @p value - * @arg @p ... - * - * @par - * PUT a set of properties to a path. - */ -void -OSCClientSender::put(const Raul::URI& path, - const Resource::Properties& properties, - Resource::Graph ctx) -{ - typedef Resource::Properties::const_iterator iterator; - lo_message m = lo_message_new(); - lo_message_add_string(m, path.c_str()); - for (iterator i = properties.begin(); i != properties.end(); ++i) { - lo_message_add_string(m, i->first.c_str()); - Raul::AtomLiblo::lo_message_add_atom(m, i->second); - } - send_message("/put", m); -} - -void -OSCClientSender::delta(const Raul::URI& path, - const Resource::Properties& remove, - const Resource::Properties& add) -{ - warn << "FIXME: OSC DELTA" << endl; -} - -/** @page client_osc_namespace - * <h2>/move</h2> - * @arg @p old-path :: String - * @arg @p new-path :: String - * - * @par - * MOVE an object to a new path. - * The new path will have the same parent as the old path. - */ -void -OSCClientSender::move(const Path& old_path, const Path& new_path) -{ - send("/move", "ss", old_path.c_str(), new_path.c_str(), LO_ARGS_END); -} - -/** @page client_osc_namespace - * <h2>/delete</h2> - * @arg @p path :: String - * - * @par - * DELETE an object. - */ -void -OSCClientSender::del(const URI& uri) -{ - send("/delete", "s", uri.c_str(), LO_ARGS_END); -} - -/** @page client_osc_namespace - * <h2>/connect</h2> - * @arg @p src-path :: String - * @arg @p dst-path :: String - * - * @par - * Notification a new connection has been made. - */ -void -OSCClientSender::connect(const Path& src_port_path, - const Path& dst_port_path) -{ - send("/connect", "ss", src_port_path.c_str(), dst_port_path.c_str(), LO_ARGS_END); -} - -/** @page client_osc_namespace - * <h2>/disconnect</h2> - * @arg @p src-path :: String - * @arg @p dst-path :: String - * - * @par - * Notification a connection has been unmade. - */ -void -OSCClientSender::disconnect(const URI& src, - const URI& dst) -{ - send("/disconnect", "ss", src.c_str(), dst.c_str(), LO_ARGS_END); -} - -/** @page client_osc_namespace - * <h2>/disconnect_all</h2> - * @arg @p parent-patch-path :: String - * @arg @p path :: String - * - * @par - * Notification all connections to an object have been disconnected. - */ -void -OSCClientSender::disconnect_all(const Raul::Path& parent_patch_path, - const Raul::Path& path) -{ - send("/disconnect_all", "ss", parent_patch_path.c_str(), path.c_str(), LO_ARGS_END); -} - -/** @page client_osc_namespace - * <h2>/set_property</h2> - * @arg @p path :: String - * @arg @p key :: URI String - * @arg @p value - * - * @par - * Notification of a property. - */ -void -OSCClientSender::set_property(const URI& path, - const URI& key, - const Atom& value) -{ - lo_message m = lo_message_new(); - lo_message_add_string(m, path.c_str()); - lo_message_add_string(m, key.c_str()); - AtomLiblo::lo_message_add_atom(m, value); - send_message("/set_property", m); -} - -/** @page client_osc_namespace - * <h2>/activity</h2> - * @arg @p path :: String - * - * @par - * Notification of "activity" (e.g. port message blinkenlights). - */ -void -OSCClientSender::activity(const Path& path) -{ - if (!_enabled) - return; - - lo_send(_address, "/activity", "s", path.c_str(), LO_ARGS_END); -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/OSCClientSender.hpp b/src/engine/OSCClientSender.hpp deleted file mode 100644 index 96263263..00000000 --- a/src/engine/OSCClientSender.hpp +++ /dev/null @@ -1,108 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_OSCCLIENTSENDER_HPP -#define INGEN_ENGINE_OSCCLIENTSENDER_HPP - -#include <cassert> -#include <string> -#include <lo/lo.h> -#include <pthread.h> -#include "ingen/ClientInterface.hpp" -#include "ingen/GraphObject.hpp" -#include "shared/OSCSender.hpp" - -namespace Ingen { - -class EngineInterface; - -namespace Engine { - - -/** Implements ClientInterface for OSC clients (sends OSC messages). - * - * \ingroup engine - */ -class OSCClientSender : public ClientInterface, - public Ingen::Shared::OSCSender -{ -public: - explicit OSCClientSender(const Raul::URI& url, - size_t max_packet_size) - : Shared::OSCSender(max_packet_size) - , _url(url) - { - _address = lo_address_new_from_url(url.c_str()); - } - - virtual ~OSCClientSender() - { lo_address_free(_address); } - - bool enabled() const { return _enabled; } - - void enable() { _enabled = true; } - void disable() { _enabled = false; } - - void bundle_begin() { OSCSender::bundle_begin(); } - void bundle_end() { OSCSender::bundle_end(); } - - Raul::URI uri() const { return _url; } - - /* *** ClientInterface Implementation Below *** */ - - void response_ok(int32_t id); - void response_error(int32_t id, const std::string& msg); - - void error(const std::string& msg); - - virtual void put(const Raul::URI& path, - const Resource::Properties& properties, - Resource::Graph ctx=Resource::DEFAULT); - - virtual void delta(const Raul::URI& path, - const Resource::Properties& remove, - const Resource::Properties& add); - - virtual void del(const Raul::URI& uri); - - virtual void move(const Raul::Path& old_path, - const Raul::Path& new_path); - - virtual void connect(const Raul::Path& src_port_path, - const Raul::Path& dst_port_path); - - virtual void disconnect(const Raul::URI& src, - const Raul::URI& dst); - - virtual void disconnect_all(const Raul::Path& parent_patch_path, - const Raul::Path& path); - - virtual void set_property(const Raul::URI& subject, - const Raul::URI& predicate, - const Raul::Atom& value); - - virtual void activity(const Raul::Path& path); - -private: - Raul::URI _url; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_OSCCLIENTSENDER_HPP - diff --git a/src/engine/OSCEngineReceiver.cpp b/src/engine/OSCEngineReceiver.cpp deleted file mode 100644 index fdb0bcc4..00000000 --- a/src/engine/OSCEngineReceiver.cpp +++ /dev/null @@ -1,586 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -//#define ENABLE_AVAHI 1 - -#include <stdlib.h> -#include <stdio.h> - -#include <string> - -#include <lo/lo.h> - -#include "raul/AtomLiblo.hpp" -#include "raul/Path.hpp" -#include "raul/SharedPtr.hpp" -#include "raul/log.hpp" - -#include "ingen-config.h" -#include "ingen/ClientInterface.hpp" - -#include "ClientBroadcaster.hpp" -#include "Engine.hpp" -#include "EventSource.hpp" -#include "OSCClientSender.hpp" -#include "OSCEngineReceiver.hpp" -#include "ThreadManager.hpp" - -#define LOG(s) s << "[OSCEngineReceiver] " - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -/** @page engine_osc_namespace Engine OSC Namespace Documentation - * - * <p>These are the commands the engine recognizes. A client can control every - * aspect of the engine entirely with these commands.</p> - * - * <p>All commands on this page are in the "control band". If a client needs to - * know about the state of the engine, it must listen to the "notification band". - * See the "Client OSC Namespace Documentation" for details.</p> - */ - -OSCEngineReceiver::OSCEngineReceiver(Engine& engine, size_t queue_size, uint16_t port) - : QueuedEngineInterface(engine, queue_size) // FIXME - , _server(NULL) -{ - _receive_thread = new ReceiveThread(*this); - - char port_str[6]; - snprintf(port_str, sizeof(port_str), "%u", port); - - _server = lo_server_new(port_str, error_cb); -#ifdef ENABLE_AVAHI - lo_server_avahi_init(_server, "ingen"); -#endif - - if (_server == NULL) { - LOG(error) << "Could not start OSC server. Aborting." << endl; - exit(EXIT_FAILURE); - } else { - char* lo_url = lo_server_get_url(_server); - LOG(info) << "Started OSC server at " << lo_url << endl; - free(lo_url); - } - -#ifdef RAUL_LOG_DEBUG - lo_server_add_method(_server, NULL, NULL, generic_cb, NULL); -#endif - - // Set response address for this message. - // It's important this is first and returns nonzero. - lo_server_add_method(_server, NULL, NULL, set_response_address_cb, this); - -#ifdef LIBLO_BUNDLES - lo_server_add_bundle_handlers(_server, bundle_start_cb, bundle_end_cb, this); -#endif - - // Commands - lo_server_add_method(_server, "/ping", "i", ping_cb, this); - lo_server_add_method(_server, "/ping_queued", "i", ping_slow_cb, this); - lo_server_add_method(_server, "/register_client", "i", register_client_cb, this); - lo_server_add_method(_server, "/unregister_client", "i", unregister_client_cb, this); - lo_server_add_method(_server, "/put", NULL, put_cb, this); - lo_server_add_method(_server, "/move", "iss", move_cb, this); - lo_server_add_method(_server, "/delete", "is", del_cb, this); - lo_server_add_method(_server, "/connect", "iss", connect_cb, this); - lo_server_add_method(_server, "/disconnect", "iss", disconnect_cb, this); - lo_server_add_method(_server, "/disconnect_all", "iss", disconnect_all_cb, this); - lo_server_add_method(_server, "/note_on", "isii", note_on_cb, this); - lo_server_add_method(_server, "/note_off", "isi", note_off_cb, this); - lo_server_add_method(_server, "/all_notes_off", "isi", all_notes_off_cb, this); - lo_server_add_method(_server, "/learn", "is", learn_cb, this); - lo_server_add_method(_server, "/set_property", NULL, set_property_cb, this); - - // Queries - lo_server_add_method(_server, "/request_property", "iss", request_property_cb, this); - lo_server_add_method(_server, "/get", "is", get_cb, this); - - lo_server_add_method(_server, NULL, NULL, unknown_cb, NULL); - - Thread::set_name("OSCEngineReceiver"); - start(); - _receive_thread->set_name("OSCEngineReceiver Listener"); - _receive_thread->start(); - _receive_thread->set_scheduling(SCHED_FIFO, 5); -} - -OSCEngineReceiver::~OSCEngineReceiver() -{ - _receive_thread->stop(); - stop(); - delete _receive_thread; - - if (_server != NULL) { -#ifdef ENABLE_AVAHI - lo_server_avahi_free(_server); -#endif - lo_server_free(_server); - _server = NULL; - } -} - -/** Override the semaphore driven _run method of QueuedEngineInterface - * to wait on OSC messages and prepare them right away in the same thread. - */ -void -OSCEngineReceiver::ReceiveThread::_run() -{ - Thread::get().set_context(THREAD_PRE_PROCESS); - - /* get a timestamp here and stamp all the events with the same time so - * they all get executed in the same cycle */ - - while (true) { - // Wait on a message and enqueue it - lo_server_recv(_receiver._server); - - // Enqueue every other message that is here "now" - // (would this provide truly atomic bundles?) - while (lo_server_recv_noblock(_receiver._server, 0) > 0) - if (_receiver.unprepared_events()) - _receiver.whip(); - - // No more unprepared events - } -} - -/** Create a new request for this message, if necessary. - * - * This is based on the fact that the current request is stored in a ref - * counted pointer, and events just take a reference to that. Thus, events - * may delete their request if we've since switched to a new one, or the - * same one can stay around and serve a series of events. - * Hooray for reference counting. - * - * If this message came from the same source as the last message, no allocation - * of requests or lo_addresses or any of it needs to be done. Unfortunately - * the only way to check is by comparing URLs, because liblo addresses suck. - * Lack of a fast liblo address comparison really sucks here, in any case. - */ -int -OSCEngineReceiver::set_response_address_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg, void* user_data) -{ - OSCEngineReceiver* const me = reinterpret_cast<OSCEngineReceiver*>(user_data); - - if (argc < 1 || types[0] != 'i') // Not a valid Ingen message - return 0; // Save liblo the trouble - - const int32_t id = argv[0]->i; - - const lo_address addr = lo_message_get_source(msg); - char* const url = lo_address_get_url(addr); - - const SharedPtr<Request> r = me->_request; - - /* Different address than last time, have to do a lookup */ - if (!r || !r->client() || strcmp(url, r->client()->uri().c_str())) { - ClientInterface* client = me->_engine.broadcaster()->client(url); - if (client) - me->_request = SharedPtr<Request>(new Request(me, client, id)); - else - me->_request = SharedPtr<Request>(new Request(me)); - } - - if (id != -1) { - me->set_next_response_id(id); - } else { - me->disable_responses(); - } - - free(url); - - // If this returns 0 no OSC commands will work - return 1; -} - -#ifdef LIBLO_BUNDLES -int -OSCEngineReceiver::_bundle_start_cb(lo_timetag time) -{ - info << "BUNDLE START" << endl; - return 0; -} - -int -OSCEngineReceiver::_bundle_end_cb() -{ - info << "BUNDLE END" << endl; - return 0; -} -#endif - -void -OSCEngineReceiver::error_cb(int num, const char* msg, const char* path) -{ - error << "liblo server error" << num; - if (path) { - error << " for path `" << path << "'"; - } - error << " (" << msg << ")" << endl; -} - -/** @page engine_osc_namespace - * <h2>/ping</h2> - * @arg @p response-id :: Integer - */ -int -OSCEngineReceiver::_ping_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - const lo_address addr = lo_message_get_source(msg); - if (lo_send(addr, "/ok", "i", argv[0]->i) < 0) - warn << "Unable to send response (" << lo_address_errstr(addr) << ")" << endl; - return 0; -} - -/** @page engine_osc_namespace - * <h2>/ping_queued</h2> - * @arg @p response-id :: Integer - * - * @par - * Reply to sender with a successful response after going through the - * event queue. This is useful for checking if the engine is actually active, - * or for sending after several events as a sentinel and wait on it's response, - * to know when all previous events have finished processing. - */ -int -OSCEngineReceiver::_ping_slow_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - ping(); - return 0; -} - -/** @page engine_osc_namespace - * <h2>/register_client</h2> - * @arg @p response-id :: Integer - * - * @par - * Register a new client with the engine. The incoming address will be - * used for the new registered client. - */ -int -OSCEngineReceiver::_register_client_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - lo_address addr = lo_message_get_source(msg); - - char* const url = lo_address_get_url(addr); - ClientInterface* client = new OSCClientSender( - (const char*)url, - _engine.world()->conf()->option("packet-size").get_int32()); - register_client(client); - free(url); - - return 0; -} - -/** @page engine_osc_namespace - * <h2>/unregister_client</h2> - * @arg @p response-id :: Integer - * - * @par - * Unregister a client. - */ -int -OSCEngineReceiver::_unregister_client_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - lo_address addr = lo_message_get_source(msg); - - char* url = lo_address_get_url(addr); - unregister_client(url); - free(url); - - return 0; -} - -/** @page engine_osc_namespace - * <h2>/get</h2> - * @arg @p response-id :: Integer - * @arg @p uri :: URI String - * - * @par - * Request all properties of an object. - */ -int -OSCEngineReceiver::_get_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - get(&argv[1]->s); - return 0; -} - -/** @page engine_osc_namespace - * <h2>/put</h2> - * @arg @p response-id :: Integer - * @arg @p path :: String - * @arg @p predicate :: URI String - * @arg @p value - * @arg @p ... - * - * @par - * PUT a set of properties to a path. - */ -int -OSCEngineReceiver::_put_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - const char* obj_path = &argv[1]->s; - Resource::Properties prop; - for (int i = 2; i < argc-1; i += 2) - prop.insert(make_pair(&argv[i]->s, AtomLiblo::lo_arg_to_atom(types[i+1], argv[i+1]))); - put(obj_path, prop); - return 0; -} - -/** @page engine_osc_namespace - * <h2>/move</h2> - * @arg @p response-id :: Integer - * @arg @p old-path :: String - * @arg @p new-path :: String - * - * @par - * MOVE an object to a new path. - */ -int -OSCEngineReceiver::_move_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - const char* old_path = &argv[1]->s; - const char* new_path = &argv[2]->s; - - move(old_path, new_path); - return 0; -} - -/** @page engine_osc_namespace - * <h2>/delete</h2> - * @arg @p response-id :: Integer - * @arg @p path :: String - * - * @par - * DELETE an object. - */ -int -OSCEngineReceiver::_del_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - const char* uri = &argv[1]->s; - - del(uri); - return 0; -} - -/** @page engine_osc_namespace - * <h2>/connect</h2> - * @arg @p response-id :: Integer - * @arg @p src-port-path :: String - * @arg @p dst-port-path :: String - * - * @par - * Connect two ports (which must be in the same patch). - */ -int -OSCEngineReceiver::_connect_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - const char* src_port_path = &argv[1]->s; - const char* dst_port_path = &argv[2]->s; - - connect(src_port_path, dst_port_path); - return 0; -} - -/** @page engine_osc_namespace - * <h2>/disconnect</h2> - * @arg @p response-id :: Integer - * @arg @p src-port-path :: String - * @arg @p dst-port-path :: String - * - * @par - * Disconnect two ports. - */ -int -OSCEngineReceiver::_disconnect_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - const char* src_port_path = &argv[1]->s; - const char* dst_port_path = &argv[2]->s; - - disconnect(src_port_path, dst_port_path); - return 0; -} - -/** @page engine_osc_namespace - * <h2>/disconnect_all</h2> - * @arg @p response-id :: Integer - * @arg @p patch-path :: String - * @arg @p object-path :: String - * - * @par - * Disconnect all connections to/from a node/port. - */ -int -OSCEngineReceiver::_disconnect_all_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - const char* patch_path = &argv[1]->s; - const char* object_path = &argv[2]->s; - - disconnect_all(patch_path, object_path); - return 0; -} - -/** @page engine_osc_namespace - * <h2>/note_on</h2> - * @arg @p response-id :: Integer - * @arg @p node-path :: String - * @arg @p note-num (int) - * @arg @p velocity (int) - * - * @par - * Trigger a note-on, just as if it came from MIDI. - */ -int -OSCEngineReceiver::_note_on_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - /* - const char* node_path = &argv[1]->s; - const uint8_t note_num = argv[2]->i; - const uint8_t velocity = argv[3]->i; - */ - warn << "TODO: OSC note on" << endl; - //note_on(node_path, note_num, velocity); - return 0; -} - -/** @page engine_osc_namespace - * <h2>/note_off</h2> - * @arg @p response-id :: Integer - * @arg @p node-path :: String - * @arg @p note-num :: Integer - * - * @par - * Trigger a note-off, just as if it came from MIDI. - */ -int -OSCEngineReceiver::_note_off_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - /* - const char* patch_path = &argv[1]->s; - const uint8_t note_num = argv[2]->i; - */ - warn << "TODO: OSC note off" << endl; - //note_off(patch_path, note_num); - return 0; -} - -/** @page engine_osc_namespace - * <h2>/all_notes_off</h2> - * @arg @p response-id :: Integer - * @arg @p patch-path :: String - * - * @par - * Trigger a note-off for all voices, just as if it came from MIDI. - */ -int -OSCEngineReceiver::_all_notes_off_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - /* - - const char* patch_path = &argv[1]->s; - */ - warn << "TODO: OSC all notes off" << endl; - //all_notes_off(patch_path); - return 0; -} - -/** @page engine_osc_namespace - * <h2>/set_property</h2> - * @arg @p response-id :: Integer - * @arg @p uri :: URI String - * @arg @p key :: URI String - * @arg @p value :: String - * - * @par - * Set a property on a graph object. - */ -int -OSCEngineReceiver::_set_property_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - if (argc != 4 || types[0] != 'i' || types[1] != 's' || types[2] != 's') - return 1; - - const char* object_path = &argv[1]->s; - const char* key = &argv[2]->s; - - Raul::Atom value = Raul::AtomLiblo::lo_arg_to_atom(types[3], argv[3]); - - set_property(object_path, key, value); - return 0; -} - -/** @page engine_osc_namespace - * <h2>/request_property</h2> - * @arg @p response-id :: Integer - * @arg @p uri :: URI String - * @arg @p key :: URI String - * - * Request the value of a property on an object. - */ -int -OSCEngineReceiver::_request_property_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - const char* object_path = &argv[1]->s; - const char* key = &argv[2]->s; - - request_property(object_path, key); - return 0; -} - -// Static Callbacks // - - -// Display incoming OSC messages (for debugging purposes) -int -OSCEngineReceiver::generic_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg, void* user_data) -{ - printf("[OSCEngineReceiver] %s (%s)\t", path, types); - - for (int i=0; i < argc; ++i) { - lo_arg_pp(lo_type(types[i]), argv[i]); - printf("\t"); - } - printf("\n"); - - return 1; // not handled -} - -int -OSCEngineReceiver::unknown_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg, void* user_data) -{ - const lo_address addr = lo_message_get_source(msg); - char* const url = lo_address_get_url(addr); - - warn << "Unknown OSC command " << path << " (" << types << ") " - << "received from " << url << endl; - - string error_msg = "Unknown command: "; - error_msg.append(path).append(" ").append(types); - - lo_send(addr, "/error", "s", error_msg.c_str(), LO_ARGS_END); - free(url); - - return 0; -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/OSCEngineReceiver.hpp b/src/engine/OSCEngineReceiver.hpp deleted file mode 100644 index 4293f890..00000000 --- a/src/engine/OSCEngineReceiver.hpp +++ /dev/null @@ -1,118 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_OSCENGINERECEIVER_HPP -#define INGEN_ENGINE_OSCENGINERECEIVER_HPP - -#include <stdint.h> -#include <lo/lo.h> -#include "QueuedEngineInterface.hpp" -#include "Request.hpp" -#include "ingen-config.h" - -namespace Ingen { -namespace Engine { - -class JackDriver; -class NodeFactory; -class PatchImpl; - -/* Some boilerplate killing macros... */ -#define LO_HANDLER_ARGS const char* path, const char* types, lo_arg** argv, int argc, lo_message msg - -/* Defines a static handler to be passed to lo_add_method, which is a trivial - * wrapper around a non-static method that does the real work. Makes a whoole - * lot of ugly boiler plate go away */ -#define LO_HANDLER(name) \ -int _##name##_cb (LO_HANDLER_ARGS);\ -inline static int name##_cb(LO_HANDLER_ARGS, void* myself)\ -{ return ((OSCEngineReceiver*)myself)->_##name##_cb(path, types, argv, argc, msg); } - -/* FIXME: Make this receive and preprocess in the same thread? */ - -/** Receives OSC messages from liblo. - * - * This inherits from QueuedEngineInterface and calls it's own functions - * via OSC. It's not actually a directly callable EngineInterface (it's - * callable via OSC...) so it should be implemented-as-a (privately inherit) - * QueuedEngineInterface, but it needs to be public so it's an EventSource - * the Driver can use. This probably should be fixed somehow.. - * - * \ingroup engine - */ -class OSCEngineReceiver : public QueuedEngineInterface -{ -public: - OSCEngineReceiver(Engine& engine, size_t queue_size, uint16_t port); - ~OSCEngineReceiver(); - -private: - struct ReceiveThread : public Raul::Thread { - explicit ReceiveThread(OSCEngineReceiver& receiver) : _receiver(receiver) {} - virtual void _run(); - private: - OSCEngineReceiver& _receiver; - }; - - friend class ReceiveThread; - - ReceiveThread* _receive_thread; - -#ifdef LIBLO_BUNDLES - static int bundle_start_cb(lo_timetag time, void* myself) { - return ((OSCEngineReceiver*)myself)->_bundle_start_cb(time); - } - static int bundle_end_cb(void* myself) { - return ((OSCEngineReceiver*)myself)->_bundle_end_cb(); - } - - int _bundle_start_cb(lo_timetag time); - int _bundle_end_cb(); -#endif - - static void error_cb(int num, const char* msg, const char* path); - static int set_response_address_cb(LO_HANDLER_ARGS, void* myself); - static int generic_cb(LO_HANDLER_ARGS, void* myself); - static int unknown_cb(LO_HANDLER_ARGS, void* myself); - - LO_HANDLER(quit); - LO_HANDLER(ping); - LO_HANDLER(ping_slow); - LO_HANDLER(register_client); - LO_HANDLER(unregister_client); - LO_HANDLER(get); - LO_HANDLER(put); - LO_HANDLER(move); - LO_HANDLER(del); - LO_HANDLER(connect); - LO_HANDLER(disconnect); - LO_HANDLER(disconnect_all); - LO_HANDLER(note_on); - LO_HANDLER(note_off); - LO_HANDLER(all_notes_off); - LO_HANDLER(learn); - LO_HANDLER(set_property); - LO_HANDLER(property_set); - LO_HANDLER(request_property); - - lo_server _server; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_OSCENGINERECEIVER_HPP diff --git a/src/engine/ObjectBuffer.cpp b/src/engine/ObjectBuffer.cpp deleted file mode 100644 index ba0b0c7f..00000000 --- a/src/engine/ObjectBuffer.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2009-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define __STDC_LIMIT_MACROS 1 -#include <string.h> -#include <stdint.h> -#include <algorithm> -#include "raul/log.hpp" -#include "lv2/lv2plug.in/ns/ext/uri-map/uri-map.h" -#include "ingen-config.h" -#include "shared/LV2Features.hpp" -#include "shared/LV2URIMap.hpp" -#include "ObjectBuffer.hpp" -#include "Engine.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -/** Allocate a new object buffer. - * \a capacity is in bytes, including LV2_Atom header - */ -ObjectBuffer::ObjectBuffer(BufferFactory& bufs, size_t capacity) - : Buffer(bufs, PortType(PortType::VALUE), capacity) -{ - capacity += sizeof(LV2_Atom); - -#ifdef HAVE_POSIX_MEMALIGN - const int ret = posix_memalign((void**)&_buf, 16, capacity); -#else - _buf = (LV2_Atom*)malloc(capacity); - const int ret = (_buf != NULL) ? 0 : -1; -#endif - - if (ret != 0) { - error << "Failed to allocate object buffer. Aborting." << endl; - exit(EXIT_FAILURE); - } - - clear(); -} - -ObjectBuffer::~ObjectBuffer() -{ - free(_buf); -} - -void -ObjectBuffer::clear() -{ - // null - _buf->type = 0; - _buf->size = 0; -} - -void -ObjectBuffer::copy(Context& context, const Buffer* src_buf) -{ - const ObjectBuffer* src = dynamic_cast<const ObjectBuffer*>(src_buf); - if (!src || src == this || src->_buf == _buf) - return; - - // Copy only if src is a POD object that fits - if (src->_buf->type != 0 && src_buf->size() <= size()) - memcpy(_buf, src->_buf, sizeof(LV2_Atom) + src_buf->size()); -} - -void -ObjectBuffer::resize(size_t size) -{ - const uint32_t contents_size = sizeof(LV2_Atom) + _buf->size; - - _buf = (LV2_Atom*)realloc(_buf, sizeof(LV2_Atom) + size); - _size = size + sizeof(LV2_Atom); - - // If we shrunk and chopped the current contents, clear corrupt data - if (size < contents_size) - clear(); -} - -void* -ObjectBuffer::port_data(PortType port_type, SampleCount offset) -{ - switch (port_type.symbol()) { - case PortType::CONTROL: - case PortType::AUDIO: - switch (_type.symbol()) { - case PortType::CONTROL: - return (float*)atom()->body; - case PortType::AUDIO: - return (float*)((LV2_Atom_Vector*)atom()->body)->elems + offset; - default: - warn << "Audio data requested from non-audio buffer" << endl; - return NULL; - } - break; - default: - return _buf; - } -} - -const void* -ObjectBuffer::port_data(PortType port_type, SampleCount offset) const -{ - switch (port_type.symbol()) { - case PortType::CONTROL: - case PortType::AUDIO: - switch (_type.symbol()) { - case PortType::CONTROL: - return (float*)atom()->body; - case PortType::AUDIO: - return (float*)((LV2_Atom_Vector*)atom()->body)->elems + offset; - default: - warn << "Audio data requested from non-audio buffer" << endl; - return NULL; - } - break; - default: - return _buf; - } -} - -void -ObjectBuffer::prepare_write(Context& context) -{ - _buf->size = _size - sizeof(LV2_Atom); -} - -} // namespace Engine -} // namespace Ingen - diff --git a/src/engine/ObjectBuffer.hpp b/src/engine/ObjectBuffer.hpp deleted file mode 100644 index fe75bd71..00000000 --- a/src/engine/ObjectBuffer.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2009-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_OBJECTBUFFER_HPP -#define INGEN_ENGINE_OBJECTBUFFER_HPP - -#include "lv2/lv2plug.in/ns/ext/atom/atom.h" -#include "ingen/PortType.hpp" -#include "Buffer.hpp" - -namespace Ingen { -namespace Engine { - -class Context; - -class ObjectBuffer : public Buffer { -public: - ObjectBuffer(BufferFactory& bufs, size_t capacity); - ~ObjectBuffer(); - - void clear(); - - void* port_data(PortType port_type, SampleCount offset); - const void* port_data(PortType port_type, SampleCount offset) const; - - void prepare_write(Context& context); - - void copy(Context& context, const Buffer* src); - - void resize(size_t size); - - LV2_Atom* atom() { return _buf; } - const LV2_Atom* atom() const { return _buf; } - -private: - LV2_Atom* _buf; ///< Contents -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_OBJECTBUFFER_HPP diff --git a/src/engine/ObjectSender.cpp b/src/engine/ObjectSender.cpp deleted file mode 100644 index 77b6c5e3..00000000 --- a/src/engine/ObjectSender.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "ObjectSender.hpp" -#include "ingen/ClientInterface.hpp" -#include "shared/LV2URIMap.hpp" -#include "EngineStore.hpp" -#include "PatchImpl.hpp" -#include "NodeImpl.hpp" -#include "PortImpl.hpp" -#include "ConnectionImpl.hpp" -#include "NodeFactory.hpp" -#include "ingen/PortType.hpp" -#include "AudioBuffer.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -void -ObjectSender::send_object(ClientInterface* client, - const GraphObjectImpl* object, - bool recursive) -{ - const PatchImpl* patch = dynamic_cast<const PatchImpl*>(object); - if (patch) { - send_patch(client, patch, recursive); - return; - } - - const NodeImpl* node = dynamic_cast<const NodeImpl*>(object); - if (node) { - send_node(client, node, recursive); - return; - } - - const PortImpl* port = dynamic_cast<const PortImpl*>(object); - if (port) { - send_port(client, port); - return; - } -} - -void -ObjectSender::send_patch(ClientInterface* client, const PatchImpl* patch, bool recursive, bool bundle) -{ - if (bundle) - client->bundle_begin(); - - client->put(patch->path(), - patch->properties(Resource::INTERNAL), - Resource::INTERNAL); - - client->put(patch->path(), - patch->properties(Resource::EXTERNAL), - Resource::EXTERNAL); - - if (recursive) { - // Send nodes - for (List<NodeImpl*>::const_iterator j = patch->nodes().begin(); - j != patch->nodes().end(); ++j) { - const NodeImpl* const node = (*j); - send_node(client, node, true, false); - } - - // Send ports - for (uint32_t i=0; i < patch->num_ports(); ++i) { - PortImpl* const port = patch->port_impl(i); - send_port(client, port, false); - } - - // Send connections - for (PatchImpl::Connections::const_iterator j = patch->connections().begin(); - j != patch->connections().end(); ++j) - client->connect(j->second->src_port_path(), j->second->dst_port_path()); - } - - if (bundle) - client->bundle_end(); -} - -/** Sends a node or a patch */ -void -ObjectSender::send_node(ClientInterface* client, const NodeImpl* node, bool recursive, bool bundle) -{ - PluginImpl* const plugin = node->plugin_impl(); - - if (plugin->type() == Plugin::Patch) { - send_patch(client, (PatchImpl*)node, recursive); - return; - } - - if (plugin->uri().length() == 0) { - error << "Node " << node->path() << "'s plugin has no URI! Not sending." << endl; - return; - } - - if (bundle) - client->bundle_begin(); - - client->put(node->path(), node->properties()); - - if (recursive) { - // Send ports - for (size_t j=0; j < node->num_ports(); ++j) - send_port(client, node->port_impl(j), false); - } - - if (bundle) - client->bundle_end(); -} - -void -ObjectSender::send_port(ClientInterface* client, const PortImpl* port, bool bundle) -{ - assert(port); - - if (bundle) - client->bundle_begin(); - - client->put(port->path(), port->properties()); - - // Send control value - if (port->is_a(PortType::CONTROL)) - client->set_property(port->path(), port->bufs().uris().ingen_value, port->value()); - - if (bundle) - client->bundle_end(); -} - -} // namespace Engine -} // namespace Ingen - diff --git a/src/engine/ObjectSender.hpp b/src/engine/ObjectSender.hpp deleted file mode 100644 index 21f0e928..00000000 --- a/src/engine/ObjectSender.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_OBJECTSENDER_HPP -#define INGEN_ENGINE_OBJECTSENDER_HPP - -namespace Ingen { - -class ClientInterface; - -namespace Engine { - -class GraphObjectImpl; -class PatchImpl; -class NodeImpl; -class PortImpl; -class PluginImpl; - -/** Utility class for sending GraphObjects to clients through ClientInterface. - * - * While ClientInterface is the direct low level message-based interface - * (protocol), this is used from the engine to easily send proper Objects - * with these messages (which is done in a few different parts of the code). - * - * Basically a serialiser, except to calls on ClientInterface rather than - * eg a byte stream. - */ -class ObjectSender { -public: - static void send_object(ClientInterface* client, - const GraphObjectImpl* object, - bool recursive); - -private: - static void send_patch(ClientInterface* client, - const PatchImpl* patch, - bool recursive, - bool bundle=true); - static void send_node(ClientInterface* client, - const NodeImpl* node, - bool recursive, - bool bundle=true); - static void send_port(ClientInterface* client, - const PortImpl* port, - bool bundle=true); -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_OBJECTSENDER_HPP - diff --git a/src/engine/OutputPort.cpp b/src/engine/OutputPort.cpp deleted file mode 100644 index 0a16d2db..00000000 --- a/src/engine/OutputPort.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "ingen/Patch.hpp" -#include "shared/LV2URIMap.hpp" -#include "Buffer.hpp" -#include "NodeImpl.hpp" -#include "OutputPort.hpp" -#include "ProcessContext.hpp" - -using namespace std; - -namespace Ingen { -namespace Engine { - -OutputPort::OutputPort(BufferFactory& bufs, - NodeImpl* parent, - const Raul::Symbol& symbol, - uint32_t index, - uint32_t poly, - PortType type, - const Raul::Atom& value, - size_t buffer_size) - : PortImpl(bufs, parent, symbol, index, poly, type, value, buffer_size) -{ - if (!dynamic_cast<Patch*>(parent)) - add_property(bufs.uris().rdf_type, bufs.uris().lv2_OutputPort); - - if (type == PortType::CONTROL) - _broadcast = true; - - setup_buffers(bufs, poly); -} - -bool -OutputPort::get_buffers(BufferFactory& bufs, Raul::Array<BufferFactory::Ref>* buffers, uint32_t poly) -{ - for (uint32_t v = 0; v < poly; ++v) - buffers->at(v) = bufs.get(buffer_type(), _buffer_size); - - return true; -} - -void -OutputPort::pre_process(Context& context) -{ - for (uint32_t v = 0; v < _poly; ++v) - _buffers->at(v)->prepare_write(context); -} - -void -OutputPort::post_process(Context& context) -{ - for (uint32_t v = 0; v < _poly; ++v) - _buffers->at(v)->prepare_read(context); - - if (_broadcast) - broadcast_value(context, false); -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/OutputPort.hpp b/src/engine/OutputPort.hpp deleted file mode 100644 index c82de111..00000000 --- a/src/engine/OutputPort.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_OUTPUTPORT_HPP -#define INGEN_ENGINE_OUTPUTPORT_HPP - -#include <string> -#include <cstdlib> -#include "PortImpl.hpp" - -namespace Ingen { -namespace Engine { - -/** An output port. - * - * Output ports always have a locally allocated buffer, and buffer() will - * always return that buffer. (This is very different from InputPort) - * - * This class actually adds no functionality to Port whatsoever right now, - * it will in the future when more advanced port types exist, and it makes - * things clearer throughout the engine. - * - * \ingroup engine - */ -class OutputPort : virtual public PortImpl -{ -public: - OutputPort(BufferFactory& bufs, - NodeImpl* parent, - const Raul::Symbol& symbol, - uint32_t index, - uint32_t poly, - PortType type, - const Raul::Atom& value, - size_t buffer_size=0); - - bool get_buffers(BufferFactory& bufs, Raul::Array<BufferFactory::Ref>* buffers, uint32_t poly); - - void pre_process(Context& context); - void post_process(Context& context); - - virtual ~OutputPort() {} - - bool is_input() const { return false; } - bool is_output() const { return true; } -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_OUTPUTPORT_HPP diff --git a/src/engine/PatchImpl.cpp b/src/engine/PatchImpl.cpp deleted file mode 100644 index 86693686..00000000 --- a/src/engine/PatchImpl.cpp +++ /dev/null @@ -1,470 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <cassert> -#include <cmath> -#include <string> -#include "raul/log.hpp" -#include "shared/World.hpp" -#include "shared/LV2URIMap.hpp" -#include "ThreadManager.hpp" -#include "NodeImpl.hpp" -#include "PatchImpl.hpp" -#include "PatchPlugin.hpp" -#include "PortImpl.hpp" -#include "ConnectionImpl.hpp" -#include "DuplexPort.hpp" -#include "Engine.hpp" -#include "ProcessSlave.hpp" -#include "Driver.hpp" -#include "ingen-config.h" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -PatchImpl::PatchImpl(Engine& engine, - const Raul::Symbol& symbol, - uint32_t poly, - PatchImpl* parent, - SampleRate srate, - uint32_t internal_poly) - : NodeImpl(new PatchPlugin(*engine.world()->uris().get(), - engine.world()->uris()->ingen_Patch.c_str(), "patch", "Ingen Patch"), - symbol, poly, parent, srate) - , _engine(engine) - , _internal_poly(internal_poly) - , _compiled_patch(NULL) - , _process(false) -{ - assert(internal_poly >= 1); -} - -PatchImpl::~PatchImpl() -{ - assert(!_activated); - - delete _compiled_patch; - delete _plugin; -} - -void -PatchImpl::activate(BufferFactory& bufs) -{ - NodeImpl::activate(bufs); - - for (List<NodeImpl*>::iterator i = _nodes.begin(); i != _nodes.end(); ++i) - (*i)->activate(bufs); - - assert(_activated); -} - -void -PatchImpl::deactivate() -{ - if (_activated) { - NodeImpl::deactivate(); - - for (List<NodeImpl*>::iterator i = _nodes.begin(); i != _nodes.end(); ++i) { - if ((*i)->activated()) - (*i)->deactivate(); - assert(!(*i)->activated()); - } - } - assert(!_activated); -} - -void -PatchImpl::disable() -{ - ThreadManager::assert_thread(THREAD_PROCESS); - - _process = false; - - for (List<PortImpl*>::iterator i = _output_ports.begin(); i != _output_ports.end(); ++i) - if ((*i)->context() == Context::AUDIO) - (*i)->clear_buffers(); -} - -bool -PatchImpl::prepare_internal_poly(BufferFactory& bufs, uint32_t poly) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - - // TODO: Subpatch dynamic polyphony (i.e. changing port polyphony) - - for (List<NodeImpl*>::iterator i = _nodes.begin(); i != _nodes.end(); ++i) - (*i)->prepare_poly(bufs, poly); - - for (List<NodeImpl*>::iterator i = _nodes.begin(); i != _nodes.end(); ++i) - for (uint32_t j = 0; j < (*i)->num_ports(); ++j) - (*i)->port_impl(j)->prepare_poly_buffers(bufs); - - return true; -} - -bool -PatchImpl::apply_internal_poly(ProcessContext& context, BufferFactory& bufs, Raul::Maid& maid, uint32_t poly) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - - // TODO: Subpatch dynamic polyphony (i.e. changing port polyphony) - - for (List<NodeImpl*>::iterator i = _nodes.begin(); i != _nodes.end(); ++i) - (*i)->apply_poly(maid, poly); - - for (List<NodeImpl*>::iterator i = _nodes.begin(); i != _nodes.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<InputPort*>(port)->direct_connect()) - port->setup_buffers(bufs, port->poly()); - port->connect_buffers(context.offset()); - } - } - - const bool polyphonic = parent_patch() && (poly == parent_patch()->internal_poly()); - for (List<PortImpl*>::iterator i = _output_ports.begin(); i != _output_ports.end(); ++i) - (*i)->setup_buffers(bufs, polyphonic ? poly : 1); - - _internal_poly = poly; - - return true; -} - -/** Run the patch for the specified number of frames. - * - * Calls all Nodes in (roughly, if parallel) the order _compiled_patch specifies. - */ -void -PatchImpl::process(ProcessContext& context) -{ - if (!_process) - return; - - NodeImpl::pre_process(context); - - // Run all nodes - if (_compiled_patch && _compiled_patch->size() > 0) { - if (context.slaves().size() > 0) { - process_parallel(context); - } else { - process_single(context); - } - } - - // Queue any cross-context connections - for (CompiledPatch::QueuedConnections::iterator i = _compiled_patch->queued_connections.begin(); - i != _compiled_patch->queued_connections.end(); ++i) { - (*i)->queue(context); - } - - NodeImpl::post_process(context); -} - -void -PatchImpl::process_parallel(ProcessContext& context) -{ - size_t n_slaves = context.slaves().size(); - - CompiledPatch* const cp = _compiled_patch; - - /* Start p-1 slaves */ - - if (n_slaves >= cp->size()) - n_slaves = cp->size()-1; - - if (n_slaves > 0) { - for (size_t i = 0; i < cp->size(); ++i) - (*cp)[i].node()->reset_input_ready(); - - for (size_t i = 0; i < n_slaves; ++i) - context.slaves()[i]->whip(cp, i+1, context); - } - - /* Process ourself until everything is done - * This is analogous to ProcessSlave::_whipped(), but this is the master - * (i.e. what the main Jack process thread calls). Where ProcessSlave - * waits on input, this just skips the node and tries the next, to avoid - * waiting in the Jack thread which pisses Jack off. - */ - - size_t index = 0; - size_t num_finished = 0; // Number of consecutive finished nodes hit - - while (num_finished < cp->size()) { - CompiledNode& n = (*cp)[index]; - - if (n.node()->process_lock()) { - if (n.node()->n_inputs_ready() == n.n_providers()) { - n.node()->process(context); - - /* Signal dependants their input is ready */ - for (uint32_t i = 0; i < n.dependants().size(); ++i) - n.dependants()[i]->signal_input_ready(); - - ++num_finished; - } else { - n.node()->process_unlock(); - num_finished = 0; - } - } else { - if (n.node()->n_inputs_ready() == n.n_providers()) - ++num_finished; - else - num_finished = 0; - } - - index = (index + 1) % cp->size(); - } - - /* Tell slaves we're done in case we beat them, and pray they're - * really done by the start of next cycle. - * FIXME: This probably breaks (race) at extremely small nframes where - * ingen is the majority of the DSP load. - */ - for (uint32_t i = 0; i < n_slaves; ++i) - context.slaves()[i]->finish(); -} - -void -PatchImpl::process_single(ProcessContext& context) -{ - for (size_t i = 0; i < _compiled_patch->size(); ++i) - (*_compiled_patch)[i].node()->process(context); -} - -void -PatchImpl::set_buffer_size(Context& context, BufferFactory& bufs, PortType type, size_t size) -{ - NodeImpl::set_buffer_size(context, bufs, type, size); - - for (size_t i = 0; i < _compiled_patch->size(); ++i) - (*_compiled_patch)[i].node()->set_buffer_size(context, bufs, type, size); -} - -// Patch specific stuff - -/** Add a node. - * Preprocessing thread only. - */ -void -PatchImpl::add_node(List<NodeImpl*>::Node* ln) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - assert(ln != NULL); - assert(ln->elem() != NULL); - assert(ln->elem()->parent_patch() == this); - //assert(ln->elem()->polyphony() == _internal_poly); - - _nodes.push_back(ln); -} - -/** Remove a node. - * Preprocessing thread only. - */ -PatchImpl::Nodes::Node* -PatchImpl::remove_node(const Raul::Symbol& symbol) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - for (List<NodeImpl*>::iterator i = _nodes.begin(); i != _nodes.end(); ++i) - if ((*i)->symbol() == symbol) - return _nodes.erase(i); - - return NULL; -} - -void -PatchImpl::add_connection(SharedPtr<ConnectionImpl> c) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - _connections.insert(make_pair(make_pair(c->src_port(), c->dst_port()), c)); -} - -/** Remove a connection. - * Preprocessing thread only. - */ -SharedPtr<ConnectionImpl> -PatchImpl::remove_connection(const PortImpl* src_port, const PortImpl* dst_port) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - Connections::iterator i = _connections.find(make_pair(src_port, dst_port)); - if (i != _connections.end()) { - SharedPtr<ConnectionImpl> c = PtrCast<ConnectionImpl>(i->second); - _connections.erase(i); - return c; - } else { - error << "[PatchImpl::remove_connection] Connection not found" << endl; - return SharedPtr<ConnectionImpl>(); - } -} - -bool -PatchImpl::has_connection(const PortImpl* src_port, const PortImpl* dst_port) const -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - Connections::const_iterator i = _connections.find(make_pair(src_port, dst_port)); - return (i != _connections.end()); -} - -uint32_t -PatchImpl::num_ports() const -{ - if (ThreadManager::thread_is(THREAD_PROCESS)) - return NodeImpl::num_ports(); - else - return _input_ports.size() + _output_ports.size(); -} - -/** Create a port. Not realtime safe. - */ -PortImpl* -PatchImpl::create_port(BufferFactory& bufs, const string& name, PortType type, size_t buffer_size, bool is_output, bool polyphonic) -{ - if (type == PortType::UNKNOWN) { - error << "[PatchImpl::create_port] Unknown port type " << type.uri() << endl; - return NULL; - } - - assert( !(type == PortType::UNKNOWN) ); - - return new DuplexPort(bufs, this, name, num_ports(), polyphonic, _polyphony, - type, Raul::Atom(), buffer_size, is_output); -} - -/** Remove port from ports list used in pre-processing thread. - * - * Port is not removed from ports array for process thread (which could be - * simultaneously running). - * - * Realtime safe. Preprocessing thread only. - */ -List<PortImpl*>::Node* -PatchImpl::remove_port(const string& symbol) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - - bool found = false; - List<PortImpl*>::Node* ret = NULL; - for (List<PortImpl*>::iterator i = _input_ports.begin(); i != _input_ports.end(); ++i) { - if ((*i)->symbol() == symbol) { - ret = _input_ports.erase(i); - found = true; - break; - } - } - - if (!found) - for (List<PortImpl*>::iterator i = _output_ports.begin(); i != _output_ports.end(); ++i) { - if ((*i)->symbol() == symbol) { - ret = _output_ports.erase(i); - found = true; - break; - } - } - - if ( ! found) - error << "[PatchImpl::remove_port] Port not found!" << endl; - - return ret; -} - -/** Remove all ports from ports list used in pre-processing thread. - * - * Ports are not removed from ports array for process thread (which could be - * simultaneously running). Returned is a (inputs, outputs) pair. - * - * Realtime safe. Preprocessing thread only. - */ -void -PatchImpl::clear_ports() -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - - _input_ports.clear(); - _output_ports.clear(); -} - -Raul::Array<PortImpl*>* -PatchImpl::build_ports_array() const -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - - Raul::Array<PortImpl*>* const result = new Raul::Array<PortImpl*>(_input_ports.size() + _output_ports.size()); - - size_t i = 0; - - for (List<PortImpl*>::const_iterator p = _input_ports.begin(); p != _input_ports.end(); ++p,++i) - result->at(i) = *p; - - for (List<PortImpl*>::const_iterator p = _output_ports.begin(); p != _output_ports.end(); ++p,++i) - result->at(i) = *p; - - return result; -} - -/** Find the process order for this Patch. - * - * The process order is a flat list that the patch will execute in order - * when it's run() method is called. Return value is a newly allocated list - * which the caller is reponsible to delete. Note that this function does - * NOT actually set the process order, it is returned so it can be inserted - * at the beginning of an audio cycle (by various Events). - * - * Not realtime safe. - */ -CompiledPatch* -PatchImpl::compile() const -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - - CompiledPatch* const compiled_patch = new CompiledPatch();//_nodes.size()); - - for (Nodes::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i) - (*i)->traversed(false); - - for (Nodes::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i) { - NodeImpl* const node = (*i); - // Either a sink or connected to our output ports: - if ( ( ! node->traversed()) && node->dependants()->size() == 0) - compile_recursive(node, compiled_patch); - } - - // Traverse any nodes we didn't hit yet - for (Nodes::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i) { - NodeImpl* const node = (*i); - if ( ! node->traversed()) - compile_recursive(node, compiled_patch); - } - - // Add any queued connections that must be run after a cycle - for (Connections::const_iterator i = _connections.begin(); i != _connections.end(); ++i) { - SharedPtr<ConnectionImpl> c = PtrCast<ConnectionImpl>(i->second); - if (c->src_port()->context() == Context::AUDIO && - c->dst_port()->context() == Context::MESSAGE) { - compiled_patch->queued_connections.push_back(c.get()); - } - } - - assert(compiled_patch->size() == _nodes.size()); - - return compiled_patch; -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/PatchImpl.hpp b/src/engine/PatchImpl.hpp deleted file mode 100644 index 8429728f..00000000 --- a/src/engine/PatchImpl.hpp +++ /dev/null @@ -1,165 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_PATCHIMPL_HPP -#define INGEN_ENGINE_PATCHIMPL_HPP - -#include <cstdlib> -#include <string> -#include "raul/List.hpp" -#include "ingen/PortType.hpp" -#include "ingen/Patch.hpp" -#include "NodeImpl.hpp" -#include "PluginImpl.hpp" -#include "CompiledPatch.hpp" - -namespace Ingen { - -class Connection; - -namespace Engine { - -class CompiledPatch; -class ConnectionImpl; -class Context; -class Engine; -class ProcessContext; - -/** A group of nodes in a graph, possibly polyphonic. - * - * Note that this is also a Node, just one which contains Nodes. - * Therefore infinite subpatching is possible, of polyphonic - * patches of polyphonic nodes etc. etc. - * - * \ingroup engine - */ -class PatchImpl : public NodeImpl, public Patch -{ -public: - PatchImpl(Engine& engine, - const Raul::Symbol& symbol, - uint32_t poly, - PatchImpl* parent, - SampleRate srate, - uint32_t local_poly); - - virtual ~PatchImpl(); - - void activate(BufferFactory& bufs); - void deactivate(); - - void process(ProcessContext& context); - - void set_buffer_size(Context& context, BufferFactory& bufs, PortType type, size_t size); - - /** Prepare for a new (internal) polyphony value. - * - * Preprocessor thread, poly is actually applied by apply_internal_poly. - * \return true on success. - */ - bool prepare_internal_poly(BufferFactory& bufs, uint32_t poly); - - /** Apply a new (internal) polyphony value. - * - * Audio thread. - * - * \param context Process context - * \param bufs New set of buffers - * \param poly Must be < the most recent value passed to prepare_internal_poly. - * \param maid Any objects no longer needed will be pushed to this - */ - bool apply_internal_poly(ProcessContext& context, BufferFactory& bufs, Raul::Maid& maid, uint32_t poly); - - // Patch specific stuff not inherited from Node - - typedef Raul::List<NodeImpl*> Nodes; - - void add_node(Nodes::Node* tn); - Nodes::Node* remove_node(const Raul::Symbol& symbol); - - Nodes& nodes() { return _nodes; } - Connections& connections() { return _connections; } - - const Nodes& nodes() const { return _nodes; } - const Connections& connections() const { return _connections; } - - uint32_t num_ports() const; - - PortImpl* create_port(BufferFactory& bufs, const std::string& name, PortType type, size_t buffer_size, bool is_output, bool polyphonic); - void add_input(Raul::List<PortImpl*>::Node* port) { _input_ports.push_back(port); } ///< Preprocesser thread - void add_output(Raul::List<PortImpl*>::Node* port) { _output_ports.push_back(port); } ///< Preprocessor thread - Raul::List<PortImpl*>::Node* remove_port(const std::string& name); - void clear_ports(); - - void add_connection(SharedPtr<ConnectionImpl> c); - - SharedPtr<ConnectionImpl> remove_connection(const PortImpl* src_port, const PortImpl* dst_port); - - bool has_connection(const PortImpl* src_port, const PortImpl* dst_port) const; - - CompiledPatch* compiled_patch() { return _compiled_patch; } - void compiled_patch(CompiledPatch* cp) { _compiled_patch = cp; } - - Raul::Array<PortImpl*>* external_ports() { return _ports; } - void external_ports(Raul::Array<PortImpl*>* pa) { _ports = pa; } - - CompiledPatch* compile() const; - Raul::Array<PortImpl*>* build_ports_array() const; - - /** Whether to run this patch's DSP bits in the audio thread */ - bool enabled() const { return _process; } - void enable() { _process = true; } - void disable(); - - uint32_t internal_poly() const { return _internal_poly; } - -private: - inline void compile_recursive(NodeImpl* n, CompiledPatch* output) const; - void process_parallel(ProcessContext& context); - void process_single(ProcessContext& context); - - Engine& _engine; - uint32_t _internal_poly; - CompiledPatch* _compiled_patch; ///< Accessed in audio thread only - Connections _connections; ///< Accessed in preprocessing thread only - Raul::List<PortImpl*> _input_ports; ///< Accessed in preprocessing thread only - Raul::List<PortImpl*> _output_ports; ///< Accessed in preprocessing thread only - Nodes _nodes; ///< Accessed in preprocessing thread only - bool _process; -}; - -/** Private helper for compile */ -inline void -PatchImpl::compile_recursive(NodeImpl* n, CompiledPatch* output) const -{ - if (n == NULL || n->traversed()) - return; - - n->traversed(true); - assert(output != NULL); - - for (Raul::List<NodeImpl*>::iterator i = n->providers()->begin(); i != n->providers()->end(); ++i) - if ( ! (*i)->traversed() ) - compile_recursive((*i), output); - - output->push_back(CompiledNode(n, n->providers()->size(), n->dependants())); -} - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_PATCHIMPL_HPP diff --git a/src/engine/PatchPlugin.hpp b/src/engine/PatchPlugin.hpp deleted file mode 100644 index ba244ef6..00000000 --- a/src/engine/PatchPlugin.hpp +++ /dev/null @@ -1,67 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_PATCHPLUGIN_HPP -#define INGEN_ENGINE_PATCHPLUGIN_HPP - -#include "ingen-config.h" - -#include <string> -#include "PluginImpl.hpp" - -namespace Ingen { -namespace Engine { - -class NodeImpl; - -/** Implementation of a Patch plugin. - * - * Patches don't actually work like this yet... - */ -class PatchPlugin : public PluginImpl -{ -public: - PatchPlugin( - Shared::LV2URIMap& uris, - const std::string& uri, - const std::string& symbol, - const std::string& name) - : PluginImpl(uris, Plugin::Patch, uri) - {} - - NodeImpl* instantiate(BufferFactory& bufs, - const std::string& name, - bool polyphonic, - PatchImpl* parent, - Engine& engine) - { - return NULL; - } - - const std::string symbol() const { return "patch"; } - const std::string name() const { return "Ingen Patch"; } - -private: - const std::string _symbol; - const std::string _name; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_PATCHPLUGIN_HPP - diff --git a/src/engine/PluginImpl.cpp b/src/engine/PluginImpl.cpp deleted file mode 100644 index e121bd62..00000000 --- a/src/engine/PluginImpl.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "raul/log.hpp" -#include "PluginImpl.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -void -PluginImpl::load() -{ - if (!_module) { - debug << "Loading plugin library " << _library_path << endl; - _module = new Glib::Module(_library_path, Glib::MODULE_BIND_LOCAL); - if (!(*_module)) - delete _module; - } -} - -void -PluginImpl::unload() -{ - if (_module) { - debug << "Unloading plugin library " << _library_path << endl; - delete _module; - _module = NULL; - } -} - -} // namespace Engine -} // namespace Ingen - diff --git a/src/engine/PluginImpl.hpp b/src/engine/PluginImpl.hpp deleted file mode 100644 index ab4e4a89..00000000 --- a/src/engine/PluginImpl.hpp +++ /dev/null @@ -1,88 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_PLUGINIMPL_HPP -#define INGEN_ENGINE_PLUGINIMPL_HPP - -#include <cstdlib> -#include <string> - -#include <boost/utility.hpp> -#include <glibmm/module.h> - -#include "ingen/Plugin.hpp" -#include "shared/ResourceImpl.hpp" - -namespace Ingen { - -namespace Shared { class LV2URIMap; } - -namespace Engine { - -class PatchImpl; -class NodeImpl; -class Engine; -class BufferFactory; - -/** Implementation of a plugin (internal code, or a loaded shared library). - * - * Conceptually, a Node is an instance of this. - */ -class PluginImpl : public Plugin - , public Ingen::Shared::ResourceImpl - , public boost::noncopyable -{ -public: - PluginImpl(Ingen::Shared::LV2URIMap& uris, - Type type, - const std::string& uri, - const std::string library_path = "") - : ResourceImpl(uris, uri) - , _type(type) - , _library_path(library_path) - , _module(NULL) - {} - - virtual NodeImpl* instantiate(BufferFactory& bufs, - const std::string& name, - bool polyphonic, - PatchImpl* parent, - Engine& engine) = 0; - - virtual const std::string symbol() const = 0; - - virtual const std::string& library_path() const { return _library_path; } - - void load(); - void unload(); - - Plugin::Type type() const { return _type; } - void type(Plugin::Type t) { _type = t; } - Glib::Module* module() const { return _module; } - void module(Glib::Module* module) { _module = module; } - -protected: - Plugin::Type _type; - mutable std::string _library_path; - Glib::Module* _module; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_PLUGINIMPL_HPP - diff --git a/src/engine/PortImpl.cpp b/src/engine/PortImpl.cpp deleted file mode 100644 index 62cc7577..00000000 --- a/src/engine/PortImpl.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "raul/Array.hpp" -#include "raul/Maid.hpp" -#include "shared/LV2URIMap.hpp" -#include "lv2/lv2plug.in/ns/ext/contexts/contexts.h" -#include "ingen/PortType.hpp" -#include "events/SendPortValue.hpp" -#include "events/SendPortActivity.hpp" -#include "AudioBuffer.hpp" -#include "BufferFactory.hpp" -#include "Engine.hpp" -#include "EventBuffer.hpp" -#include "LV2Atom.hpp" -#include "NodeImpl.hpp" -#include "ObjectBuffer.hpp" -#include "PortImpl.hpp" -#include "ThreadManager.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -PortImpl::PortImpl(BufferFactory& bufs, - NodeImpl* const node, - const Raul::Symbol& name, - uint32_t index, - uint32_t poly, - PortType type, - const Atom& value, - size_t buffer_size) - : GraphObjectImpl(bufs.uris(), node, name) - , _bufs(bufs) - , _index(index) - , _poly(poly) - , _buffer_size(buffer_size) - , _buffer_type(type) - , _value(value) - , _broadcast(false) - , _set_by_user(false) - , _last_broadcasted_value(value) - , _context(Context::AUDIO) - , _buffers(new Array<BufferFactory::Ref>(static_cast<size_t>(poly))) - , _prepared_buffers(NULL) -{ - _types.insert(type); - assert(node != NULL); - assert(_poly > 0); - - if (_buffer_size == 0) - _buffer_size = bufs.default_buffer_size(type); - - const Ingen::Shared::LV2URIMap& uris = bufs.uris(); - add_property(uris.rdf_type, type.uri()); - set_property(uris.lv2_index, Atom((int32_t)index)); - set_context(_context); - - if (type == PortType::EVENTS) - _broadcast = true; // send activity blips -} - -PortImpl::~PortImpl() -{ - delete _buffers; -} - -bool -PortImpl::supports(const Raul::URI& value_type) const -{ - return has_property(_bufs.uris().atom_supports, value_type); -} - -Raul::Array<BufferFactory::Ref>* -PortImpl::set_buffers(Raul::Array<BufferFactory::Ref>* buffers) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - - Raul::Array<BufferFactory::Ref>* ret = NULL; - if (buffers != _buffers) { - ret = _buffers; - _buffers = buffers; - } - - connect_buffers(); - - return ret; -} - -bool -PortImpl::prepare_poly(BufferFactory& bufs, uint32_t poly) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - if (buffer_type() != PortType::CONTROL && buffer_type() != PortType::AUDIO) - return false; - - if (_poly == poly) - return true; - - if (_prepared_buffers && _prepared_buffers->size() != poly) { - delete _prepared_buffers; - _prepared_buffers = NULL; - } - - if (!_prepared_buffers) - _prepared_buffers = new Array<BufferFactory::Ref>(poly, *_buffers, NULL); - - return true; -} - -void -PortImpl::prepare_poly_buffers(BufferFactory& bufs) -{ - if (_prepared_buffers) - get_buffers(bufs, _prepared_buffers, _prepared_buffers->size()); -} - -bool -PortImpl::apply_poly(Maid& maid, uint32_t poly) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - if (buffer_type() != PortType::CONTROL && buffer_type() != PortType::AUDIO) - return false; - - if (!_prepared_buffers) - return true; - - assert(poly == _prepared_buffers->size()); - - _poly = poly; - - // Apply a new set of buffers from a preceding call to prepare_poly - maid.push(set_buffers(_prepared_buffers)); - assert(_buffers == _prepared_buffers); - _prepared_buffers = NULL; - - if (is_a(PortType::CONTROL)) - for (uint32_t v = 0; v < _poly; ++v) - if (_buffers->at(v)) - boost::static_pointer_cast<AudioBuffer>(_buffers->at(v))->set_value( - _value.get_float(), 0, 0); - - assert(_buffers->size() >= poly); - assert(this->poly() == poly); - assert(!_prepared_buffers); - - return true; -} - -void -PortImpl::set_buffer_size(Context& context, BufferFactory& bufs, size_t size) -{ - _buffer_size = size; - - for (uint32_t v = 0; v < _poly; ++v) - _buffers->at(v)->resize(size); - - connect_buffers(); -} - -void -PortImpl::connect_buffers(SampleCount offset) -{ - for (uint32_t v = 0; v < _poly; ++v) - PortImpl::parent_node()->set_port_buffer(v, _index, buffer(v), offset); -} - -void -PortImpl::recycle_buffers() -{ - for (uint32_t v = 0; v < _poly; ++v) - _buffers->at(v) = NULL; -} - -void -PortImpl::clear_buffers() -{ - for (uint32_t v = 0; v < _poly; ++v) - buffer(v)->clear(); -} - -void -PortImpl::broadcast_value(Context& context, bool force) -{ - Raul::Atom val; - switch (buffer_type().symbol()) { - case PortType::UNKNOWN: - break; - case PortType::AUDIO: - case PortType::CONTROL: - val = ((AudioBuffer*)buffer(0).get())->value_at(0); - break; - case PortType::EVENTS: - if (((EventBuffer*)buffer(0).get())->event_count() > 0) { - const Events::SendPortActivity ev(context.engine(), context.start(), this); - context.event_sink().write(sizeof(ev), &ev); - } - break; - case PortType::VALUE: - case PortType::MESSAGE: - Ingen::Shared::LV2Atom::to_atom(_bufs.uris(), ((ObjectBuffer*)buffer(0).get())->atom(), val); - break; - } - - if (val.is_valid() && (force || val != _last_broadcasted_value)) { - _last_broadcasted_value = val; - const Events::SendPortValue ev(context.engine(), context.start(), this, true, 0, val); - context.event_sink().write(sizeof(ev), &ev); - } -} - -void -PortImpl::set_context(Context::ID c) -{ - const Ingen::Shared::LV2URIMap& uris = _bufs.uris(); - _context = c; - switch (c) { - case Context::AUDIO: - remove_property(uris.ctx_context, uris.wildcard); - break; - case Context::MESSAGE: - set_property(uris.ctx_context, uris.ctx_MessageContext); - break; - } -} - -PortType -PortImpl::buffer_type() const -{ - // TODO: multiple types - return *_types.begin(); -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/PortImpl.hpp b/src/engine/PortImpl.hpp deleted file mode 100644 index a8f3a63e..00000000 --- a/src/engine/PortImpl.hpp +++ /dev/null @@ -1,174 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_PORTIMPL_HPP -#define INGEN_ENGINE_PORTIMPL_HPP - -#include <cstdlib> -#include <string> -#include <set> -#include "raul/Array.hpp" -#include "raul/Atom.hpp" -#include "ingen/Port.hpp" -#include "types.hpp" -#include "GraphObjectImpl.hpp" -#include "ingen/PortType.hpp" -#include "Buffer.hpp" -#include "Context.hpp" - -namespace Raul { class Maid; } - -namespace Ingen { -namespace Engine { - -class NodeImpl; -class Buffer; -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. - * - * \ingroup engine - */ -class PortImpl : public GraphObjectImpl, public Port -{ -public: - ~PortImpl(); - - /** A port's parent is always a node, so static cast should be safe */ - NodeImpl* parent_node() const { return (NodeImpl*)_parent; } - - /** Set the buffers array for this port. - * - * Audio thread. Returned value must be freed by caller. - * \a buffers must be poly() long - */ - Raul::Array<BufferFactory::Ref>* set_buffers(Raul::Array<BufferFactory::Ref>* buffers); - - /** Prepare for a new (external) polyphony value. - * - * Preprocessor thread, poly is actually applied by apply_poly. - */ - virtual bool prepare_poly(BufferFactory& bufs, uint32_t poly); - - virtual void prepare_poly_buffers(BufferFactory& bufs); - - /** Apply a new polyphony value. - * - * Audio thread. - * \a poly Must be < the most recent value passed to prepare_poly. - */ - virtual bool apply_poly(Raul::Maid& maid, uint32_t poly); - - const Raul::Atom& value() const { return _value; } - void set_value(const Raul::Atom& v) { _value = v; } - - inline BufferFactory::Ref buffer(uint32_t voice) const { - return _buffers->at((_poly == 1) ? 0 : voice); - } - inline BufferFactory::Ref prepared_buffer(uint32_t voice) const { - return _prepared_buffers->at(voice); - } - - /** Called once per process cycle */ - virtual void pre_process(Context& context) = 0; - virtual void post_process(Context& context) = 0; - - /** Empty buffer contents completely (ie silence) */ - virtual void clear_buffers(); - - virtual bool get_buffers(BufferFactory& bufs, - Raul::Array<BufferFactory::Ref>* buffers, - uint32_t poly) = 0; - - void setup_buffers(BufferFactory& bufs, uint32_t poly) { - get_buffers(bufs, _buffers, poly); - } - - virtual void connect_buffers(SampleCount offset=0); - virtual void recycle_buffers(); - - virtual bool is_input() const = 0; - virtual bool is_output() const = 0; - - uint32_t index() const { return _index; } - - const PortTypes& types() const { return _types; } - - PortType buffer_type() const; - - bool supports(const Raul::URI& value_type) const; - - size_t buffer_size() const { return _buffer_size; } - - uint32_t poly() const { - return _poly; - } - uint32_t prepared_poly() const { - return (_prepared_buffers) ? _prepared_buffers->size() : 1; - } - - void set_buffer_size(Context& context, BufferFactory& bufs, size_t size); - void set_buffer_type(PortType type); - - void broadcast(bool b) { _broadcast = b; } - bool broadcast() { return _broadcast; } - - void broadcast_value(Context& context, bool force=false); - - void raise_set_by_user_flag() { _set_by_user = true; } - - Context::ID context() const { return _context; } - void set_context(Context::ID c); - - BufferFactory& bufs() const { return _bufs; } - -protected: - PortImpl(BufferFactory& bufs, - NodeImpl* node, - const Raul::Symbol& name, - uint32_t index, - uint32_t poly, - PortType type, - const Raul::Atom& value, - size_t buffer_size); - - BufferFactory& _bufs; - uint32_t _index; - uint32_t _poly; - uint32_t _buffer_size; - PortType _buffer_type; - std::set<PortType> _types; - Raul::Atom _value; - bool _broadcast; - bool _set_by_user; - Raul::Atom _last_broadcasted_value; - - Context::ID _context; - Raul::Array<BufferFactory::Ref>* _buffers; - - // Dynamic polyphony - Raul::Array<BufferFactory::Ref>* _prepared_buffers; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_PORTIMPL_HPP diff --git a/src/engine/PostProcessor.cpp b/src/engine/PostProcessor.cpp deleted file mode 100644 index 29179b00..00000000 --- a/src/engine/PostProcessor.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <cassert> -#include <pthread.h> -#include "raul/log.hpp" -#include "raul/SRSWQueue.hpp" -#include "events/SendPortValue.hpp" -#include "Event.hpp" -#include "PostProcessor.hpp" -#include "Engine.hpp" -#include "Driver.hpp" -#include "ProcessContext.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -PostProcessor::PostProcessor(Engine& engine, size_t queue_size) - : _engine(engine) - , _max_time(0) - , _events(queue_size) - , _event_buffer_size(sizeof(Events::SendPortValue)) // FIXME: make generic - , _event_buffer((uint8_t*)malloc(_event_buffer_size)) -{ -} - -PostProcessor::~PostProcessor() -{ - free(_event_buffer); -} - -void -PostProcessor::process() -{ - const FrameTime end_time = _max_time.get(); - - /* FIXME: The order here is a bit tricky: if the normal events are - * processed first, then a deleted port may still have a pending - * broadcast event which will segfault if executed afterwards. - * If it's the other way around, broadcasts will be sent for - * ports the client doesn't even know about yet... */ - - /* FIXME: process events from all threads if parallel */ - - /* Process audio thread generated events */ - while (true) { - Driver* driver = _engine.driver(); - if (driver && driver->context().event_sink().read(_event_buffer_size, _event_buffer)) { - if (((Event*)_event_buffer)->time() > end_time) { - warn << "Lost event with time " - << ((Event*)_event_buffer)->time() << " > " << end_time << endl; - break; - } - ((Event*)_event_buffer)->post_process(); - } else { - break; - } - } - - /* Process normal events */ - Raul::List<Event*>::Node* n = _events.head(); - while (n) { - if (n->elem()->time() > end_time) - break; - Raul::List<Event*>::Node* next = n->next(); - n->elem()->post_process(); - _events.erase(_events.begin()); - delete n->elem(); - delete n; - n = next; - } -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/PostProcessor.hpp b/src/engine/PostProcessor.hpp deleted file mode 100644 index f0888d2f..00000000 --- a/src/engine/PostProcessor.hpp +++ /dev/null @@ -1,68 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_POSTPROCESSOR_HPP -#define INGEN_ENGINE_POSTPROCESSOR_HPP - -#include <pthread.h> -#include "raul/SRSWQueue.hpp" -#include "raul/List.hpp" - -namespace Ingen { -namespace Engine { - -class Event; -class Engine; - -/** Processor for Events after leaving the audio thread. - * - * The audio thread pushes events to this when it is done with them (which - * is realtime-safe), which signals the processing thread through a semaphore - * to handle the event and pass it on to the Maid. - * - * Update: This is all run from main_iteration now to solve scripting - * thread issues. Not sure if this is permanent/ideal or not... - * - * \ingroup engine - */ -class PostProcessor -{ -public: - PostProcessor(Engine& engine, size_t queue_size); - ~PostProcessor(); - - /** Push a list of events on to the process queue, realtime-safe, not thread-safe. */ - inline void append(Raul::List<Event*>* l) { _events.append(*l); } - - /** Post-process and delete all pending events */ - void process(); - - /** Set the latest event time that should be post-processed */ - void set_end_time(FrameTime time) { _max_time = time; } - -private: - Engine& _engine; - Raul::AtomicInt _max_time; - Raul::List<Event*> _events; - uint32_t _event_buffer_size; - uint8_t* _event_buffer; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_POSTPROCESSOR_HPP diff --git a/src/engine/ProcessContext.cpp b/src/engine/ProcessContext.cpp deleted file mode 100644 index 2abe7cf2..00000000 --- a/src/engine/ProcessContext.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "ProcessContext.hpp" -#include "ProcessSlave.hpp" - -namespace Ingen { -namespace Engine { - -void -ProcessContext::activate(uint32_t parallelism, bool sched_rt) -{ - for (uint32_t i = 0; i < _slaves.size(); ++i) { - delete _slaves[i]; - } - _slaves.clear(); - _slaves.reserve(parallelism); - for (uint32_t i = 0; i < parallelism - 1; ++i) { - _slaves.push_back(new ProcessSlave(_engine, sched_rt)); - } -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/ProcessContext.hpp b/src/engine/ProcessContext.hpp deleted file mode 100644 index bbaa5ad2..00000000 --- a/src/engine/ProcessContext.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_PROCESSCONTEXT_HPP -#define INGEN_ENGINE_PROCESSCONTEXT_HPP - -#include <vector> - -#include "Context.hpp" -#include "EventSink.hpp" -#include "types.hpp" - -namespace Ingen { -namespace Engine { - -class ProcessSlave; - -/** Context of a process() call (the audio context). - * \ingroup engine - */ -class ProcessContext : public Context -{ -public: - explicit ProcessContext(Engine& engine) : Context(engine, AUDIO) {} - - typedef std::vector<ProcessSlave*> Slaves; - - const Slaves& slaves() const { return _slaves; } - Slaves& slaves() { return _slaves; } - - void activate(uint32_t parallelism, bool sched_rt); - -private: - Slaves _slaves; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_PROCESSCONTEXT_HPP diff --git a/src/engine/ProcessSlave.cpp b/src/engine/ProcessSlave.cpp deleted file mode 100644 index 44197d4a..00000000 --- a/src/engine/ProcessSlave.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "ProcessSlave.hpp" -#include "NodeImpl.hpp" -#include "CompiledPatch.hpp" - -using namespace std; - -namespace Ingen { -namespace Engine { - -uint32_t ProcessSlave::_next_id = 0; - -void -ProcessSlave::_whipped() -{ - assert(_compiled_patch); - CompiledPatch* const cp = _compiled_patch; - - /* Iterate over all nodes attempting to run immediately or block then run, - * until we've been through the entire array without getting a lock, - * and thus are finished this cycle. - */ - - size_t num_finished = 0; // Number of consecutive finished nodes hit - - while (_state == STATE_RUNNING) { - - CompiledNode& n = (*cp)[_index]; - - if (n.node()->process_lock()) { - - n.node()->wait_for_input(n.n_providers()); - - n.node()->process(*_context); - - /* Signal dependants their input is ready */ - for (size_t i=0; i < n.dependants().size(); ++i) - n.dependants()[i]->signal_input_ready(); - - num_finished = 1; - } else { - ++num_finished; - } - - _index = (_index + 1) % cp->size(); - - if (num_finished >= cp->size()) - break; - } - - _index = 0; - _compiled_patch = NULL; - _state = STATE_FINISHED; -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/ProcessSlave.hpp b/src/engine/ProcessSlave.hpp deleted file mode 100644 index 39c599af..00000000 --- a/src/engine/ProcessSlave.hpp +++ /dev/null @@ -1,104 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_PROCESSSLAVE_HPP -#define INGEN_ENGINE_PROCESSSLAVE_HPP - -#include <sstream> - -#include "raul/Array.hpp" -#include "raul/AtomicInt.hpp" -#include "raul/Slave.hpp" - -#include "Driver.hpp" -#include "Engine.hpp" -#include "ProcessContext.hpp" - -namespace Ingen { -namespace Engine { - -class NodeImpl; -class CompiledPatch; - -class ProcessSlave : protected Raul::Slave { -public: - ProcessSlave(Engine& engine, bool realtime) - : _engine(engine) - , _id(_next_id++) - , _index(0) - , _state(STATE_FINISHED) - , _compiled_patch(NULL) - , _context(NULL) - { - std::stringstream ss; - ss << "Process Slave "; - ss << _id; - set_name(ss.str()); - - start(); - - if (realtime) - set_scheduling(SCHED_FIFO, 40); - } - - ~ProcessSlave() { - stop(); - } - - inline void whip(CompiledPatch* compiled_patch, - uint32_t start_index, - ProcessContext& context) - { - assert(_state == STATE_FINISHED); - _index = start_index; - _state = STATE_RUNNING; - _compiled_patch = compiled_patch; - _context = &context; - - Raul::Slave::whip(); - } - - inline void finish() { - while (_state.get() != STATE_FINISHED) - _state.compare_and_exchange(STATE_RUNNING, STATE_FINISH_SIGNALLED); - } - - inline uint32_t id() const { return _id; } - inline const ProcessContext& context() const { return _engine.driver()->context(); } - inline ProcessContext& context() { return _engine.driver()->context(); } - -private: - void _whipped(); - - static uint32_t _next_id; - - static const int STATE_RUNNING = 0; - static const int STATE_FINISH_SIGNALLED = 1; - static const int STATE_FINISHED = 2; - - Engine& _engine; - uint32_t _id; - uint32_t _index; - Raul::AtomicInt _state; - CompiledPatch* _compiled_patch; - ProcessContext* _context; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_PROCESSSLAVE_HPP diff --git a/src/engine/QueuedEngineInterface.cpp b/src/engine/QueuedEngineInterface.cpp deleted file mode 100644 index 24042b27..00000000 --- a/src/engine/QueuedEngineInterface.cpp +++ /dev/null @@ -1,223 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <string> - -#include "raul/log.hpp" - -#include "Driver.hpp" -#include "Engine.hpp" -#include "EventSource.hpp" -#include "QueuedEngineInterface.hpp" -#include "events.hpp" - -#define LOG(s) s << "[QueuedEngineInterface] " - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { - -QueuedEngineInterface::QueuedEngineInterface(Engine& engine, size_t queue_size) - : EventSource(queue_size) - , _request(new Request(this, NULL, 0)) - , _engine(engine) - , _in_bundle(false) -{ - start(); -} - - -QueuedEngineInterface::~QueuedEngineInterface() -{ - stop(); -} - -SampleCount -QueuedEngineInterface::now() const -{ - // Exactly one cycle latency (some could run ASAP if we get lucky, but not always, and a slight - // constant latency is far better than jittery lower (average) latency - if (_engine.driver()) - return _engine.driver()->frame_time() + _engine.driver()->block_length(); - else - return 0; -} - -void -QueuedEngineInterface::set_next_response_id(int32_t id) -{ - if (_request) - _request->set_id(id); -} - -void -QueuedEngineInterface::disable_responses() -{ - _request->set_client(NULL); - _request->set_id(0); -} - -/* *** EngineInterface implementation below here *** */ - -void -QueuedEngineInterface::register_client(ClientInterface* client) -{ - push_queued(new Events::RegisterClient(_engine, _request, now(), client->uri(), client)); - if (!_request) { - _request = SharedPtr<Request>(new Request(this, client, 1)); - } else { - _request->set_id(1); - _request->set_client(client); - } -} - -void -QueuedEngineInterface::unregister_client(const URI& uri) -{ - push_queued(new Events::UnregisterClient(_engine, _request, now(), uri)); - if (_request && _request->client() && _request->client()->uri() == uri) { - _request->set_id(0); - _request->set_client(NULL); - } -} - -// Bundle commands - -void -QueuedEngineInterface::bundle_begin() -{ - _in_bundle = true; -} - -void -QueuedEngineInterface::bundle_end() -{ - _in_bundle = false; -} - -// Object commands - -void -QueuedEngineInterface::put(const URI& uri, - const Resource::Properties& properties, - const Resource::Graph ctx) -{ - push_queued(new Events::SetMetadata(_engine, _request, now(), true, ctx, uri, properties)); -} - -void -QueuedEngineInterface::delta(const URI& uri, - const Resource::Properties& remove, - const Resource::Properties& add) -{ - push_queued(new Events::SetMetadata(_engine, _request, now(), false, Resource::DEFAULT, uri, add, remove)); -} - -void -QueuedEngineInterface::move(const Path& old_path, - const Path& new_path) -{ - push_queued(new Events::Move(_engine, _request, now(), old_path, new_path)); -} - -void -QueuedEngineInterface::del(const URI& uri) -{ - if (uri == "ingen:engine") { - _request->respond_ok(); - _engine.quit(); - } else { - push_queued(new Events::Delete(_engine, _request, now(), uri)); - } -} - -void -QueuedEngineInterface::connect(const Path& src_port_path, - const Path& dst_port_path) -{ - push_queued(new Events::Connect(_engine, _request, now(), src_port_path, dst_port_path)); - -} - -void -QueuedEngineInterface::disconnect(const URI& src, - const URI& dst) -{ - if (!Path::is_path(src) && !Path::is_path(dst)) { - std::cerr << "Bad disconnect request " << src << " => " << dst << std::endl; - return; - } - - push_queued(new Events::Disconnect(_engine, _request, now(), - Path(src.str()), Path(dst.str()))); -} - -void -QueuedEngineInterface::disconnect_all(const Path& patch_path, - const Path& path) -{ - push_queued(new Events::DisconnectAll(_engine, _request, now(), patch_path, path)); -} - -void -QueuedEngineInterface::set_property(const URI& uri, - const URI& predicate, - const Atom& value) -{ - if (uri == "ingen:engine" && predicate == "ingen:enabled" - && value.type() == Atom::BOOL) { - if (value.get_bool()) { - _engine.activate(); - push_queued(new Events::Ping(_engine, _request, now())); - } else { - push_queued(new Events::Deactivate(_engine, _request, now())); - } - } else { - Resource::Properties remove; - remove.insert(make_pair(predicate, _engine.world()->uris()->wildcard)); - Resource::Properties add; - add.insert(make_pair(predicate, value)); - push_queued(new Events::SetMetadata( - _engine, _request, now(), false, Resource::DEFAULT, - uri, add, remove)); - } -} - -// Requests // - -void -QueuedEngineInterface::ping() -{ - push_queued(new Events::Ping(_engine, _request, now())); -} - -void -QueuedEngineInterface::get(const URI& uri) -{ - push_queued(new Events::Get(_engine, _request, now(), uri)); -} - -void -QueuedEngineInterface::request_property(const URI& uri, const URI& key) -{ - push_queued(new Events::RequestMetadata(_engine, _request, now(), Resource::DEFAULT, uri, key)); -} - -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/QueuedEngineInterface.hpp b/src/engine/QueuedEngineInterface.hpp deleted file mode 100644 index b9f4f7b7..00000000 --- a/src/engine/QueuedEngineInterface.hpp +++ /dev/null @@ -1,116 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_QUEUEDENGINEINTERFACE_HPP -#define INGEN_ENGINE_QUEUEDENGINEINTERFACE_HPP - -#include <inttypes.h> -#include <string> -#include <memory> -#include "raul/SharedPtr.hpp" -#include "ingen/ClientInterface.hpp" -#include "ingen/EngineInterface.hpp" -#include "ingen/Resource.hpp" -#include "EventSource.hpp" -#include "Request.hpp" -#include "types.hpp" - -namespace Ingen { -namespace Engine { - -class Engine; - -/** A queued (preprocessed) event source / interface. - * - * This is the bridge between the EngineInterface presented to the client, and - * the EventSource that needs to be presented to the Driver. - * - * Responses occur through the event mechanism (which notified clients in - * event post_process methods) and are related to an event by an integer ID. - * If you do not register a request, you have no way of knowing if your calls - * are successful. - */ -class QueuedEngineInterface : public EventSource, - public EngineInterface -{ -public: - QueuedEngineInterface(Engine& engine, size_t queue_size); - virtual ~QueuedEngineInterface(); - - Raul::URI uri() const { return "http://drobilla.net/ns/ingen#internal"; } - - void set_next_response_id(int32_t id); - - // Client registration - virtual void register_client(ClientInterface* client); - virtual void unregister_client(const Raul::URI& uri); - - // Bundles - virtual void bundle_begin(); - virtual void bundle_end(); - - // CommonInterface object commands - - virtual void put(const Raul::URI& path, - const Resource::Properties& properties, - const Resource::Graph g=Resource::DEFAULT); - - virtual void delta(const Raul::URI& path, - const Resource::Properties& remove, - const Resource::Properties& add); - - virtual void move(const Raul::Path& old_path, - const Raul::Path& new_path); - - virtual void connect(const Raul::Path& src_port_path, - const Raul::Path& dst_port_path); - - virtual void disconnect(const Raul::URI& src, - const Raul::URI& dst); - - virtual void set_property(const Raul::URI& subject_path, - const Raul::URI& predicate, - const Raul::Atom& value); - - virtual void del(const Raul::URI& uri); - - // EngineInterface object commands - - virtual void disconnect_all(const Raul::Path& parent_patch_path, - const Raul::Path& path); - - // Requests - virtual void ping(); - virtual void get(const Raul::URI& uri); - virtual void request_property(const Raul::URI& object_path, - const Raul::URI& key); - -protected: - virtual void disable_responses(); - - SharedPtr<Request> _request; ///< NULL if responding disabled - Engine& _engine; - bool _in_bundle; ///< True iff a bundle is currently being received - -private: - SampleCount now() const; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_QUEUEDENGINEINTERFACE_HPP diff --git a/src/engine/QueuedEvent.cpp b/src/engine/QueuedEvent.cpp deleted file mode 100644 index e08b6b30..00000000 --- a/src/engine/QueuedEvent.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "QueuedEvent.hpp" -#include "ThreadManager.hpp" -#include "ProcessContext.hpp" - -namespace Ingen { -namespace Engine { - -void -QueuedEvent::pre_process() -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - assert(_pre_processed == false); - _pre_processed = true; -} - -void -QueuedEvent::execute(ProcessContext& context) -{ - assert(_pre_processed); - assert(_time <= context.end()); - - // Didn't prepare in time. QueuedEvents aren't (necessarily) sample accurate - // so just run at the beginning of this cycle - if (_time <= context.start()) - _time = context.start(); - - Event::execute(context); -} - -} // namespace Engine -} // namespace Ingen - diff --git a/src/engine/QueuedEvent.hpp b/src/engine/QueuedEvent.hpp deleted file mode 100644 index 99c5ff33..00000000 --- a/src/engine/QueuedEvent.hpp +++ /dev/null @@ -1,77 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_QUEUEDEVENT_HPP -#define INGEN_ENGINE_QUEUEDEVENT_HPP - -#include "Event.hpp" - -namespace Ingen { -namespace Engine { - -/** An Event with a not-time-critical preprocessing stage. - * - * These events are events that aren't able to be executed immediately by the - * Jack thread (because they allocate memory or whatever). They are pushed - * on to the QueuedEventQueue where they are preprocessed then pushed on - * to the realtime Event Queue when they are ready. - * - * Lookups for these events should go in the pre_process() method, since they are - * not time critical and shouldn't waste time in the audio thread doing - * lookups they can do beforehand. (This applies for any expensive operation that - * could be done before the execute() method). - * - * \ingroup engine - */ -class QueuedEvent : public Event -{ -public: - /** Process this event into a realtime-suitable event. */ - virtual void pre_process(); - - virtual void execute(ProcessContext& context); - - /** True iff this event blocks the prepare phase of other events. */ - bool is_blocking() { return _blocking; } - - bool is_prepared() { return _pre_processed; } - -protected: - QueuedEvent(Engine& engine, - SharedPtr<Request> request, - FrameTime time, - bool blocking=false) - : Event(engine, request, time) - , _pre_processed(false) - , _blocking(blocking) - {} - - // NULL event base (for internal events only!) - explicit QueuedEvent(Engine& engine) - : Event(engine, SharedPtr<Request>(), 0) - , _pre_processed(false) - , _blocking(false) - {} - - bool _pre_processed; - bool _blocking; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_QUEUEDEVENT_HPP diff --git a/src/engine/Request.hpp b/src/engine/Request.hpp deleted file mode 100644 index 3e4372c9..00000000 --- a/src/engine/Request.hpp +++ /dev/null @@ -1,81 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_REQUEST_HPP -#define INGEN_ENGINE_REQUEST_HPP - -#include <inttypes.h> -#include <string> -#include "ingen/ClientInterface.hpp" -#include "EventSource.hpp" - -namespace Ingen { -namespace Engine { - -/** Record of a request (used to respond to clients). - * - * This is a glorified std::pair<ClientInterface*, int32_t> for replying - * to numbered messages from a client. - * - * For responses that involve several messages, the response will come first - * followed by the messages (eg object notifications, values, errors, etc.) - * in a bundle (or "transfer" if too large). - */ -class Request -{ -public: - Request(EventSource* source=0, - ClientInterface* client=0, - int32_t id=1) - : _source(source) - , _client(client) - , _id(id) - {} - - EventSource* source() { return _source; } - int32_t id() const { return _id; } - void set_id(int32_t id) { _id = id; } - - ClientInterface* client() const { return _client; } - void set_client(ClientInterface* client) { _client = client; } - - void unblock() { - if (_source) - _source->unblock(); - } - - void respond_ok() { - if (_client) - _client->response_ok(_id); - } - - void respond_error(const std::string& msg) { - if (_client) - _client->response_error(_id, msg); - } - -private: - EventSource* _source; - ClientInterface* _client; - int32_t _id; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_REQUEST_HPP - diff --git a/src/engine/ThreadManager.hpp b/src/engine/ThreadManager.hpp deleted file mode 100644 index 9a73250d..00000000 --- a/src/engine/ThreadManager.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_THREADMANAGER_HPP -#define INGEN_ENGINE_THREADMANAGER_HPP - -#include <cassert> -#include "raul/Thread.hpp" - -namespace Ingen { -namespace Engine { - -enum ThreadID { - THREAD_PRE_PROCESS, - THREAD_PROCESS, - THREAD_MESSAGE, -}; - -class ThreadManager { -public: - inline static bool thread_is(ThreadID id) { - return Raul::Thread::get().is_context(id); - } - - inline static void assert_thread(ThreadID id) { - assert(single_threaded || Raul::Thread::get().is_context(id)); - } - - inline static void assert_not_thread(ThreadID id) { - assert(single_threaded || !Raul::Thread::get().is_context(id)); - } - - /** Set to true during initialisation so ensure_thread doesn't fail. - * Defined in Engine.cpp - */ - static bool single_threaded; -}; - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_THREADMANAGER_HPP diff --git a/src/engine/events.hpp b/src/engine/events.hpp deleted file mode 100644 index 7ddcfe52..00000000 --- a/src/engine/events.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_EVENTS_HPP -#define INGEN_ENGINE_EVENTS_HPP - -#include "ingen-config.h" - -#include "events/Connect.hpp" -#include "events/CreateNode.hpp" -#include "events/CreatePatch.hpp" -#include "events/CreatePort.hpp" -#include "events/Deactivate.hpp" -#include "events/Delete.hpp" -#include "events/Disconnect.hpp" -#include "events/DisconnectAll.hpp" -#include "events/Get.hpp" -#include "events/Move.hpp" -#include "events/Ping.hpp" -#include "events/RegisterClient.hpp" -#include "events/RequestMetadata.hpp" -#include "events/SetMetadata.hpp" -#include "events/SetPortValue.hpp" -#include "events/UnregisterClient.hpp" - -#endif // INGEN_ENGINE_EVENTS_HPP - diff --git a/src/engine/events/Connect.cpp b/src/engine/events/Connect.cpp deleted file mode 100644 index 0f4bd465..00000000 --- a/src/engine/events/Connect.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <string> -#include <boost/format.hpp> -#include "raul/Maid.hpp" -#include "raul/Path.hpp" -#include "ClientBroadcaster.hpp" -#include "Connect.hpp" -#include "ConnectionImpl.hpp" -#include "DuplexPort.hpp" -#include "Engine.hpp" -#include "EngineStore.hpp" -#include "InputPort.hpp" -#include "OutputPort.hpp" -#include "PatchImpl.hpp" -#include "PortImpl.hpp" -#include "ProcessContext.hpp" -#include "Request.hpp" -#include "types.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { -namespace Events { - -Connect::Connect(Engine& engine, SharedPtr<Request> request, SampleCount timestamp, const Path& src_port_path, const Path& dst_port_path) - : QueuedEvent(engine, request, timestamp) - , _src_port_path(src_port_path) - , _dst_port_path(dst_port_path) - , _patch(NULL) - , _src_output_port(NULL) - , _dst_input_port(NULL) - , _compiled_patch(NULL) - , _port_listnode(NULL) - , _buffers(NULL) -{ -} - -void -Connect::pre_process() -{ - PortImpl* src_port = _engine.engine_store()->find_port(_src_port_path); - PortImpl* dst_port = _engine.engine_store()->find_port(_dst_port_path); - if (!src_port || !dst_port) { - _error = PORT_NOT_FOUND; - QueuedEvent::pre_process(); - return; - } - - _dst_input_port = dynamic_cast<InputPort*>(dst_port); - _src_output_port = dynamic_cast<OutputPort*>(src_port); - if (!_dst_input_port || !_src_output_port) { - _error = DIRECTION_MISMATCH; - QueuedEvent::pre_process(); - return; - } - - NodeImpl* const src_node = src_port->parent_node(); - NodeImpl* const dst_node = dst_port->parent_node(); - if (!src_node || !dst_node) { - _error = PARENTS_NOT_FOUND; - QueuedEvent::pre_process(); - return; - } - - if (src_node->parent() != dst_node->parent() - && src_node != dst_node->parent() - && src_node->parent() != dst_node) { - _error = PARENT_PATCH_DIFFERENT; - QueuedEvent::pre_process(); - return; - } - - if (!ConnectionImpl::can_connect(_src_output_port, _dst_input_port)) { - _error = TYPE_MISMATCH; - QueuedEvent::pre_process(); - return; - } - - // Connection to a patch port from inside the patch - if (src_node->parent_patch() != dst_node->parent_patch()) { - assert(src_node->parent() == dst_node || dst_node->parent() == src_node); - if (src_node->parent() == dst_node) - _patch = dynamic_cast<PatchImpl*>(dst_node); - else - _patch = dynamic_cast<PatchImpl*>(src_node); - - // Connection from a patch input to a patch output (pass through) - } else if (src_node == dst_node && dynamic_cast<PatchImpl*>(src_node)) { - _patch = dynamic_cast<PatchImpl*>(src_node); - - // Normal connection between nodes with the same parent - } else { - _patch = src_node->parent_patch(); - } - - if (_patch->has_connection(_src_output_port, _dst_input_port)) { - _error = ALREADY_CONNECTED; - QueuedEvent::pre_process(); - return; - } - - _connection = SharedPtr<ConnectionImpl>( - new ConnectionImpl(*_engine.buffer_factory(), _src_output_port, _dst_input_port)); - - _port_listnode = new InputPort::Connections::Node(_connection); - - // Need to be careful about patch port connections here and adding a node's - // parent as a dependant/provider, or adding a patch as it's own provider... - if (src_node != dst_node && src_node->parent() == dst_node->parent()) { - dst_node->providers()->push_back(new Raul::List<NodeImpl*>::Node(src_node)); - src_node->dependants()->push_back(new Raul::List<NodeImpl*>::Node(dst_node)); - } - - _patch->add_connection(_connection); - _dst_input_port->increment_num_connections(); - - /*if ((_dst_input_port->num_connections() == 1 - && (_connection->must_mix() || _connection->must_queue())) - || _dst_input_port->num_connections() == 2) {*/ - _buffers = new Raul::Array<BufferFactory::Ref>(_dst_input_port->poly()); - _dst_input_port->get_buffers(*_engine.buffer_factory(), - _buffers, _dst_input_port->poly()); - //} - - if (_patch->enabled()) - _compiled_patch = _patch->compile(); - - QueuedEvent::pre_process(); -} - -void -Connect::execute(ProcessContext& context) -{ - QueuedEvent::execute(context); - - if (_error == NO_ERROR) { - // This must be inserted here, since they're actually used by the audio thread - _dst_input_port->add_connection(_port_listnode); - assert(_buffers); - //if (_buffers) - _engine.maid()->push(_dst_input_port->set_buffers(_buffers)); - //else - // _dst_input_port->setup_buffers(*_engine.buffer_factory(), _dst_input_port->poly()); - _dst_input_port->connect_buffers(); - _engine.maid()->push(_patch->compiled_patch()); - _patch->compiled_patch(_compiled_patch); - } -} - -void -Connect::post_process() -{ - std::ostringstream ss; - if (_error == NO_ERROR) { - _request->respond_ok(); - _engine.broadcaster()->connect(_src_port_path, _dst_port_path); - return; - } - - ss << boost::format("Unable to make connection %1% -> %2% (") - % _src_port_path.chop_scheme() % _dst_port_path.chop_scheme(); - - switch (_error) { - case PARENT_PATCH_DIFFERENT: - ss << "Ports have mismatched parents"; break; - case PORT_NOT_FOUND: - ss << "Port not found"; break; - case TYPE_MISMATCH: - ss << "Type mismatch"; break; - case DIRECTION_MISMATCH: - ss << "Direction mismatch"; break; - case ALREADY_CONNECTED: - ss << "Already connected"; break; - case PARENTS_NOT_FOUND: - ss << "Parents not found"; break; - default: - ss << "Unknown error"; - } - ss << ")"; - _request->respond_error(ss.str()); -} - -} // namespace Engine -} // namespace Ingen -} // namespace Events - diff --git a/src/engine/events/Connect.hpp b/src/engine/events/Connect.hpp deleted file mode 100644 index ec40f70b..00000000 --- a/src/engine/events/Connect.hpp +++ /dev/null @@ -1,88 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_EVENTS_CONNECT_HPP -#define INGEN_EVENTS_CONNECT_HPP - -#include "raul/Path.hpp" -#include "QueuedEvent.hpp" -#include "PatchImpl.hpp" -#include "InputPort.hpp" -#include "types.hpp" - -namespace Raul { - template <typename T> class ListNode; - template <typename T> class Array; -} - -namespace Ingen { -namespace Engine { - -class PatchImpl; -class NodeImpl; -class ConnectionImpl; -class PortImpl; -class InputPort; -class OutputPort; -class CompiledPatch; - -namespace Events { - -/** Make a Connection between two Ports. - * - * \ingroup engine - */ -class Connect : public QueuedEvent -{ -public: - Connect(Engine& engine, SharedPtr<Request> request, SampleCount timestamp, const Raul::Path& src_port_path, const Raul::Path& dst_port_path); - - void pre_process(); - void execute(ProcessContext& context); - void post_process(); - -private: - enum ErrorType { - NO_ERROR, - PARENT_PATCH_DIFFERENT, - PORT_NOT_FOUND, - TYPE_MISMATCH, - DIRECTION_MISMATCH, - ALREADY_CONNECTED, - PARENTS_NOT_FOUND - }; - - Raul::Path _src_port_path; - Raul::Path _dst_port_path; - - PatchImpl* _patch; - OutputPort* _src_output_port; - InputPort* _dst_input_port; - - CompiledPatch* _compiled_patch; ///< New process order for Patch - - SharedPtr<ConnectionImpl> _connection; - InputPort::Connections::Node* _port_listnode; - - Raul::Array<BufferFactory::Ref>* _buffers; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Events - -#endif // INGEN_EVENTS_CONNECT_HPP diff --git a/src/engine/events/CreateNode.cpp b/src/engine/events/CreateNode.cpp deleted file mode 100644 index 68e66f0a..00000000 --- a/src/engine/events/CreateNode.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "raul/log.hpp" -#include "raul/Maid.hpp" -#include "raul/Path.hpp" -#include "sord/sordmm.hpp" -#include "shared/LV2URIMap.hpp" -#include "CreateNode.hpp" -#include "Request.hpp" -#include "PatchImpl.hpp" -#include "NodeImpl.hpp" -#include "PluginImpl.hpp" -#include "Engine.hpp" -#include "PatchImpl.hpp" -#include "NodeFactory.hpp" -#include "ClientBroadcaster.hpp" -#include "EngineStore.hpp" -#include "PortImpl.hpp" -#include "Driver.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { -namespace Events { - -CreateNode::CreateNode( - Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - const Path& path, - const URI& plugin_uri, - const Resource::Properties& properties) - : QueuedEvent(engine, request, timestamp) - , _path(path) - , _plugin_uri(plugin_uri) - , _patch(NULL) - , _plugin(NULL) - , _node(NULL) - , _compiled_patch(NULL) - , _node_already_exists(false) - , _polyphonic(false) - , _properties(properties) -{ - const Resource::Properties::const_iterator p = properties.find( - engine.world()->uris()->ingen_polyphonic); - if (p != properties.end() && p->second.type() == Raul::Atom::BOOL - && p->second.get_bool()) - _polyphonic = true; -} - -void -CreateNode::pre_process() -{ - if (_engine.engine_store()->find_object(_path) != NULL) { - _node_already_exists = true; - QueuedEvent::pre_process(); - return; - } - - _patch = _engine.engine_store()->find_patch(_path.parent()); - _plugin = _engine.node_factory()->plugin(_plugin_uri.str()); - - if (_patch && _plugin) { - - _node = _plugin->instantiate(*_engine.buffer_factory(), _path.symbol(), _polyphonic, _patch, _engine); - - if (_node != NULL) { - _node->properties().insert(_properties.begin(), _properties.end()); - _node->activate(*_engine.buffer_factory()); - - // This can be done here because the audio thread doesn't touch the - // node tree - just the process order array - _patch->add_node(new PatchImpl::Nodes::Node(_node)); - _engine.engine_store()->add(_node); - - // FIXME: not really necessary to build process order since it's not connected, - // just append to the list - if (_patch->enabled()) - _compiled_patch = _patch->compile(); - } - } - - if (!_node) - _error = 1; - - QueuedEvent::pre_process(); -} - -void -CreateNode::execute(ProcessContext& context) -{ - QueuedEvent::execute(context); - - if (_node) { - _engine.maid()->push(_patch->compiled_patch()); - _patch->compiled_patch(_compiled_patch); - } -} - -void -CreateNode::post_process() -{ - if (!_request) - return; - - string msg; - if (_node_already_exists) { - msg = string("Could not create node - ").append(_path.str());// + " already exists."; - _request->respond_error(msg); - } else if (_patch == NULL) { - msg = "Could not find patch '" + _path.parent().str() +"' to add node."; - _request->respond_error(msg); - } else if (_plugin == NULL) { - msg = "Unable to load node "; - msg += _path.str() + " (you're missing the plugin " + _plugin_uri.str() + ")"; - _request->respond_error(msg); - } else if (_node == NULL) { - msg = "Failed to instantiate plugin " + _plugin_uri.str(); - _request->respond_error(msg); - } else { - _request->respond_ok(); - _engine.broadcaster()->send_object(_node, true); // yes, send ports - } -} - -} // namespace Engine -} // namespace Ingen -} // namespace Events - diff --git a/src/engine/events/CreateNode.hpp b/src/engine/events/CreateNode.hpp deleted file mode 100644 index 844eca01..00000000 --- a/src/engine/events/CreateNode.hpp +++ /dev/null @@ -1,71 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_EVENTS_CREATENODE_HPP -#define INGEN_EVENTS_CREATENODE_HPP - -#include <string> -#include "QueuedEvent.hpp" -#include "ingen/Resource.hpp" - -namespace Ingen { -namespace Engine { - -class PatchImpl; -class PluginImpl; -class NodeImpl; -class CompiledPatch; - -namespace Events { - -/** An event to load a Node and insert it into a Patch. - * - * \ingroup engine - */ -class CreateNode : public QueuedEvent -{ -public: - CreateNode( - Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - const Raul::Path& node_path, - const Raul::URI& plugin_uri, - const Resource::Properties& properties); - - void pre_process(); - void execute(ProcessContext& context); - void post_process(); - -private: - Raul::Path _path; - Raul::URI _plugin_uri; - PatchImpl* _patch; - PluginImpl* _plugin; - NodeImpl* _node; - CompiledPatch* _compiled_patch; ///< Patch's new process order - bool _node_already_exists; - bool _polyphonic; - - Resource::Properties _properties; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Events - -#endif // INGEN_EVENTS_CREATENODE_HPP diff --git a/src/engine/events/CreatePatch.cpp b/src/engine/events/CreatePatch.cpp deleted file mode 100644 index dcc79513..00000000 --- a/src/engine/events/CreatePatch.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "raul/Maid.hpp" -#include "raul/Path.hpp" -#include "shared/LV2URIMap.hpp" -#include "events/CreatePatch.hpp" -#include "Request.hpp" -#include "PatchImpl.hpp" -#include "NodeImpl.hpp" -#include "PluginImpl.hpp" -#include "Engine.hpp" -#include "ClientBroadcaster.hpp" -#include "Driver.hpp" -#include "EngineStore.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { -namespace Events { - -CreatePatch::CreatePatch( - Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - const Raul::Path& path, - int poly, - const Resource::Properties& properties) - : QueuedEvent(engine, request, timestamp) - , _path(path) - , _patch(NULL) - , _parent(NULL) - , _compiled_patch(NULL) - , _poly(poly) - , _properties(properties) -{ -} - -void -CreatePatch::pre_process() -{ - if (_path.is_root() || _engine.engine_store()->find_object(_path) != NULL) { - _error = OBJECT_EXISTS; - QueuedEvent::pre_process(); - return; - } - - if (_poly < 1) { - _error = INVALID_POLY; - QueuedEvent::pre_process(); - return; - } - - const Path& path = (const Path&)_path; - - _parent = _engine.engine_store()->find_patch(path.parent()); - if (_parent == NULL) { - _error = PARENT_NOT_FOUND; - QueuedEvent::pre_process(); - return; - } - - uint32_t poly = 1; - if (_parent != NULL && _poly > 1 && _poly == static_cast<int>(_parent->internal_poly())) - poly = _poly; - - const Ingen::Shared::LV2URIMap& uris = *_engine.world()->uris().get(); - - _patch = new PatchImpl(_engine, path.symbol(), poly, _parent, - _engine.driver()->sample_rate(), _poly); - _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)); - - if (_parent != NULL) { - _parent->add_node(new PatchImpl::Nodes::Node(_patch)); - - if (_parent->enabled()) - _compiled_patch = _parent->compile(); - } - - _patch->activate(*_engine.buffer_factory()); - - // Insert into EngineStore - //_patch->add_to_store(_engine.engine_store()); - _engine.engine_store()->add(_patch); - - QueuedEvent::pre_process(); -} - -void -CreatePatch::execute(ProcessContext& context) -{ - QueuedEvent::execute(context); - - if (_patch) { - if (!_parent) { - assert(_path.is_root()); - assert(_patch->parent_patch() == NULL); - _engine.driver()->set_root_patch(_patch); - } else { - assert(_parent); - assert(!_path.is_root()); - _engine.maid()->push(_parent->compiled_patch()); - _parent->compiled_patch(_compiled_patch); - } - } -} - -void -CreatePatch::post_process() -{ - string msg; - if (_request) { - switch (_error) { - case NO_ERROR: - _request->respond_ok(); - // Don't send ports/nodes that have been added since prepare() - // (otherwise they would be sent twice) - _engine.broadcaster()->send_object(_patch, false); - break; - case OBJECT_EXISTS: - _request->respond_ok(); - /*string msg = "Unable to create patch: "; - msg.append(_path).append(" already exists."); - _request->respond_error(msg);*/ - break; - case PARENT_NOT_FOUND: - msg = "Unable to create patch: Parent "; - msg.append(Path(_path).parent().str()).append(" not found."); - _request->respond_error(msg); - break; - case INVALID_POLY: - msg = "Unable to create patch "; - msg.append(_path.str()).append(": ").append("Invalid polyphony requested."); - _request->respond_error(msg); - break; - default: - _request->respond_error("Unable to load patch."); - } - } -} - -} // namespace Engine -} // namespace Ingen -} // namespace Events - diff --git a/src/engine/events/CreatePatch.hpp b/src/engine/events/CreatePatch.hpp deleted file mode 100644 index 847583a4..00000000 --- a/src/engine/events/CreatePatch.hpp +++ /dev/null @@ -1,67 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_EVENTS_CREATEPATCH_HPP -#define INGEN_EVENTS_CREATEPATCH_HPP - -#include "QueuedEvent.hpp" -#include "ingen/Resource.hpp" - -namespace Ingen { -namespace Engine { - -class PatchImpl; -class CompiledPatch; - -namespace Events { - -/** Creates a new Patch. - * - * \ingroup engine - */ -class CreatePatch : public QueuedEvent -{ -public: - CreatePatch( - Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - const Raul::Path& path, - int poly, - const Resource::Properties& properties); - - void pre_process(); - void execute(ProcessContext& context); - void post_process(); - -private: - enum ErrorType { NO_ERROR, OBJECT_EXISTS, PARENT_NOT_FOUND, INVALID_POLY }; - - const Raul::Path _path; - PatchImpl* _patch; - PatchImpl* _parent; - CompiledPatch* _compiled_patch; - int _poly; - - Resource::Properties _properties; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Events - -#endif // INGEN_EVENTS_CREATEPATCH_HPP diff --git a/src/engine/events/CreatePort.cpp b/src/engine/events/CreatePort.cpp deleted file mode 100644 index de5b2219..00000000 --- a/src/engine/events/CreatePort.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "raul/Array.hpp" -#include "raul/Atom.hpp" -#include "raul/List.hpp" -#include "raul/Maid.hpp" -#include "raul/Path.hpp" -#include "shared/LV2URIMap.hpp" -#include "ClientBroadcaster.hpp" -#include "ControlBindings.hpp" -#include "CreatePort.hpp" -#include "Driver.hpp" -#include "DuplexPort.hpp" -#include "Engine.hpp" -#include "EngineStore.hpp" -#include "PatchImpl.hpp" -#include "PatchImpl.hpp" -#include "PluginImpl.hpp" -#include "PortImpl.hpp" -#include "Request.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { -namespace Events { - -CreatePort::CreatePort( - Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - const Raul::Path& path, - const Raul::URI& type, - bool is_output, - const Resource::Properties& properties) - : QueuedEvent(engine, request, timestamp, bool(request)) - , _path(path) - , _type(type) - , _is_output(is_output) - , _data_type(type) - , _patch(NULL) - , _patch_port(NULL) - , _driver_port(NULL) - , _properties(properties) -{ - /* This is blocking because of the two different sets of Patch ports, the array used in the - * audio thread (inherited from NodeImpl), and the arrays used in the pre processor thread. - * If two add port events arrive in the same cycle and the second pre processes before the - * first executes, bad things happen (ports are lost). - * - * TODO: fix this using RCU? - */ - - if (_data_type == PortType::UNKNOWN) - _error = UNKNOWN_TYPE; -} - -void -CreatePort::pre_process() -{ - if (_error == UNKNOWN_TYPE || _engine.engine_store()->find_object(_path)) { - QueuedEvent::pre_process(); - return; - } - - _patch = _engine.engine_store()->find_patch(_path.parent()); - - const Ingen::Shared::LV2URIMap& uris = *_engine.world()->uris().get(); - - if (_patch != NULL) { - assert(_patch->path() == _path.parent()); - - size_t buffer_size = _engine.buffer_factory()->default_buffer_size(_data_type); - - const uint32_t old_num_ports = (_patch->external_ports()) - ? _patch->external_ports()->size() - : 0; - - Resource::Properties::const_iterator index_i = _properties.find(uris.lv2_index); - if (index_i == _properties.end()) { - index_i = _properties.insert(make_pair(uris.lv2_index, (int)old_num_ports)); - } else if (index_i->second.type() != Atom::INT - || index_i->second.get_int32() != static_cast<int32_t>(old_num_ports)) { - QueuedEvent::pre_process(); - _error = BAD_INDEX; - return; - } - - Resource::Properties::const_iterator poly_i = _properties.find(uris.ingen_polyphonic); - bool polyphonic = (poly_i != _properties.end() && poly_i->second.type() == Atom::BOOL - && poly_i->second.get_bool()); - - _patch_port = _patch->create_port(*_engine.buffer_factory(), _path.symbol(), _data_type, buffer_size, _is_output, polyphonic); - - _patch_port->properties().insert(_properties.begin(), _properties.end()); - - assert(index_i->second == Atom((int)_patch_port->index())); - - if (_patch_port) { - - if (_is_output) - _patch->add_output(new Raul::List<PortImpl*>::Node(_patch_port)); - else - _patch->add_input(new Raul::List<PortImpl*>::Node(_patch_port)); - - if (_patch->external_ports()) - _ports_array = new Raul::Array<PortImpl*>(old_num_ports + 1, *_patch->external_ports(), NULL); - else - _ports_array = new Raul::Array<PortImpl*>(old_num_ports + 1, NULL); - - _ports_array->at(old_num_ports) = _patch_port; - _engine.engine_store()->add(_patch_port); - - if (!_patch->parent()) - _driver_port = _engine.driver()->create_port( - dynamic_cast<DuplexPort*>(_patch_port)); - - assert(_ports_array->size() == _patch->num_ports()); - - } else { - _error = CREATION_FAILED; - } - } - QueuedEvent::pre_process(); -} - -void -CreatePort::execute(ProcessContext& context) -{ - QueuedEvent::execute(context); - - if (_patch_port) { - _engine.maid()->push(_patch->external_ports()); - _patch->external_ports(_ports_array); - _engine.control_bindings()->port_binding_changed(context, _patch_port); - } - - if (_driver_port) { - _engine.driver()->add_port(_driver_port); - } - - if (_request) - _request->unblock(); -} - -void -CreatePort::post_process() -{ - if (!_request) - return; - - string msg; - switch (_error) { - case NO_ERROR: - _request->respond_ok(); - _engine.broadcaster()->send_object(_patch_port, true); - break; - case BAD_INDEX: - msg = string("Could not create port ") + _path.str() + " (Illegal index given)"; - _request->respond_error(msg); - break; - case UNKNOWN_TYPE: - msg = string("Could not create port ") + _path.str() + " (Unknown type)"; - _request->respond_error(msg); - break; - case CREATION_FAILED: - msg = string("Could not create port ") + _path.str() + " (Creation failed)"; - _request->respond_error(msg); - break; - } -} - -} // namespace Engine -} // namespace Ingen -} // namespace Events - diff --git a/src/engine/events/CreatePort.hpp b/src/engine/events/CreatePort.hpp deleted file mode 100644 index a4be3a30..00000000 --- a/src/engine/events/CreatePort.hpp +++ /dev/null @@ -1,81 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_EVENTS_CREATEPORT_HPP -#define INGEN_EVENTS_CREATEPORT_HPP - -#include "QueuedEvent.hpp" -#include "raul/Path.hpp" -#include "raul/Array.hpp" -#include "ingen/PortType.hpp" -#include "ingen/Resource.hpp" - -namespace Ingen { -namespace Engine { - -class PatchImpl; -class PortImpl; -class DriverPort; - -namespace Events { - -/** An event to add a Port to a Patch. - * - * \ingroup engine - */ -class CreatePort : public QueuedEvent -{ -public: - CreatePort( - Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - const Raul::Path& path, - const Raul::URI& type, - bool is_output, - const Resource::Properties& properties); - - void pre_process(); - void execute(ProcessContext& context); - void post_process(); - -private: - enum ErrorType { - NO_ERROR, - UNKNOWN_TYPE, - BAD_INDEX, - CREATION_FAILED - }; - - Raul::Path _path; - Raul::URI _type; - bool _is_output; - PortType _data_type; - PatchImpl* _patch; - PortImpl* _patch_port; - Raul::Array<PortImpl*>* _ports_array; ///< New (external) ports array for Patch - DriverPort* _driver_port; ///< Driver (eg Jack) port if this is a toplevel port - bool _succeeded; - - Resource::Properties _properties; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Events - -#endif // INGEN_EVENTS_CREATEPORT_HPP diff --git a/src/engine/events/Deactivate.hpp b/src/engine/events/Deactivate.hpp deleted file mode 100644 index 87bfe298..00000000 --- a/src/engine/events/Deactivate.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_EVENTS_DEACTIVATE_HPP -#define INGEN_EVENTS_DEACTIVATE_HPP - -#include "QueuedEvent.hpp" -#include "Engine.hpp" - -namespace Ingen { -namespace Engine { -namespace Events { - -/** Deactivates the engine. - * - * \ingroup engine - */ -class Deactivate : public QueuedEvent -{ -public: - Deactivate(Engine& engine, SharedPtr<Request> request, SampleCount timestamp) - : QueuedEvent(engine, request, timestamp) - {} - - void post_process() { - _request->respond_ok(); - _engine.deactivate(); - } -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Events - -#endif // INGEN_EVENTS_DEACTIVATE_HPP diff --git a/src/engine/events/Delete.cpp b/src/engine/events/Delete.cpp deleted file mode 100644 index 4a6e520b..00000000 --- a/src/engine/events/Delete.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "raul/Maid.hpp" -#include "raul/Path.hpp" -#include "ClientBroadcaster.hpp" -#include "ControlBindings.hpp" -#include "Delete.hpp" -#include "DisconnectAll.hpp" -#include "Driver.hpp" -#include "Engine.hpp" -#include "EngineStore.hpp" -#include "NodeImpl.hpp" -#include "PatchImpl.hpp" -#include "PluginImpl.hpp" -#include "PortImpl.hpp" -#include "Request.hpp" - -using namespace std; - -namespace Ingen { -namespace Engine { -namespace Events { - -Delete::Delete(Engine& engine, - SharedPtr<Request> request, - FrameTime time, - const Raul::URI& uri) - : QueuedEvent(engine, request, time, true) - , _uri(uri) - , _store_iterator(engine.engine_store()->end()) - , _garbage(NULL) - , _driver_port(NULL) - , _patch_node_listnode(NULL) - , _patch_port_listnode(NULL) - , _ports_array(NULL) - , _compiled_patch(NULL) - , _disconnect_event(NULL) -{ - assert(request); - assert(request->source()); - - if (Raul::Path::is_path(uri)) - _path = Raul::Path(uri.str()); -} - -Delete::~Delete() -{ - delete _disconnect_event; -} - -void -Delete::pre_process() -{ - if (_path.is_root() || _path == "path:/control_in" || _path == "path:/control_out") { - QueuedEvent::pre_process(); - return; - } - - _removed_bindings = _engine.control_bindings()->remove(_path); - - _store_iterator = _engine.engine_store()->find(_path); - - if (_store_iterator != _engine.engine_store()->end()) { - _node = PtrCast<NodeImpl>(_store_iterator->second); - - if (!_node) - _port = PtrCast<PortImpl>(_store_iterator->second); - } - - if (_store_iterator != _engine.engine_store()->end()) { - _removed_table = _engine.engine_store()->remove(_store_iterator); - } - - if (_node && !_path.is_root()) { - assert(_node->parent_patch()); - _patch_node_listnode = _node->parent_patch()->remove_node(_path.symbol()); - if (_patch_node_listnode) { - assert(_patch_node_listnode->elem() == _node.get()); - - _disconnect_event = new DisconnectAll(_engine, _node->parent_patch(), _node.get()); - _disconnect_event->pre_process(); - - if (_node->parent_patch()->enabled()) { - // FIXME: is this called multiple times? - _compiled_patch = _node->parent_patch()->compile(); -#ifndef NDEBUG - // Be sure node is removed from process order, so it can be deleted - for (size_t i=0; i < _compiled_patch->size(); ++i) { - assert(_compiled_patch->at(i).node() != _node.get()); - // FIXME: check providers/dependants too - } -#endif - } - } - } else if (_port) { - assert(_port->parent_patch()); - _patch_port_listnode = _port->parent_patch()->remove_port(_path.symbol()); - if (_patch_port_listnode) { - assert(_patch_port_listnode->elem() == _port.get()); - - _disconnect_event = new DisconnectAll(_engine, _port->parent_patch(), _port.get()); - _disconnect_event->pre_process(); - - if (_port->parent_patch()->enabled()) { - // FIXME: is this called multiple times? - _compiled_patch = _port->parent_patch()->compile(); - _ports_array = _port->parent_patch()->build_ports_array(); - assert(_ports_array->size() == _port->parent_patch()->num_ports()); - } - } - - } - - QueuedEvent::pre_process(); -} - -void -Delete::execute(ProcessContext& context) -{ - QueuedEvent::execute(context); - - PatchImpl* parent_patch = NULL; - - if (_patch_node_listnode) { - assert(_node); - - if (_disconnect_event) - _disconnect_event->execute(context); - - parent_patch = _node->parent_patch(); - - } else if (_patch_port_listnode) { - assert(_port); - - if (_disconnect_event) - _disconnect_event->execute(context); - - parent_patch = _port->parent_patch(); - - _engine.maid()->push(_port->parent_patch()->external_ports()); - _port->parent_patch()->external_ports(_ports_array); - - if ( ! _port->parent_patch()->parent()) - _garbage = _engine.driver()->remove_port(_port->path(), &_driver_port); - } - - if (parent_patch) { - _engine.maid()->push(parent_patch->compiled_patch()); - parent_patch->compiled_patch(_compiled_patch); - } - - _request->unblock(); -} - -void -Delete::post_process() -{ - _removed_bindings.reset(); - - if (!Raul::Path::is_path(_uri) - || _path.is_root() || _path == "path:/control_in" || _path == "path:/control_out") { - // XXX: Just ignore? - //_request->respond_error(_path.chop_scheme() + " can not be deleted"); - } else if (!_node && !_port) { - string msg = string("Could not find object ") + _path.chop_scheme() + " to delete"; - _request->respond_error(msg); - } else if (_patch_node_listnode) { - assert(_node); - _node->deactivate(); - _request->respond_ok(); - _engine.broadcaster()->bundle_begin(); - if (_disconnect_event) - _disconnect_event->post_process(); - _engine.broadcaster()->del(_path); - _engine.broadcaster()->bundle_end(); - _engine.maid()->push(_patch_node_listnode); - } else if (_patch_port_listnode) { - assert(_port); - _request->respond_ok(); - _engine.broadcaster()->bundle_begin(); - if (_disconnect_event) - _disconnect_event->post_process(); - _engine.broadcaster()->del(_path); - _engine.broadcaster()->bundle_end(); - _engine.maid()->push(_patch_port_listnode); - } else { - _request->respond_error("Unable to delete object " + _path.chop_scheme()); - } - - if (_driver_port) - _driver_port->destroy(); - - _engine.maid()->push(_garbage); -} - -} // namespace Engine -} // namespace Ingen -} // namespace Events diff --git a/src/engine/events/Delete.hpp b/src/engine/events/Delete.hpp deleted file mode 100644 index f00ad847..00000000 --- a/src/engine/events/Delete.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_EVENTS_DELETE_HPP -#define INGEN_EVENTS_DELETE_HPP - -#include "QueuedEvent.hpp" -#include "EngineStore.hpp" -#include "PatchImpl.hpp" -#include "ControlBindings.hpp" - -namespace Raul { - template<typename T> class Array; - template<typename T> class ListNode; -} - -namespace Ingen { -namespace Engine { - -class GraphObjectImpl; -class NodeImpl; -class PortImpl; -class DriverPort; -class CompiledPatch; - -namespace Events { - -class DisconnectAll; - -/** \page methods - * <h2>DELETE</h2> - * As per WebDAV (RFC4918 S9.6). - * - * Remove an object from the engine and destroy it. - * - * \li All properties of the object are lost - * \li All references to the object are lost (e.g. the parent's reference to - * this child is lost, any connections to the object are removed, etc.) - */ - -/** DELETE a graph object (see \ref methods). - * \ingroup engine - */ -class Delete : public QueuedEvent -{ -public: - Delete(Engine& engine, - SharedPtr<Request> request, - FrameTime timestamp, - const Raul::URI& uri); - - ~Delete(); - - void pre_process(); - void execute(ProcessContext& context); - void post_process(); - -private: - Raul::URI _uri; - Raul::Path _path; - EngineStore::iterator _store_iterator; - SharedPtr<NodeImpl> _node; ///< Non-NULL iff a node - SharedPtr<PortImpl> _port; ///< Non-NULL iff a port - Raul::Deletable* _garbage; - DriverPort* _driver_port; - PatchImpl::Nodes::Node* _patch_node_listnode; - Raul::List<PortImpl*>::Node* _patch_port_listnode; - Raul::Array<PortImpl*>* _ports_array; ///< New (external) ports for Patch - CompiledPatch* _compiled_patch; ///< Patch's new process order - DisconnectAll* _disconnect_event; - - SharedPtr<ControlBindings::Bindings> _removed_bindings; - - SharedPtr< Raul::Table<Raul::Path, SharedPtr<GraphObject> > > _removed_table; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Events - -#endif // INGEN_EVENTS_DELETE_HPP diff --git a/src/engine/events/Disconnect.cpp b/src/engine/events/Disconnect.cpp deleted file mode 100644 index 9618826c..00000000 --- a/src/engine/events/Disconnect.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "raul/log.hpp" -#include "raul/Maid.hpp" -#include "raul/Path.hpp" -#include "events/Disconnect.hpp" -#include "AudioBuffer.hpp" -#include "ClientBroadcaster.hpp" -#include "ConnectionImpl.hpp" -#include "DuplexPort.hpp" -#include "Engine.hpp" -#include "EngineStore.hpp" -#include "InputPort.hpp" -#include "OutputPort.hpp" -#include "PatchImpl.hpp" -#include "PortImpl.hpp" -#include "ProcessContext.hpp" -#include "Request.hpp" -#include "ThreadManager.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { -namespace Events { - -Disconnect::Disconnect( - Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - const Raul::Path& src_port_path, - const Raul::Path& dst_port_path) - : QueuedEvent(engine, request, timestamp) - , _src_port_path(src_port_path) - , _dst_port_path(dst_port_path) - , _patch(NULL) - , _src_port(NULL) - , _dst_port(NULL) - , _impl(NULL) - , _compiled_patch(NULL) -{ -} - -Disconnect::Impl::Impl(Engine& e, - PatchImpl* patch, - OutputPort* s, - InputPort* d) - : _engine(e) - , _src_output_port(s) - , _dst_input_port(d) - , _patch(patch) - , _connection(patch->remove_connection(_src_output_port, _dst_input_port)) - , _buffers(NULL) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - - NodeImpl* const src_node = _src_output_port->parent_node(); - NodeImpl* const dst_node = _dst_input_port->parent_node(); - - for (Raul::List<NodeImpl*>::iterator i = dst_node->providers()->begin(); - i != dst_node->providers()->end(); ++i) { - if ((*i) == src_node) { - delete dst_node->providers()->erase(i); - break; - } - } - - for (Raul::List<NodeImpl*>::iterator i = src_node->dependants()->begin(); - i != src_node->dependants()->end(); ++i) { - if ((*i) == dst_node) { - delete src_node->dependants()->erase(i); - break; - } - } - - _dst_input_port->decrement_num_connections(); - - if (_dst_input_port->num_connections() == 0) { - _buffers = new Raul::Array<BufferFactory::Ref>(_dst_input_port->poly()); - _dst_input_port->get_buffers(*_engine.buffer_factory(), - _buffers, _dst_input_port->poly()); - - const bool is_control = _dst_input_port->is_a(PortType::CONTROL); - const float value = is_control ? _dst_input_port->value().get_float() : 0; - for (uint32_t i = 0; i < _buffers->size(); ++i) { - if (is_control) { - PtrCast<AudioBuffer>(_buffers->at(i))->set_value(value, 0, 0); - } else { - _buffers->at(i)->clear(); - } - } - } - - _connection->pending_disconnection(true); -} - -void -Disconnect::pre_process() -{ - if (_src_port_path.parent().parent() != _dst_port_path.parent().parent() - && _src_port_path.parent() != _dst_port_path.parent().parent() - && _src_port_path.parent().parent() != _dst_port_path.parent()) { - _error = PARENT_PATCH_DIFFERENT; - QueuedEvent::pre_process(); - return; - } - - _src_port = _engine.engine_store()->find_port(_src_port_path); - _dst_port = _engine.engine_store()->find_port(_dst_port_path); - - if (_src_port == NULL || _dst_port == NULL) { - _error = PORT_NOT_FOUND; - QueuedEvent::pre_process(); - return; - } - - NodeImpl* const src_node = _src_port->parent_node(); - NodeImpl* const dst_node = _dst_port->parent_node(); - - // Connection to a patch port from inside the patch - if (src_node->parent_patch() != dst_node->parent_patch()) { - - assert(src_node->parent() == dst_node || dst_node->parent() == src_node); - if (src_node->parent() == dst_node) - _patch = dynamic_cast<PatchImpl*>(dst_node); - else - _patch = dynamic_cast<PatchImpl*>(src_node); - - // Connection from a patch input to a patch output (pass through) - } else if (src_node == dst_node && dynamic_cast<PatchImpl*>(src_node)) { - _patch = dynamic_cast<PatchImpl*>(src_node); - - // Normal connection between nodes with the same parent - } else { - _patch = src_node->parent_patch(); - } - - assert(_patch); - - if (!_patch->has_connection(_src_port, _dst_port)) { - _error = NOT_CONNECTED; - QueuedEvent::pre_process(); - return; - } - - if (src_node == NULL || dst_node == NULL) { - _error = PARENTS_NOT_FOUND; - QueuedEvent::pre_process(); - return; - } - - _impl = new Impl(_engine, - _patch, - dynamic_cast<OutputPort*>(_src_port), - dynamic_cast<InputPort*>(_dst_port)); - - if (_patch->enabled()) - _compiled_patch = _patch->compile(); - - QueuedEvent::pre_process(); -} - -bool -Disconnect::Impl::execute(ProcessContext& context, bool set_dst_buffers) -{ - ThreadManager::assert_thread(THREAD_PROCESS); - - InputPort::Connections::Node* const port_connections_node - = _dst_input_port->remove_connection(context, _src_output_port); - if (!port_connections_node) { - return false; - } - - if (set_dst_buffers) { - if (_buffers) { - _engine.maid()->push(_dst_input_port->set_buffers(_buffers)); - } else { - _dst_input_port->setup_buffers(*_engine.buffer_factory(), - _dst_input_port->poly()); - } - _dst_input_port->connect_buffers(); - } else { - _dst_input_port->recycle_buffers(); - } - - assert(_connection); - assert(port_connections_node->elem() == _connection); - - _engine.maid()->push(port_connections_node); - return true; -} - -void -Disconnect::execute(ProcessContext& context) -{ - QueuedEvent::execute(context); - - if (_error == NO_ERROR) { - if (!_impl->execute(context, true)) { - _error = CONNECTION_NOT_FOUND; - return; - } - - _engine.maid()->push(_patch->compiled_patch()); - _patch->compiled_patch(_compiled_patch); - } -} - -void -Disconnect::post_process() -{ - if (_error == NO_ERROR) { - if (_request) - _request->respond_ok(); - _engine.broadcaster()->disconnect(_src_port->path(), _dst_port->path()); - } else { - string msg("Unable to disconnect "); - msg.append(_src_port_path.str() + " => " + _dst_port_path.str()); - msg.append(" ("); - switch (_error) { - case PARENT_PATCH_DIFFERENT: - msg.append("Ports exist in different patches"); - break; - case PORT_NOT_FOUND: - msg.append("Port not found"); - break; - case TYPE_MISMATCH: - msg.append("Ports have incompatible types"); - break; - case NOT_CONNECTED: - msg.append("Ports are not connected"); - break; - case PARENTS_NOT_FOUND: - msg.append("Parent node not found"); - break; - case CONNECTION_NOT_FOUND: - msg.append("Connection not found"); - break; - default: - break; - } - msg.append(")"); - if (_request) - _request->respond_error(msg); - } - - delete _impl; -} - -} // namespace Engine -} // namespace Ingen -} // namespace Events - diff --git a/src/engine/events/Disconnect.hpp b/src/engine/events/Disconnect.hpp deleted file mode 100644 index 7a22e474..00000000 --- a/src/engine/events/Disconnect.hpp +++ /dev/null @@ -1,106 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_EVENTS_DISCONNECT_HPP -#define INGEN_EVENTS_DISCONNECT_HPP - -#include "raul/Path.hpp" -#include "QueuedEvent.hpp" -#include "types.hpp" -#include "PatchImpl.hpp" -#include "BufferFactory.hpp" - -namespace Raul { - template <typename T> class ListNode; - template <typename T> class Array; -} - -namespace Ingen { -namespace Engine { - -class CompiledPatch; -class InputPort; -class OutputPort; -class PortImpl; - -namespace Events { - -/** Make a Connection between two Ports. - * - * \ingroup engine - */ -class Disconnect : public QueuedEvent -{ -public: - Disconnect( - Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - const Raul::Path& src_port_path, - const Raul::Path& dst_port_path); - - void pre_process(); - void execute(ProcessContext& context); - void post_process(); - - class Impl { - public: - Impl(Engine& e, - PatchImpl* patch, - OutputPort* s, - InputPort* d); - - bool execute(ProcessContext& context, bool set_dst_buffers); - - InputPort* dst_port() { return _dst_input_port; } - - private: - Engine& _engine; - OutputPort* _src_output_port; - InputPort* _dst_input_port; - PatchImpl* _patch; - SharedPtr<ConnectionImpl> _connection; - Raul::Array<BufferFactory::Ref>* _buffers; - }; - -private: - enum ErrorType { - NO_ERROR, - PARENT_PATCH_DIFFERENT, - PORT_NOT_FOUND, - TYPE_MISMATCH, - NOT_CONNECTED, - PARENTS_NOT_FOUND, - CONNECTION_NOT_FOUND - }; - - const Raul::Path _src_port_path; - const Raul::Path _dst_port_path; - - PatchImpl* _patch; - PortImpl* _src_port; - PortImpl* _dst_port; - - Impl* _impl; - CompiledPatch* _compiled_patch; -}; - -} // namespace Events -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_EVENTS_DISCONNECT_HPP diff --git a/src/engine/events/DisconnectAll.cpp b/src/engine/events/DisconnectAll.cpp deleted file mode 100644 index 3509fd04..00000000 --- a/src/engine/events/DisconnectAll.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <boost/format.hpp> - -#include "raul/Array.hpp" -#include "raul/Maid.hpp" -#include "raul/Path.hpp" - -#include "ClientBroadcaster.hpp" -#include "ConnectionImpl.hpp" -#include "Engine.hpp" -#include "EngineStore.hpp" -#include "InputPort.hpp" -#include "NodeImpl.hpp" -#include "OutputPort.hpp" -#include "PatchImpl.hpp" -#include "PortImpl.hpp" -#include "Request.hpp" -#include "events/Disconnect.hpp" -#include "events/DisconnectAll.hpp" -#include "util.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { -namespace Events { - -DisconnectAll::DisconnectAll(Engine& engine, SharedPtr<Request> request, SampleCount timestamp, const Path& parent_path, const Path& node_path) - : QueuedEvent(engine, request, timestamp) - , _parent_path(parent_path) - , _path(node_path) - , _parent(NULL) - , _node(NULL) - , _port(NULL) - , _compiled_patch(NULL) - , _deleting(false) -{ -} - -/** Internal version for use by other events. - */ -DisconnectAll::DisconnectAll(Engine& engine, PatchImpl* parent, GraphObjectImpl* object) - : QueuedEvent(engine) - , _parent_path(parent->path()) - , _path(object->path()) - , _parent(parent) - , _node(dynamic_cast<NodeImpl*>(object)) - , _port(dynamic_cast<PortImpl*>(object)) - , _compiled_patch(NULL) - , _deleting(true) -{ -} - -DisconnectAll::~DisconnectAll() -{ - for (Impls::iterator i = _impls.begin(); i != _impls.end(); ++i) - delete (*i); -} - -void -DisconnectAll::maybe_remove_connection(ConnectionImpl* c) -{ - if (c->pending_disconnection()) - return; - - OutputPort* src = dynamic_cast<OutputPort*>(c->src_port()); - InputPort* dst = dynamic_cast<InputPort*>(c->dst_port()); - - if (_node) { - if (src->parent_node() == _node || dst->parent_node() == _node) { - _impls.push_back(new Disconnect::Impl(_engine, _parent, src, dst)); - } - } else { - assert(_port); - if (src == _port || dst == _port) { - _impls.push_back(new Disconnect::Impl(_engine, _parent, src, dst)); - } - } -} - -void -DisconnectAll::pre_process() -{ - if (!_deleting) { - _parent = _engine.engine_store()->find_patch(_parent_path); - - if (_parent == NULL) { - _error = PARENT_NOT_FOUND; - QueuedEvent::pre_process(); - return; - } - - GraphObjectImpl* object = _engine.engine_store()->find_object(_path); - - if (object == NULL) { - _error = OBJECT_NOT_FOUND; - QueuedEvent::pre_process(); - return; - } - - if (object->parent_patch() != _parent && object->parent()->parent_patch() != _parent) { - _error = INVALID_PARENT_PATH; - QueuedEvent::pre_process(); - return; - } - - // Only one of these will succeed - _node = dynamic_cast<NodeImpl*>(object); - _port = dynamic_cast<PortImpl*>(object); - - assert((_node || _port) && !(_node && _port)); - } - - for (Patch::Connections::const_iterator i = _parent->connections().begin(); - i != _parent->connections().end(); ++i) { - maybe_remove_connection((ConnectionImpl*)i->second.get()); - } - - if (!_deleting && _parent->enabled()) - _compiled_patch = _parent->compile(); - - QueuedEvent::pre_process(); -} - -void -DisconnectAll::execute(ProcessContext& context) -{ - QueuedEvent::execute(context); - - if (_error == NO_ERROR) { - for (Impls::iterator i = _impls.begin(); i != _impls.end(); ++i) { - (*i)->execute(context, - !_deleting || ((*i)->dst_port()->parent_node() != _node)); - } - } - - _engine.maid()->push(_parent->compiled_patch()); - _parent->compiled_patch(_compiled_patch); -} - -void -DisconnectAll::post_process() -{ - if (_error == NO_ERROR) { - if (_request) - _request->respond_ok(); - _engine.broadcaster()->disconnect_all(_parent_path, _path); - } else { - if (_request) { - boost::format fmt("Unable to disconnect %1% (%2%)"); - fmt % _path; - switch (_error) { - case INVALID_PARENT_PATH: - fmt % string("Invalid parent path: ").append(_parent_path.str()); - break; - case PARENT_NOT_FOUND: - fmt % string("Unable to find parent: ").append(_parent_path.str()); - break; - case OBJECT_NOT_FOUND: - fmt % string("Unable to find object"); - default: - break; - } - _request->respond_error(fmt.str()); - } - } -} - -} // namespace Engine -} // namespace Ingen -} // namespace Events - diff --git a/src/engine/events/DisconnectAll.hpp b/src/engine/events/DisconnectAll.hpp deleted file mode 100644 index b5dc258c..00000000 --- a/src/engine/events/DisconnectAll.hpp +++ /dev/null @@ -1,93 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_EVENTS_DISCONNECTALL_HPP -#define INGEN_EVENTS_DISCONNECTALL_HPP - -#include <list> - -#include "raul/Path.hpp" - -#include "Disconnect.hpp" -#include "QueuedEvent.hpp" - -namespace Ingen { -namespace Engine { - -class CompiledPatch; -class NodeImpl; -class PatchImpl; -class PortImpl; - -namespace Events { - -class Disconnect; - -/** An event to disconnect all connections to a Node. - * - * \ingroup engine - */ -class DisconnectAll : public QueuedEvent -{ -public: - DisconnectAll( - Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - const Raul::Path& parent, - const Raul::Path& object); - - DisconnectAll( - Engine& engine, - PatchImpl* parent, - GraphObjectImpl* object); - - ~DisconnectAll(); - - void pre_process(); - void execute(ProcessContext& context); - void post_process(); - -private: - enum ErrorType { - NO_ERROR, - INVALID_PARENT_PATH, - PARENT_NOT_FOUND, - OBJECT_NOT_FOUND, - }; - - void maybe_remove_connection(ConnectionImpl* c); - - Raul::Path _parent_path; - Raul::Path _path; - PatchImpl* _parent; - NodeImpl* _node; - PortImpl* _port; - - typedef std::list<Disconnect::Impl*> Impls; - Impls _impls; - - CompiledPatch* _compiled_patch; ///< New process order for Patch - - bool _deleting; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Events - -#endif // INGEN_EVENTS_DISCONNECTALL_HPP diff --git a/src/engine/events/Get.cpp b/src/engine/events/Get.cpp deleted file mode 100644 index 7425dd8a..00000000 --- a/src/engine/events/Get.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "Get.hpp" -#include "ingen/ClientInterface.hpp" -#include "Request.hpp" -#include "Engine.hpp" -#include "EngineStore.hpp" -#include "ClientBroadcaster.hpp" -#include "PatchImpl.hpp" -#include "NodeImpl.hpp" -#include "PortImpl.hpp" -#include "ObjectSender.hpp" -#include "ProcessContext.hpp" - -using namespace Raul; - -namespace Ingen { -namespace Engine { -namespace Events { - -Get::Get( - Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - const URI& uri) - : QueuedEvent(engine, request, timestamp) - , _uri(uri) - , _object(NULL) - , _plugin(NULL) -{ -} - -void -Get::pre_process() -{ - if (_uri == "ingen:plugins") { - _plugins = _engine.node_factory()->plugins(); - } else if (Path::is_valid(_uri.str())) { - _object = _engine.engine_store()->find_object(Path(_uri.str())); - } else { - _plugin = _engine.node_factory()->plugin(_uri); - } - - QueuedEvent::pre_process(); -} - -void -Get::post_process() -{ - if (_uri == "ingen:plugins") { - _request->respond_ok(); - _engine.broadcaster()->send_plugins_to(_request->client(), _plugins); - } else if (!_object && !_plugin) { - _request->respond_error("Unable to find object requested."); - } else if (_request->client()) { - _request->respond_ok(); - if (_object) - ObjectSender::send_object(_request->client(), _object, true); - else if (_plugin) - _request->client()->put(_uri, _plugin->properties()); - } else { - _request->respond_error("Unable to find client to send object."); - } -} - -} // namespace Engine -} // namespace Ingen -} // namespace Events - diff --git a/src/engine/events/Get.hpp b/src/engine/events/Get.hpp deleted file mode 100644 index 56bc5f17..00000000 --- a/src/engine/events/Get.hpp +++ /dev/null @@ -1,60 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_EVENTS_GET_HPP -#define INGEN_EVENTS_GET_HPP - -#include "QueuedEvent.hpp" -#include "NodeFactory.hpp" -#include "types.hpp" - -namespace Ingen { -namespace Engine { - -class GraphObjectImpl; -class PluginImpl; - -namespace Events { - -/** A request from a client to send an object. - * - * \ingroup engine - */ -class Get : public QueuedEvent -{ -public: - Get( - Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - const Raul::URI& uri); - - void pre_process(); - void post_process(); - -private: - const Raul::URI _uri; - GraphObjectImpl* _object; - const PluginImpl* _plugin; - NodeFactory::Plugins _plugins; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Events - -#endif // INGEN_EVENTS_GET_HPP diff --git a/src/engine/events/Move.cpp b/src/engine/events/Move.cpp deleted file mode 100644 index bccb3856..00000000 --- a/src/engine/events/Move.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "raul/Path.hpp" -#include "events/Move.hpp" -#include "ClientBroadcaster.hpp" -#include "Engine.hpp" -#include "NodeImpl.hpp" -#include "EngineStore.hpp" -#include "PatchImpl.hpp" -#include "Request.hpp" -#include "Driver.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { -namespace Events { - -Move::Move(Engine& engine, SharedPtr<Request> request, SampleCount timestamp, const Path& path, const Path& new_path) - : QueuedEvent(engine, request, timestamp) - , _old_path(path) - , _new_path(new_path) - , _parent_patch(NULL) - , _store_iterator(engine.engine_store()->end()) -{ -} - -Move::~Move() -{ -} - -void -Move::pre_process() -{ - if (!_old_path.parent().is_parent_of(_new_path)) { - _error = PARENT_DIFFERS; - QueuedEvent::pre_process(); - return; - } - _store_iterator = _engine.engine_store()->find(_old_path); - if (_store_iterator == _engine.engine_store()->end()) { - _error = OBJECT_NOT_FOUND; - QueuedEvent::pre_process(); - return; - } - - if (_engine.engine_store()->find_object(_new_path)) { - _error = OBJECT_EXISTS; - QueuedEvent::pre_process(); - return; - } - - SharedPtr< Table<Path, SharedPtr<GraphObject> > > removed - = _engine.engine_store()->remove(_store_iterator); - - assert(removed->size() > 0); - - for (Table<Path, SharedPtr<GraphObject> >::iterator i = removed->begin(); i != removed->end(); ++i) { - const Path& child_old_path = i->first; - assert(Path::descendant_comparator(_old_path, child_old_path)); - - Path child_new_path; - if (child_old_path == _old_path) - child_new_path = _new_path; - else - child_new_path = Path(_new_path).base() + child_old_path.substr(_old_path.length()+1); - - PtrCast<GraphObjectImpl>(i->second)->set_path(child_new_path); - i->first = child_new_path; - } - - _engine.engine_store()->add(*removed.get()); - - QueuedEvent::pre_process(); -} - -void -Move::execute(ProcessContext& context) -{ - QueuedEvent::execute(context); - - SharedPtr<PortImpl> port = PtrCast<PortImpl>(_store_iterator->second); - if (port && port->parent()->parent() == NULL) { - DriverPort* driver_port = _engine.driver()->driver_port(_new_path); - if (driver_port) - driver_port->move(_new_path); - } -} - -void -Move::post_process() -{ - string msg = "Unable to rename object - "; - - if (_error == NO_ERROR) { - _request->respond_ok(); - _engine.broadcaster()->move(_old_path, _new_path); - } else { - if (_error == OBJECT_EXISTS) - msg.append("Object already exists at ").append(_new_path.str()); - else if (_error == OBJECT_NOT_FOUND) - msg.append("Could not find object ").append(_old_path.str()); - else if (_error == OBJECT_NOT_RENAMABLE) - msg.append(_old_path.str()).append(" is not renamable"); - else if (_error == PARENT_DIFFERS) - msg.append(_new_path.str()).append(" is a child of a different patch"); - - _request->respond_error(msg); - } -} - -} // namespace Engine -} // namespace Ingen -} // namespace Events diff --git a/src/engine/events/Move.hpp b/src/engine/events/Move.hpp deleted file mode 100644 index 03e7e1a6..00000000 --- a/src/engine/events/Move.hpp +++ /dev/null @@ -1,79 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_EVENTS_MOVE_HPP -#define INGEN_EVENTS_MOVE_HPP - -#include "raul/Path.hpp" -#include "QueuedEvent.hpp" -#include "EngineStore.hpp" - -namespace Ingen { -namespace Engine { - -class PatchImpl; - -namespace Events { - -/** \page methods - * <h2>MOVE</h2> - * As per WebDAV (RFC4918 S9.9). - * - * Move an object from its current location and insert it at a new location - * in a single operation. - * - * MOVE to a path with a different parent is currently not supported. - */ - -/** MOVE a graph object to a new path (see \ref methods). - * \ingroup engine - */ -class Move : public QueuedEvent -{ -public: - Move( - Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - const Raul::Path& old_path, - const Raul::Path& new_path); - ~Move(); - - void pre_process(); - void execute(ProcessContext& context); - void post_process(); - -private: - enum ErrorType { - NO_ERROR, - OBJECT_NOT_FOUND, - OBJECT_EXISTS, - OBJECT_NOT_RENAMABLE, - PARENT_DIFFERS - }; - - Raul::Path _old_path; - Raul::Path _new_path; - PatchImpl* _parent_patch; - EngineStore::iterator _store_iterator; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Events - -#endif // INGEN_EVENTS_MOVE_HPP diff --git a/src/engine/events/Ping.hpp b/src/engine/events/Ping.hpp deleted file mode 100644 index ad4e1361..00000000 --- a/src/engine/events/Ping.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_EVENTS_PING_HPP -#define INGEN_EVENTS_PING_HPP - -#include "QueuedEvent.hpp" -#include "types.hpp" -#include "Request.hpp" - -namespace Ingen { -namespace Engine { - -class PortImpl; - -namespace Events { - -/** A ping that travels through the pre-processed event queue before responding - * (useful for the order guarantee). - * - * \ingroup engine - */ -class Ping : public QueuedEvent -{ -public: - Ping(Engine& engine, SharedPtr<Request> request, SampleCount timestamp) - : QueuedEvent(engine, request, timestamp) - {} - - void post_process() { _request->respond_ok(); } -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Events - -#endif // INGEN_EVENTS_PING_HPP diff --git a/src/engine/events/RegisterClient.cpp b/src/engine/events/RegisterClient.cpp deleted file mode 100644 index 50916e6a..00000000 --- a/src/engine/events/RegisterClient.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "Request.hpp" -#include "events/RegisterClient.hpp" -#include "Engine.hpp" -#include "ClientBroadcaster.hpp" - -using namespace Raul; - -namespace Ingen { -namespace Engine { -namespace Events { - -RegisterClient::RegisterClient(Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - const URI& uri, - ClientInterface* client) - : QueuedEvent(engine, request, timestamp) - , _uri(uri) - , _client(client) -{ -} - -void -RegisterClient::pre_process() -{ - _engine.broadcaster()->register_client(_uri, _client); - - QueuedEvent::pre_process(); -} - -void -RegisterClient::post_process() -{ - _request->respond_ok(); -} - -} // namespace Engine -} // namespace Ingen -} // namespace Events - diff --git a/src/engine/events/RegisterClient.hpp b/src/engine/events/RegisterClient.hpp deleted file mode 100644 index 5e5c6a15..00000000 --- a/src/engine/events/RegisterClient.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_EVENTS_REGISTERCLIENT_HPP -#define INGEN_EVENTS_REGISTERCLIENT_HPP - -#include "raul/URI.hpp" -#include "ingen/ClientInterface.hpp" -#include "QueuedEvent.hpp" - -namespace Ingen { -namespace Engine { -namespace Events { - -/** Registers a new client with the OSC system, so it can receive updates. - * - * \ingroup engine - */ -class RegisterClient : public QueuedEvent -{ -public: - RegisterClient(Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - const Raul::URI& uri, - ClientInterface* client); - - void pre_process(); - void post_process(); - -private: - Raul::URI _uri; - ClientInterface* _client; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Events - -#endif // INGEN_EVENTS_REGISTERCLIENT_HPP diff --git a/src/engine/events/RequestMetadata.cpp b/src/engine/events/RequestMetadata.cpp deleted file mode 100644 index c5642104..00000000 --- a/src/engine/events/RequestMetadata.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "raul/IntrusivePtr.hpp" -#include "ingen/ClientInterface.hpp" -#include "events/RequestMetadata.hpp" -#include "shared/LV2Atom.hpp" -#include "shared/LV2URIMap.hpp" -#include "AudioBuffer.hpp" -#include "ClientBroadcaster.hpp" -#include "Engine.hpp" -#include "EngineStore.hpp" -#include "GraphObjectImpl.hpp" -#include "ObjectBuffer.hpp" -#include "PluginImpl.hpp" -#include "PortImpl.hpp" -#include "ProcessContext.hpp" -#include "Request.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { -namespace Events { - -RequestMetadata::RequestMetadata(Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - Resource::Graph ctx, - const URI& subject, - const URI& key) - : QueuedEvent(engine, request, timestamp) - , _special_type(NONE) - , _uri(subject) - , _key(key) - , _resource(0) - , _context(ctx) -{ -} - -void -RequestMetadata::pre_process() -{ - const bool is_object = Path::is_path(_uri); - if (_request->client()) { - if (is_object) - _resource = _engine.engine_store()->find_object(Path(_uri.str())); - else - _resource = _engine.node_factory()->plugin(_uri); - - if (!_resource) { - QueuedEvent::pre_process(); - return; - } - } - - GraphObjectImpl* obj = dynamic_cast<GraphObjectImpl*>(_resource); - if (obj) { - if (_key == _engine.world()->uris()->ingen_value) - _special_type = PORT_VALUE; - else - _value = obj->get_property(_key); - } else { - _value = _resource->get_property(_key); - } - - QueuedEvent::pre_process(); -} - -void -RequestMetadata::execute(ProcessContext& context) -{ - QueuedEvent::execute(context); - if (_special_type == PORT_VALUE) { - PortImpl* port = dynamic_cast<PortImpl*>(_resource); - if (port) { - IntrusivePtr<AudioBuffer> abuf = PtrCast<AudioBuffer>(port->buffer(0)); - if (abuf) { - _value = abuf->value_at(0); - } else { - IntrusivePtr<ObjectBuffer> obuf = PtrCast<ObjectBuffer>(port->buffer(0)); - if (obuf) { - Ingen::Shared::LV2Atom::to_atom(*_engine.world()->uris().get(), - obuf->atom(), - _value); - } - } - } else { - _resource = 0; - } - } -} - -void -RequestMetadata::post_process() -{ - if (_request->client()) { - if (_special_type == PORT_VALUE) { - if (_resource) { - _request->respond_ok(); - _request->client()->set_property(_uri.str(), - _engine.world()->uris()->ingen_value, _value); - } else { - const string msg = "Get value for non-port " + _uri.str(); - _request->respond_error(msg); - } - } else if (!_resource) { - const string msg = "Unable to find subject " + _uri.str(); - _request->respond_error(msg); - } else { - _request->respond_ok(); - _request->client()->set_property(_uri, _key, _value); - } - } else { - _request->respond_error("Unknown client"); - } -} - -} // namespace Engine -} // namespace Ingen -} // namespace Events - diff --git a/src/engine/events/RequestMetadata.hpp b/src/engine/events/RequestMetadata.hpp deleted file mode 100644 index e1730207..00000000 --- a/src/engine/events/RequestMetadata.hpp +++ /dev/null @@ -1,79 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_EVENTS_REQUESTMETADATA_HPP -#define INGEN_EVENTS_REQUESTMETADATA_HPP - -#include "raul/Atom.hpp" -#include "raul/URI.hpp" - -#include "QueuedEvent.hpp" - -namespace Ingen { - -namespace Shared { class ResourceImpl; } - -namespace Engine { - -class GraphObjectImpl; - -namespace Events { - -/** \page methods - * <h2>GET</h2> - * As per HTTP (RFC2616 S9.3). - * - * Get the description of a graph object. - */ - -/** GET an object (see \ref methods). - * - * \ingroup engine - */ -class RequestMetadata : public QueuedEvent -{ -public: - RequestMetadata(Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - Resource::Graph context, - const Raul::URI& subject, - const Raul::URI& key); - - void pre_process(); - void execute(ProcessContext& context); - void post_process(); - -private: - enum ErrorType { NO_ERROR, NOT_FOUND }; - enum { - NONE, - PORT_VALUE - } _special_type; - - Raul::URI _uri; - Raul::URI _key; - Raul::Atom _value; - Ingen::Shared::ResourceImpl* _resource; - Resource::Graph _context; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Events - -#endif // INGEN_EVENTS_REQUESTMETADATA_HPP diff --git a/src/engine/events/SendBinding.cpp b/src/engine/events/SendBinding.cpp deleted file mode 100644 index b9a43366..00000000 --- a/src/engine/events/SendBinding.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <sstream> -#include "events/SendBinding.hpp" -#include "shared/LV2URIMap.hpp" -#include "Engine.hpp" -#include "PortImpl.hpp" -#include "ClientBroadcaster.hpp" - -using namespace std; - -namespace Ingen { -namespace Engine { -namespace Events { - -void -SendBinding::post_process() -{ - const Ingen::Shared::LV2URIMap& uris = *_engine.world()->uris().get(); - Raul::Atom::DictValue dict; - if (_type == ControlBindings::MIDI_CC) { - dict[uris.rdf_type] = uris.midi_Controller; - dict[uris.midi_controllerNumber] = _num; - } else if (_type == ControlBindings::MIDI_BENDER) { - dict[uris.rdf_type] = uris.midi_Bender; - } else if (_type == ControlBindings::MIDI_CHANNEL_PRESSURE) { - dict[uris.rdf_type] = uris.midi_ChannelPressure; - } else if (_type == ControlBindings::MIDI_NOTE) { - dict[uris.rdf_type] = uris.midi_Note; - dict[uris.midi_noteNumber] = _num; - } - // TODO: other event types - _port->set_property(uris.ingen_controlBinding, dict); // FIXME: thread unsafe - _engine.broadcaster()->set_property(_port->path(), uris.ingen_controlBinding, dict); -} - -} // namespace Engine -} // namespace Ingen -} // namespace Events - diff --git a/src/engine/events/SendBinding.hpp b/src/engine/events/SendBinding.hpp deleted file mode 100644 index 1cd38ff2..00000000 --- a/src/engine/events/SendBinding.hpp +++ /dev/null @@ -1,86 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_EVENTS_SENDBINDING_HPP -#define INGEN_EVENTS_SENDBINDING_HPP - -#include "engine/Event.hpp" -#include "engine/ControlBindings.hpp" -#include "engine/types.hpp" - -namespace Ingen { -namespace Engine { - -class PortImpl; - -namespace Events { - -/** A special event used internally to send control bindings from the audio thread. - * - * See SendPortValue documentation for details. - * - * \ingroup engine - */ -class SendBinding : public Event -{ -public: - inline SendBinding( - Engine& engine, - SampleCount timestamp, - PortImpl* port, - ControlBindings::Type type, - int16_t num) - : Event(engine, SharedPtr<Request>(), timestamp) - , _port(port) - , _type(type) - , _num(num) - { - assert(_port); - switch (type) { - case ControlBindings::MIDI_CC: - assert(num >= 0 && num < 128); - break; - case ControlBindings::MIDI_RPN: - assert(num >= 0 && num < 16384); - break; - case ControlBindings::MIDI_NRPN: - assert(num >= 0 && num < 16384); - default: - break; - } - } - - inline SendBinding& operator=(const SendBinding& ev) { - _port = ev._port; - _type = ev._type; - _num = ev._num; - return *this; - } - - void post_process(); - -private: - PortImpl* _port; - ControlBindings::Type _type; - int16_t _num; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Events - -#endif // INGEN_EVENTS_SENDBINDING_HPP diff --git a/src/engine/events/SendPortActivity.cpp b/src/engine/events/SendPortActivity.cpp deleted file mode 100644 index e202c519..00000000 --- a/src/engine/events/SendPortActivity.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "events/SendPortActivity.hpp" -#include "Engine.hpp" -#include "PortImpl.hpp" -#include "ClientBroadcaster.hpp" - -namespace Ingen { -namespace Engine { -namespace Events { - -void -SendPortActivity::post_process() -{ - _engine.broadcaster()->activity(_port->path()); -} - -} // namespace Engine -} // namespace Ingen -} // namespace Events - diff --git a/src/engine/events/SendPortActivity.hpp b/src/engine/events/SendPortActivity.hpp deleted file mode 100644 index a99081ba..00000000 --- a/src/engine/events/SendPortActivity.hpp +++ /dev/null @@ -1,69 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_EVENTS_SENDPORTACTIVITY_HPP -#define INGEN_EVENTS_SENDPORTACTIVITY_HPP - -#include "Event.hpp" -#include "types.hpp" - -namespace Ingen { -namespace Engine { - -class PortImpl; - -namespace Events { - -/** A special event used internally to send port activity notification (e.g. - * MIDI event activity) from the audio thread. - * - * This is created in the audio thread (directly in a ringbuffer, not new'd) - * for processing in the post processing thread (unlike normal events which - * are created in the pre-processor thread then run through the audio - * thread). This event's job is done entirely in post_process. - * - * This only really makes sense for message ports. - * - * \ingroup engine - */ -class SendPortActivity : public Event -{ -public: - inline SendPortActivity(Engine& engine, - SampleCount timestamp, - PortImpl* port) - : Event(engine, SharedPtr<Request>(), timestamp) - , _port(port) - { - } - - inline SendPortActivity& operator=(const SendPortActivity& ev) { - _port = ev._port; - return *this; - } - - void post_process(); - -private: - PortImpl* _port; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Events - -#endif // INGEN_EVENTS_SENDPORTACTIVITY_HPP diff --git a/src/engine/events/SendPortValue.cpp b/src/engine/events/SendPortValue.cpp deleted file mode 100644 index 9ac60a05..00000000 --- a/src/engine/events/SendPortValue.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <sstream> -#include "events/SendPortValue.hpp" -#include "shared/LV2URIMap.hpp" -#include "Engine.hpp" -#include "PortImpl.hpp" -#include "ClientBroadcaster.hpp" - -using namespace std; - -namespace Ingen { -namespace Engine { -namespace Events { - -void -SendPortValue::post_process() -{ - _engine.broadcaster()->set_property( - _port->path(), - _engine.world()->uris()->ingen_value, _value); -} - -} // namespace Engine -} // namespace Ingen -} // namespace Events - diff --git a/src/engine/events/SendPortValue.hpp b/src/engine/events/SendPortValue.hpp deleted file mode 100644 index 3ed1275e..00000000 --- a/src/engine/events/SendPortValue.hpp +++ /dev/null @@ -1,82 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_EVENTS_SENDPORTVALUE_HPP -#define INGEN_EVENTS_SENDPORTVALUE_HPP - -#include "raul/Atom.hpp" -#include "engine/Event.hpp" -#include "engine/types.hpp" - -namespace Ingen { -namespace Engine { - -class PortImpl; - -namespace Events { - -/** A special event used internally to send port values from the audio thread. - * - * This is created in the audio thread (using in-place new on a preallocated - * buffer) for processing in the post processing thread (unlike normal events - * which are created in the pre-processor thread then run through the audio - * thread). This event's job is done entirely in post_process. - * - * This only works for control ports right now. - * - * \ingroup engine - */ -class SendPortValue : public Event -{ -public: - inline SendPortValue( - Engine& engine, - SampleCount timestamp, - PortImpl* port, - bool omni, - uint32_t voice_num, - const Raul::Atom& value) - : Event(engine, SharedPtr<Request>(), timestamp) - , _port(port) - , _omni(omni) - , _voice_num(voice_num) - , _value(value) - { - } - - inline SendPortValue& operator=(const SendPortValue& ev) { - _port = ev._port; - _omni = ev._omni; - _voice_num = ev._voice_num; - _value = ev._value; - return *this; - } - - void post_process(); - -private: - PortImpl* _port; - bool _omni; - uint32_t _voice_num; - Raul::Atom _value; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Events - -#endif // INGEN_EVENTS_SENDPORTVALUE_HPP diff --git a/src/engine/events/SetMetadata.cpp b/src/engine/events/SetMetadata.cpp deleted file mode 100644 index 8e7ef2bf..00000000 --- a/src/engine/events/SetMetadata.cpp +++ /dev/null @@ -1,380 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <string> -#include <boost/format.hpp> -#include "raul/log.hpp" -#include "raul/Maid.hpp" -#include "ingen/PortType.hpp" -#include "shared/LV2URIMap.hpp" -#include "ClientBroadcaster.hpp" -#include "ControlBindings.hpp" -#include "CreateNode.hpp" -#include "CreatePatch.hpp" -#include "CreatePort.hpp" -#include "Driver.hpp" -#include "Engine.hpp" -#include "EngineStore.hpp" -#include "GraphObjectImpl.hpp" -#include "PatchImpl.hpp" -#include "PluginImpl.hpp" -#include "PortImpl.hpp" -#include "Request.hpp" -#include "SetMetadata.hpp" -#include "SetPortValue.hpp" - -#define LOG(s) s << "[SetMetadata] " - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { -namespace Events { - -typedef Resource::Properties Properties; - -SetMetadata::SetMetadata( - Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - bool create, - Resource::Graph context, - const URI& subject, - const Properties& properties, - const Properties& remove) - : QueuedEvent(engine, request, timestamp, false) - , _create_event(NULL) - , _subject(subject) - , _properties(properties) - , _remove(remove) - , _object(NULL) - , _patch(NULL) - , _compiled_patch(NULL) - , _create(create) - , _context(context) -{ - if (context != Resource::DEFAULT) { - Resource::set_context(_properties, context); - } - - /* - LOG(info) << "Set " << subject << " : " << context << " {" << endl; - typedef Resource::Properties::const_iterator iterator; - for (iterator i = properties.begin(); i != properties.end(); ++i) - LOG(info) << " " << i->first << " = " << i->second << " :: " << i->second.type() << endl; - LOG(info) << "}" << endl; - - LOG(info) << "Unset " << subject << " {" << endl; - typedef Resource::Properties::const_iterator iterator; - for (iterator i = remove.begin(); i != remove.end(); ++i) - LOG(info) << " " << i->first << " = " << i->second << " :: " << i->second.type() << endl; - LOG(info) << "}" << endl; - */ -} - -SetMetadata::~SetMetadata() -{ - for (SetEvents::iterator i = _set_events.begin(); i != _set_events.end(); ++i) - delete *i; - - delete _create_event; -} - -void -SetMetadata::pre_process() -{ - typedef Properties::const_iterator iterator; - - const bool is_graph_object = Path::is_path(_subject); - - _object = is_graph_object - ? _engine.engine_store()->find_object(Path(_subject.str())) - : static_cast<Shared::ResourceImpl*>(_engine.node_factory()->plugin(_subject)); - - if (!_object && (!is_graph_object || !_create)) { - _error = NOT_FOUND; - QueuedEvent::pre_process(); - return; - } - - const Ingen::Shared::LV2URIMap& uris = *_engine.world()->uris().get(); - - if (is_graph_object && !_object) { - Path path(_subject.str()); - bool is_patch = false, is_node = false, is_port = false, is_output = false; - PortType data_type(PortType::UNKNOWN); - Shared::ResourceImpl::type(uris, _properties, is_patch, is_node, is_port, is_output, data_type); - - // Create a separate request without a source so EventSource isn't unblocked twice - SharedPtr<Request> sub_request(new Request(NULL, _request->client(), _request->id())); - - if (is_patch) { - uint32_t poly = 1; - iterator p = _properties.find(uris.ingen_polyphony); - if (p != _properties.end() && p->second.is_valid() && p->second.type() == Atom::INT) - poly = p->second.get_int32(); - _create_event = new CreatePatch(_engine, sub_request, _time, - path, poly, _properties); - } else if (is_node) { - const iterator p = _properties.find(uris.rdf_instanceOf); - _create_event = new CreateNode(_engine, sub_request, _time, - path, p->second.get_uri(), _properties); - } else if (is_port) { - _blocking = bool(_request); - _create_event = new CreatePort(_engine, sub_request, _time, - path, data_type.uri(), is_output, _properties); - } - if (_create_event) - _create_event->pre_process(); - else - _error = BAD_OBJECT_TYPE; - QueuedEvent::pre_process(); - return; - } - - _types.reserve(_properties.size()); - - GraphObjectImpl* obj = dynamic_cast<GraphObjectImpl*>(_object); - -#if 0 - // If we're replacing (i.e. this is a PUT, not a POST), first remove all properties - // with keys we will later set. This must be done first so a PUT with several properties - // of the same predicate (e.g. rdf:type) retains the multiple values. Only previously - // existing properties should be replaced - if (_replace) - for (Properties::iterator p = _properties.begin(); p != _properties.end(); ++p) - obj->properties().erase(p->first); -#endif - - for (Properties::const_iterator p = _remove.begin(); p != _remove.end(); ++p) { - const Raul::URI& key = p->first; - const Raul::Atom& value = p->second; - if (key == uris.ingen_controlBinding && value == uris.wildcard) { - PortImpl* port = dynamic_cast<PortImpl*>(_object); - if (port) - _old_bindings = _engine.control_bindings()->remove(port); - } - _object->remove_property(key, value); - } - - for (Properties::iterator p = _properties.begin(); p != _properties.end(); ++p) { - const Raul::URI& key = p->first; - const Raul::Atom& value = p->second; - SpecialType op = NONE; - if (obj) { - Resource& resource = *obj; - resource.add_property(key, value); - - PortImpl* port = dynamic_cast<PortImpl*>(_object); - if (port) { - if (key == uris.ingen_broadcast) { - if (value.type() == Atom::BOOL) { - op = ENABLE_BROADCAST; - } else { - _error = BAD_VALUE_TYPE; - } - } else if (key == uris.ingen_value) { - SetPortValue* ev = new SetPortValue(_engine, _request, _time, port, value); - ev->pre_process(); - _set_events.push_back(ev); - } else if (key == uris.ingen_controlBinding) { - if (port->is_a(PortType::CONTROL)) { - if (value == uris.wildcard) { - _engine.control_bindings()->learn(port); - } else if (value.type() == Atom::DICT) { - op = CONTROL_BINDING; - } else { - _error = BAD_VALUE_TYPE; - } - } else { - _error = BAD_OBJECT_TYPE; - } - } - } else if ((_patch = dynamic_cast<PatchImpl*>(_object))) { - if (key == uris.ingen_enabled) { - if (value.type() == Atom::BOOL) { - op = ENABLE; - // FIXME: defer this until all other metadata has been processed - if (value.get_bool() && !_patch->enabled()) - _compiled_patch = _patch->compile(); - } else { - _error = BAD_VALUE_TYPE; - } - } else if (key == uris.ingen_polyphony) { - if (value.type() == Atom::INT) { - op = POLYPHONY; - _blocking = true; - _patch->prepare_internal_poly(*_engine.buffer_factory(), value.get_int32()); - } else { - _error = BAD_VALUE_TYPE; - } - } - } else if (key == uris.ingen_polyphonic) { - PatchImpl* parent = dynamic_cast<PatchImpl*>(obj->parent()); - if (parent) { - if (value.type() == Atom::BOOL) { - op = POLYPHONIC; - _blocking = true; - obj->set_property(key, value.get_bool()); - NodeImpl* node = dynamic_cast<NodeImpl*>(obj); - if (node) - node->set_polyphonic(value.get_bool()); - if (value.get_bool()) { - obj->prepare_poly(*_engine.buffer_factory(), parent->internal_poly()); - } else { - obj->prepare_poly(*_engine.buffer_factory(), 1); - } - } else { - _error = BAD_VALUE_TYPE; - } - } else { - _error = BAD_OBJECT_TYPE; - } - } - } - - if (_error != NO_ERROR) { - _error_predicate += key.str(); - break; - } - - _types.push_back(op); - } - - QueuedEvent::pre_process(); -} - -void -SetMetadata::execute(ProcessContext& context) -{ - if (_error != NO_ERROR) { - QueuedEvent::execute(context); - return; - } - - if (_create_event) { - QueuedEvent::execute(context); - _create_event->execute(context); - if (_blocking) - _request->unblock(); - return; - } - - for (SetEvents::iterator i = _set_events.begin(); i != _set_events.end(); ++i) - (*i)->execute(context); - - GraphObjectImpl* const object = dynamic_cast<GraphObjectImpl*>(_object); - NodeImpl* const node = dynamic_cast<NodeImpl*>(_object); - PortImpl* const port = dynamic_cast<PortImpl*>(_object); - - std::vector<SpecialType>::const_iterator t = _types.begin(); - for (Properties::const_iterator p = _properties.begin(); p != _properties.end(); ++p, ++t) { - const Raul::Atom& value = p->second; - switch (*t) { - case ENABLE_BROADCAST: - if (port) - port->broadcast(value.get_bool()); - break; - case ENABLE: - if (value.get_bool()) { - if (_compiled_patch) { - _engine.maid()->push(_patch->compiled_patch()); - _patch->compiled_patch(_compiled_patch); - } - _patch->enable(); - } else { - _patch->disable(); - } - break; - case POLYPHONIC: - { - PatchImpl* parent = reinterpret_cast<PatchImpl*>(object->parent()); - if (value.get_bool()) - object->apply_poly(*_engine.maid(), parent->internal_poly()); - else - object->apply_poly(*_engine.maid(), 1); - } - break; - case POLYPHONY: - if (_patch->internal_poly() != static_cast<uint32_t>(value.get_int32()) && - !_patch->apply_internal_poly(_engine.driver()->context(), - *_engine.buffer_factory(), - *_engine.maid(), value.get_int32())) { - _error = INTERNAL; - } - break; - case CONTROL_BINDING: - if (port) { - _engine.control_bindings()->port_binding_changed(context, port); - } else if (node) { - if (node->plugin_impl()->type() == Plugin::Internal) { - node->learn(); - } - } - break; - case NONE: - break; - } - } - - QueuedEvent::execute(context); - - if (_blocking) - _request->unblock(); -} - -void -SetMetadata::post_process() -{ - for (SetEvents::iterator i = _set_events.begin(); i != _set_events.end(); ++i) - (*i)->post_process(); - - switch (_error) { - case NO_ERROR: - if (_create_event) - _create_event->post_process(); - else - _request->respond_ok(); - if (_create) - _engine.broadcaster()->put(_subject, _properties, _context); - else - _engine.broadcaster()->delta(_subject, _remove, _properties); - break; - case NOT_FOUND: - _request->respond_error((boost::format( - "Unable to find object `%1%'") % _subject).str()); - break; - case INTERNAL: - _request->respond_error("Internal error"); - break; - case BAD_OBJECT_TYPE: - _request->respond_error((boost::format( - "Bad type for object `%1%'") % _subject).str()); - break; - case BAD_VALUE_TYPE: - _request->respond_error((boost::format( - "Bad metadata value type for subject `%1%' predicate `%2%'") - % _subject % _error_predicate).str()); - break; - } -} - -} // namespace Engine -} // namespace Ingen -} // namespace Events - diff --git a/src/engine/events/SetMetadata.hpp b/src/engine/events/SetMetadata.hpp deleted file mode 100644 index ca2d49ec..00000000 --- a/src/engine/events/SetMetadata.hpp +++ /dev/null @@ -1,124 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_EVENTS_SETMETADATA_HPP -#define INGEN_EVENTS_SETMETADATA_HPP - -#include <vector> -#include "raul/URI.hpp" -#include "shared/ResourceImpl.hpp" -#include "QueuedEvent.hpp" - -namespace Ingen { -namespace Engine { - -class GraphObjectImpl; -class PatchImpl; -class CompiledPatch; - -namespace Events { - -/** \page methods - * <h2>POST</h2> - * As per HTTP (RFC2616 S9.5). - * - * Append properties to a graph object. - * - * An object can have several properties with a single predicate. - * POST appends properties without modifying or removing existing properties. - */ - -/** \page methods - * <h2>PUT</h2> - * As per HTTP (RFC2616 S9.6). - * - * Set properties of a graph object, or create an object. - * - * An object can have several properties with a single predicate. - * \li If the object does not yet exist, the message must contain sufficient - * information to create the object (e.g. known rdf:type properties, etc.) - * \li If the object does exist, a PUT removes all existing object properties - * with predicates that match any property in the message, then adds all - * properties from the message. - */ - -class SetPortValue; - -/** Set properties of a graph object. - * \ingroup engine - */ -class SetMetadata : public QueuedEvent -{ -public: - SetMetadata( - Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - bool create, - Resource::Graph context, - const Raul::URI& subject, - const Resource::Properties& properties, - const Resource::Properties& remove = Resource::Properties()); - - ~SetMetadata(); - - void pre_process(); - void execute(ProcessContext& context); - void post_process(); - -private: - enum ErrorType { - NO_ERROR, - NOT_FOUND, - INTERNAL, - BAD_OBJECT_TYPE, - BAD_VALUE_TYPE - }; - - enum SpecialType { - NONE, - ENABLE, - ENABLE_BROADCAST, - POLYPHONY, - POLYPHONIC, - CONTROL_BINDING - }; - - typedef std::vector<SetPortValue*> SetEvents; - - QueuedEvent* _create_event; - SetEvents _set_events; - std::vector<SpecialType> _types; - std::vector<SpecialType> _remove_types; - Raul::URI _subject; - Resource::Properties _properties; - Resource::Properties _remove; - Ingen::Shared::ResourceImpl* _object; - PatchImpl* _patch; - CompiledPatch* _compiled_patch; - std::string _error_predicate; - bool _create; - Resource::Graph _context; - - SharedPtr<ControlBindings::Bindings> _old_bindings; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Events - -#endif // INGEN_EVENTS_SETMETADATA_HPP diff --git a/src/engine/events/SetPortValue.cpp b/src/engine/events/SetPortValue.cpp deleted file mode 100644 index f68a6cab..00000000 --- a/src/engine/events/SetPortValue.cpp +++ /dev/null @@ -1,223 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <sstream> -#include "raul/log.hpp" -#include "lv2/lv2plug.in/ns/ext/event/event.h" -#include "shared/LV2URIMap.hpp" -#include "shared/LV2Features.hpp" -#include "shared/LV2Atom.hpp" -#include "shared/World.hpp" -#include "AudioBuffer.hpp" -#include "ClientBroadcaster.hpp" -#include "ControlBindings.hpp" -#include "Driver.hpp" -#include "Engine.hpp" -#include "EngineStore.hpp" -#include "EventBuffer.hpp" -#include "MessageContext.hpp" -#include "NodeImpl.hpp" -#include "ObjectBuffer.hpp" -#include "PortImpl.hpp" -#include "ProcessContext.hpp" -#include "ProcessContext.hpp" -#include "Request.hpp" -#include "SetPortValue.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { -namespace Events { - -SetPortValue::SetPortValue(Engine& engine, - SharedPtr<Request> request, - bool queued, - SampleCount timestamp, - const Raul::Path& port_path, - const Raul::Atom& value) - : QueuedEvent(engine, request, timestamp) - , _queued(queued) - , _port_path(port_path) - , _value(value) - , _port(NULL) -{ -} - -/** Internal */ -SetPortValue::SetPortValue(Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - PortImpl* port, - const Raul::Atom& value) - : QueuedEvent(engine, request, timestamp) - , _queued(false) - , _port_path(port->path()) - , _value(value) - , _port(port) -{ -} - -SetPortValue::~SetPortValue() -{ -} - -void -SetPortValue::pre_process() -{ - if (_queued) { - if (_port == NULL) - _port = _engine.engine_store()->find_port(_port_path); - if (_port == NULL) - _error = PORT_NOT_FOUND; - } - - // Port is a message context port, set its value and - // call the plugin's message run function once - if (_port && _port->context() == Context::MESSAGE) { - apply(*_engine.message_context()); - _port->parent_node()->set_port_valid(_port->index()); - _engine.message_context()->run(_port->parent_node(), - _engine.driver()->frame_time() + _engine.driver()->block_length()); - } - - if (_port) { - _port->set_value(_value); - _port->set_property(_engine.world()->uris()->ingen_value, _value); - } - - QueuedEvent::pre_process(); -} - -void -SetPortValue::execute(ProcessContext& context) -{ - Event::execute(context); - assert(_time >= context.start() && _time <= context.end()); - - if (_port && _port->context() == Context::MESSAGE) - return; - - apply(context); - _engine.control_bindings()->port_value_changed(context, _port); -} - -void -SetPortValue::apply(Context& context) -{ - uint32_t start = context.start(); - if (_error == NO_ERROR && !_port) - _port = _engine.engine_store()->find_port(_port_path); - - if (!_port) { - if (_error == NO_ERROR) - _error = PORT_NOT_FOUND; - /*} else if (_port->buffer(0)->capacity() < _data_size) { - _error = NO_SPACE;*/ - } else { - Buffer* const buf = _port->buffer(0).get(); - AudioBuffer* const abuf = dynamic_cast<AudioBuffer*>(buf); - if (abuf) { - if (_value.type() != Atom::FLOAT) { - _error = TYPE_MISMATCH; - return; - } - - for (uint32_t v = 0; v < _port->poly(); ++v) { - ((AudioBuffer*)_port->buffer(v).get())->set_value( - _value.get_float(), start, _time); - } - return; - } - - Ingen::Shared::LV2URIMap& uris = *_engine.world()->uris().get(); - - EventBuffer* const ebuf = dynamic_cast<EventBuffer*>(buf); - if (ebuf && _value.type() == Atom::BLOB) { - const uint32_t frames = std::max(uint32_t(_time - start), ebuf->latest_frames()); - - // Size 0 event, pass it along to the plugin as a typed but empty event - if (_value.data_size() == 0) { - const uint32_t type_id = uris.uri_to_id(NULL, _value.get_blob_type()); - ebuf->append(frames, 0, type_id, 0, NULL); - _port->raise_set_by_user_flag(); - return; - - } else if (!strcmp(_value.get_blob_type(), - "http://lv2plug.in/ns/ext/midi#MidiEvent")) { - ebuf->prepare_write(context); - ebuf->append(frames, 0, - uris.global_to_event(uris.midi_MidiEvent.id).second, - _value.data_size(), - (const uint8_t*)_value.get_blob()); - _port->raise_set_by_user_flag(); - return; - } - } - - ObjectBuffer* const obuf = dynamic_cast<ObjectBuffer*>(buf); - if (obuf) { - obuf->atom()->size = obuf->size() - sizeof(LV2_Atom); - if (Ingen::Shared::LV2Atom::from_atom(uris, _value, obuf->atom())) { - debug << "Converted atom " << _value << " :: " << obuf->atom()->type - << " * " << obuf->atom()->size << " @ " << obuf->atom() << endl; - return; - } else { - warn << "Failed to convert atom to LV2 object" << endl; - } - } - - warn << "Unknown value type " << (int)_value.type() << endl; - } -} - -void -SetPortValue::post_process() -{ - string msg; - std::ostringstream ss; - switch (_error) { - case NO_ERROR: - assert(_port != NULL); - _request->respond_ok(); - _engine.broadcaster()->set_property(_port_path, - _engine.world()->uris()->ingen_value, _value); - break; - case TYPE_MISMATCH: - ss << "Illegal value type " << _value.type() - << " for port " << _port_path << endl; - _request->respond_error(ss.str()); - break; - case PORT_NOT_FOUND: - msg = "Unable to find port "; - msg.append(_port_path.str()).append(" to set value"); - _request->respond_error(msg); - break; - case NO_SPACE: - ss << "Attempt to write " << _value.data_size() << " bytes to " - << _port_path.str() << ", with capacity " - << _port->buffer_size() << endl; - _request->respond_error(ss.str()); - break; - } -} - -} // namespace Engine -} // namespace Ingen -} // namespace Events - diff --git a/src/engine/events/SetPortValue.hpp b/src/engine/events/SetPortValue.hpp deleted file mode 100644 index 78ef0cf4..00000000 --- a/src/engine/events/SetPortValue.hpp +++ /dev/null @@ -1,83 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_EVENTS_SETPORTVALUE_HPP -#define INGEN_EVENTS_SETPORTVALUE_HPP - -#include "raul/Atom.hpp" -#include "QueuedEvent.hpp" -#include "types.hpp" - -namespace Ingen { -namespace Engine { - -class PortImpl; - -namespace Events { - -/** An event to change the value of a port. - * - * This event can either be queued or immediate, depending on the queued - * parameter passed to the constructor. It must be passed to the appropriate - * place (ie queued event passed to the event queue and non-queued event - * processed in the audio thread) or nasty things will happen. - * - * \ingroup engine - */ -class SetPortValue : public QueuedEvent -{ -public: - SetPortValue(Engine& engine, - SharedPtr<Request> request, - bool queued, - SampleCount timestamp, - const Raul::Path& port_path, - const Raul::Atom& value); - - SetPortValue(Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - PortImpl* port, - const Raul::Atom& value); - - ~SetPortValue(); - - void pre_process(); - void execute(ProcessContext& context); - void post_process(); - -private: - enum ErrorType { - NO_ERROR, - PORT_NOT_FOUND, - NO_SPACE, - TYPE_MISMATCH - }; - - void apply(Context& context); - - bool _queued; - const Raul::Path _port_path; - const Raul::Atom _value; - PortImpl* _port; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Events - -#endif // INGEN_EVENTS_SETPORTVALUE_HPP diff --git a/src/engine/events/UnregisterClient.cpp b/src/engine/events/UnregisterClient.cpp deleted file mode 100644 index 6f850596..00000000 --- a/src/engine/events/UnregisterClient.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "ingen/ClientInterface.hpp" -#include "Request.hpp" -#include "UnregisterClient.hpp" -#include "Engine.hpp" -#include "ClientBroadcaster.hpp" - -using namespace Raul; - -namespace Ingen { -namespace Engine { -namespace Events { - -UnregisterClient::UnregisterClient(Engine& engine, SharedPtr<Request> request, SampleCount timestamp, const URI& uri) - : QueuedEvent(engine, request, timestamp) - , _uri(uri) -{ -} - -void -UnregisterClient::post_process() -{ - if (_engine.broadcaster()->unregister_client(_uri)) - _request->respond_ok(); - else - _request->respond_error("Unable to unregister client"); -} - -} // namespace Engine -} // namespace Ingen -} // namespace Events - diff --git a/src/engine/events/UnregisterClient.hpp b/src/engine/events/UnregisterClient.hpp deleted file mode 100644 index 427fc897..00000000 --- a/src/engine/events/UnregisterClient.hpp +++ /dev/null @@ -1,50 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_EVENTS_UNREGISTERCLIENT_HPP -#define INGEN_EVENTS_UNREGISTERCLIENT_HPP - -#include "QueuedEvent.hpp" -#include "raul/URI.hpp" - -namespace Ingen { -namespace Engine { -namespace Events { - -/** Unregisters an OSC client so it no longer receives notifications. - * - * \ingroup engine - */ -class UnregisterClient : public QueuedEvent -{ -public: - UnregisterClient(Engine& engine, - SharedPtr<Request> request, - SampleCount timestamp, - const Raul::URI& uri); - - void post_process(); - -private: - Raul::URI _uri; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Events - -#endif // INGEN_EVENTS_UNREGISTERCLIENT_HPP diff --git a/src/engine/ingen_engine.cpp b/src/engine/ingen_engine.cpp deleted file mode 100644 index c31e5e33..00000000 --- a/src/engine/ingen_engine.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "shared/Module.hpp" -#include "shared/World.hpp" -#include "Engine.hpp" -#include "QueuedEngineInterface.hpp" -#include "util.hpp" - -using namespace Ingen; - -struct IngenEngineModule : public Ingen::Shared::Module { - virtual void load(Ingen::Shared::World* world) { - Engine::set_denormal_flags(); - SharedPtr<Engine::Engine> engine(new Engine::Engine(world)); - world->set_local_engine(engine); - SharedPtr<Engine::QueuedEngineInterface> interface( - new Engine::QueuedEngineInterface(*engine.get(), - engine->event_queue_size())); - world->set_engine(interface); - engine->add_event_source(interface); - assert(world->local_engine() == engine); - } -}; - -extern "C" { - -Ingen::Shared::Module* -ingen_module_load() -{ - return new IngenEngineModule(); -} - -} // extern "C" diff --git a/src/engine/ingen_http.cpp b/src/engine/ingen_http.cpp deleted file mode 100644 index f7153ca2..00000000 --- a/src/engine/ingen_http.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "shared/Module.hpp" -#include "shared/World.hpp" -#include "HTTPEngineReceiver.hpp" -#include "Engine.hpp" - -using namespace std; -using namespace Ingen; - -struct IngenHTTPModule : public Ingen::Shared::Module { - void load(Ingen::Shared::World* world) { - Engine::Engine* engine = (Engine::Engine*)world->local_engine().get(); - SharedPtr<Engine::HTTPEngineReceiver> interface( - new Engine::HTTPEngineReceiver( - *engine, - world->conf()->option("engine-port").get_int32())); - engine->add_event_source(interface); - } -}; - -extern "C" { - -Ingen::Shared::Module* -ingen_module_load() -{ - return new IngenHTTPModule(); -} - -} // extern "C" diff --git a/src/engine/ingen_jack.cpp b/src/engine/ingen_jack.cpp deleted file mode 100644 index e46dd8a6..00000000 --- a/src/engine/ingen_jack.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "shared/Module.hpp" -#include "shared/World.hpp" -#include "JackDriver.hpp" -#include "Engine.hpp" - -using namespace std; -using namespace Ingen; - -struct IngenJackModule : public Ingen::Shared::Module { - void load(Ingen::Shared::World* world) { - Engine::JackDriver* driver = new Engine::JackDriver( - *(Engine::Engine*)world->local_engine().get()); - driver->attach(world->conf()->option("jack-server").get_string(), - world->conf()->option("jack-client").get_string(), NULL); - ((Engine::Engine*)world->local_engine().get())->set_driver( - SharedPtr<Engine::Driver>(driver)); - } -}; - -extern "C" { - -Ingen::Shared::Module* -ingen_module_load() -{ - return new IngenJackModule(); -} - -} // extern "C" diff --git a/src/engine/ingen_lv2.cpp b/src/engine/ingen_lv2.cpp deleted file mode 100644 index c6a250b7..00000000 --- a/src/engine/ingen_lv2.cpp +++ /dev/null @@ -1,422 +0,0 @@ -/* Ingen.LV2 - A thin wrapper which allows Ingen to run as an LV2 plugin. - * Copyright 2008-2011 David Robillard <http://drobilla.net> - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include <stdlib.h> - -#include <string> -#include <vector> - -#include <glib.h> -#include <glibmm/convert.h> -#include <glibmm/miscutils.h> - -#include "lv2/lv2plug.in/ns/lv2core/lv2.h" - -#include "raul/SharedPtr.hpp" -#include "raul/Thread.hpp" -#include "raul/log.hpp" - -#include "engine/AudioBuffer.hpp" -#include "engine/Driver.hpp" -#include "engine/Engine.hpp" -#include "engine/PatchImpl.hpp" -#include "engine/PostProcessor.hpp" -#include "engine/ProcessContext.hpp" -#include "engine/QueuedEngineInterface.hpp" -#include "engine/ThreadManager.hpp" -#include "ingen/EngineInterface.hpp" -#include "shared/World.hpp" -#include "serialisation/Parser.hpp" -#include "shared/Configuration.hpp" -#include "shared/runtime_paths.hpp" - -#include "ingen-config.h" - -/** Record of a patch in this Ingen LV2 bundle */ -struct LV2Patch { - LV2Patch(const std::string& u, const std::string& f); - - const std::string uri; - const std::string filename; - LV2_Descriptor descriptor; -}; - -class Lib { -public: - Lib(); - ~Lib(); - - typedef std::vector< SharedPtr<const LV2Patch> > Patches; - - Patches patches; - Ingen::Shared::Configuration conf; - int argc; - char** argv; -}; - -/** Library state (constructed/destructed on library load/unload) */ -Lib lib; - -namespace Ingen { -namespace Engine { - -class LV2Driver; - -class LV2Port : public DriverPort -{ -public: - LV2Port(LV2Driver* driver, DuplexPort* patch_port) - : DriverPort(patch_port) - , _driver(driver) - , _buffer(NULL) - {} - - // TODO: LV2 dynamic ports - void create() {} - void destroy() {} - void move(const Raul::Path& path) {} - - void pre_process(ProcessContext& context) { - if (!is_input() || !_buffer) - return; - - if (_patch_port->buffer_type() == PortType::AUDIO) { - AudioBuffer* patch_buf = (AudioBuffer*)_patch_port->buffer(0).get(); - patch_buf->copy((Sample*)_buffer, 0, context.nframes() - 1); - } else if (_patch_port->buffer_type() == PortType::EVENTS) { - //Raul::warn << "TODO: LV2 event I/O" << std::endl; - } - } - - void post_process(ProcessContext& context) { - if (is_input() || !_buffer) - return; - - if (_patch_port->buffer_type() == PortType::AUDIO) { - AudioBuffer* patch_buf = (AudioBuffer*)_patch_port->buffer(0).get(); - memcpy((Sample*)_buffer, patch_buf->data(), context.nframes() * sizeof(Sample)); - } else if (_patch_port->buffer_type() == PortType::EVENTS) { - //Raul::warn << "TODO: LV2 event I/O" << std::endl; - } - } - - void* buffer() const { return _buffer; } - void set_buffer(void* buf) { _buffer = buf; } - -private: - LV2Driver* _driver; - void* _buffer; -}; - -class LV2Driver : public Ingen::Engine::Driver { -private: - typedef std::vector<LV2Port*> Ports; - -public: - LV2Driver(Engine& engine, SampleCount buffer_size, SampleCount sample_rate) - : _context(engine) - , _root_patch(NULL) - , _buffer_size(buffer_size) - , _sample_rate(sample_rate) - , _frame_time(0) - {} - - void run(uint32_t nframes) { - _context.locate(_frame_time, nframes, 0); - - for (Ports::iterator i = _ports.begin(); i != _ports.end(); ++i) - (*i)->pre_process(_context); - - _context.engine().process_events(_context); - - if (_root_patch) - _root_patch->process(_context); - - for (Ports::iterator i = _ports.begin(); i != _ports.end(); ++i) - (*i)->post_process(_context); - - _frame_time += nframes; - } - - virtual void set_root_patch(PatchImpl* patch) { _root_patch = patch; } - virtual PatchImpl* root_patch() { return _root_patch; } - - virtual void add_port(DriverPort* port) { - // Note this doesn't have to be realtime safe since there's no dynamic LV2 ports - ThreadManager::assert_thread(THREAD_PROCESS); - assert(dynamic_cast<LV2Port*>(port)); - assert(port->patch_port()->index() == _ports.size()); - _ports.push_back((LV2Port*)port); - } - - virtual Raul::Deletable* remove_port(const Raul::Path& path, - DriverPort** port=NULL) { - // Note this doesn't have to be realtime safe since there's no dynamic LV2 ports - ThreadManager::assert_thread(THREAD_PROCESS); - - for (Ports::iterator i = _ports.begin(); i != _ports.end(); ++i) { - if ((*i)->patch_port()->path() == path) { - _ports.erase(i); - return NULL; - } - } - - Raul::warn << "Unable to find port " << path << std::endl; - return NULL; - } - - virtual bool supports(PortType port_type, EventType event_type) { - return true; - } - - virtual DriverPort* create_port(DuplexPort* patch_port) { - return new LV2Port(this, patch_port); - } - - virtual DriverPort* driver_port(const Raul::Path& path) { - ThreadManager::assert_thread(THREAD_PROCESS); - - for (Ports::iterator i = _ports.begin(); i != _ports.end(); ++i) - if ((*i)->patch_port()->path() == path) - return (*i); - - return NULL; - } - - virtual SampleCount block_length() const { return _buffer_size; } - virtual SampleCount sample_rate() const { return _sample_rate; } - virtual SampleCount frame_time() const { return _frame_time;} - - virtual bool is_realtime() const { return true; } - virtual ProcessContext& context() { return _context; } - - Ports& ports() { return _ports; } - -private: - ProcessContext _context; - PatchImpl* _root_patch; - SampleCount _buffer_size; - SampleCount _sample_rate; - SampleCount _frame_time; - Ports _ports; -}; - -} // namespace Engine -} // namespace Ingen - -extern "C" { - -using namespace Ingen; -using namespace Ingen::Engine; - -/** LV2 plugin library entry point */ -LV2_SYMBOL_EXPORT -const LV2_Descriptor* -lv2_descriptor(uint32_t index) -{ - return index < lib.patches.size() ? &lib.patches[index]->descriptor : NULL; -} - -struct IngenPlugin { - Ingen::Shared::World* world; -}; - -static LV2_Handle -ingen_instantiate(const LV2_Descriptor* descriptor, - double rate, - const char* bundle_path, - const LV2_Feature*const* features) -{ - Shared::set_bundle_path(bundle_path); - - const LV2Patch* patch = NULL; - for (Lib::Patches::iterator i = lib.patches.begin(); i != lib.patches.end(); ++i) { - if (&(*i)->descriptor == descriptor) { - patch = (*i).get(); - break; - } - } - - if (!patch) { - Raul::error << "Could not find patch " << descriptor->URI << std::endl; - return NULL; - } - - IngenPlugin* plugin = (IngenPlugin*)malloc(sizeof(IngenPlugin)); - plugin->world = new Ingen::Shared::World(&lib.conf, lib.argc, lib.argv); - if (!plugin->world->load_module("serialisation")) { - delete plugin->world; - return NULL; - } - - SharedPtr<Engine::Engine> engine(new Engine::Engine(plugin->world)); - plugin->world->set_local_engine(engine); - - SharedPtr<Engine::QueuedEngineInterface> interface( - new Engine::QueuedEngineInterface( - *engine.get(), - engine->event_queue_size())); - - plugin->world->set_engine(interface); - engine->add_event_source(interface); - - Raul::Thread::get().set_context(Engine::THREAD_PRE_PROCESS); - Engine::ThreadManager::single_threaded = true; - - // FIXME: fixed (or at least maximum) buffer size - LV2Driver* driver = new LV2Driver(*engine.get(), rate, 4096); - engine->set_driver(SharedPtr<Ingen::Engine::Driver>(driver)); - - engine->activate(); - Engine::ThreadManager::single_threaded = true; - - ProcessContext context(*engine.get()); - context.locate(0, UINT_MAX, 0); - - engine->post_processor()->set_end_time(UINT_MAX); - - // TODO: Load only necessary plugins - plugin->world->engine()->get("ingen:plugins"); - interface->process(*engine->post_processor(), context, false); - engine->post_processor()->process(); - - plugin->world->parser()->parse_file(plugin->world, - plugin->world->engine().get(), - patch->filename); - - while (!interface->empty()) { - interface->process(*engine->post_processor(), context, false); - engine->post_processor()->process(); - } - - engine->deactivate(); - - return (LV2_Handle)plugin; -} - -static void -ingen_connect_port(LV2_Handle instance, uint32_t port, void* data) -{ - using namespace Ingen::Engine; - - IngenPlugin* me = (IngenPlugin*)instance; - Engine::Engine* engine = (Engine::Engine*)me->world->local_engine().get(); - LV2Driver* driver = (LV2Driver*)engine->driver(); - if (port < driver->ports().size()) { - driver->ports().at(port)->set_buffer(data); - assert(driver->ports().at(port)->patch_port()->index() == port); - } else { - Raul::warn << "Connect to non-existent port " << port << std::endl; - } -} - -static void -ingen_activate(LV2_Handle instance) -{ - IngenPlugin* me = (IngenPlugin*)instance; - me->world->local_engine()->activate(); -} - -static void -ingen_run(LV2_Handle instance, uint32_t sample_count) -{ - IngenPlugin* me = (IngenPlugin*)instance; - Engine::Engine* engine = (Engine::Engine*)me->world->local_engine().get(); - // FIXME: don't do this every call - Raul::Thread::get().set_context(Ingen::Engine::THREAD_PROCESS); - ((LV2Driver*)engine->driver())->run(sample_count); -} - -static void -ingen_deactivate(LV2_Handle instance) -{ - IngenPlugin* me = (IngenPlugin*)instance; - me->world->local_engine()->deactivate(); -} - -static void -ingen_cleanup(LV2_Handle instance) -{ - IngenPlugin* me = (IngenPlugin*)instance; - me->world->set_local_engine(SharedPtr<Ingen::Engine::Engine>()); - me->world->set_engine(SharedPtr<Ingen::EngineInterface>()); - delete me->world; - free(instance); -} - -static const void* -ingen_extension_data(const char* uri) -{ - return NULL; -} - -LV2Patch::LV2Patch(const std::string& u, const std::string& f) - : uri(u) - , filename(f) -{ - descriptor.URI = uri.c_str(); - descriptor.instantiate = ingen_instantiate; - descriptor.connect_port = ingen_connect_port; - descriptor.activate = ingen_activate; - descriptor.run = ingen_run; - descriptor.deactivate = ingen_deactivate; - descriptor.cleanup = ingen_cleanup; - descriptor.extension_data = ingen_extension_data; -} - -/** Library constructor (called on shared library load) */ -Lib::Lib() - : argc(0) - , argv(NULL) -{ - if (!Glib::thread_supported()) - Glib::thread_init(); - - using namespace Ingen; - - Ingen::Shared::set_bundle_path_from_code((void*)&lv2_descriptor); - - Ingen::Shared::World* world = new Ingen::Shared::World(&conf, argc, argv); - if (!world->load_module("serialisation")) { - delete world; - return; - } - - assert(world->parser()); - - typedef Serialisation::Parser::PatchRecords Records; - - Records records(world->parser()->find_patches( - world, Glib::filename_to_uri( - Shared::bundle_file_path("manifest.ttl")))); - - for (Records::iterator i = records.begin(); i != records.end(); ++i) { - patches.push_back( - SharedPtr<const LV2Patch>(new LV2Patch(i->patch_uri.str(), - i->file_uri))); - } - - delete world; -} - -/** Library destructor (called on shared library unload) */ -Lib::~Lib() -{ -} - -} // extern "C" diff --git a/src/engine/ingen_osc.cpp b/src/engine/ingen_osc.cpp deleted file mode 100644 index 252d984e..00000000 --- a/src/engine/ingen_osc.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "shared/Module.hpp" -#include "shared/World.hpp" -#include "OSCEngineReceiver.hpp" -#include "Engine.hpp" - -using namespace std; -using namespace Ingen; - -struct IngenOSCModule : public Ingen::Shared::Module { - void load(Ingen::Shared::World* world) { - Engine::Engine* engine = (Engine::Engine*)world->local_engine().get(); - SharedPtr<Engine::OSCEngineReceiver> interface( - new Engine::OSCEngineReceiver( - *engine, - engine->event_queue_size(), - world->conf()->option("engine-port").get_int32())); - engine->add_event_source(interface); - } -}; - -extern "C" { - -Ingen::Shared::Module* -ingen_module_load() -{ - return new IngenOSCModule(); -} - -} // extern "C" diff --git a/src/engine/internals/Controller.cpp b/src/engine/internals/Controller.cpp deleted file mode 100644 index 15156f08..00000000 --- a/src/engine/internals/Controller.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <math.h> -#include "raul/midi_events.h" -#include "shared/LV2URIMap.hpp" -#include "internals/Controller.hpp" -#include "PostProcessor.hpp" -#include "events/SendPortValue.hpp" -#include "InputPort.hpp" -#include "OutputPort.hpp" -#include "InternalPlugin.hpp" -#include "AudioBuffer.hpp" -#include "ProcessContext.hpp" -#include "EventBuffer.hpp" -#include "util.hpp" - -using namespace std; - -namespace Ingen { -namespace Engine { -namespace Internals { - -InternalPlugin* ControllerNode::internal_plugin(Shared::LV2URIMap& uris) { - return new InternalPlugin(uris, NS_INTERNALS "Controller", "controller"); -} - -ControllerNode::ControllerNode(InternalPlugin* plugin, - BufferFactory& bufs, - const string& path, - bool polyphonic, - PatchImpl* parent, - SampleRate srate) - : NodeImpl(plugin, path, false, parent, srate) - , _learning(false) -{ - const Ingen::Shared::LV2URIMap& uris = bufs.uris(); - _ports = new Raul::Array<PortImpl*>(6); - - _midi_in_port = new InputPort(bufs, this, "input", 0, 1, PortType::EVENTS, Raul::Atom()); - _midi_in_port->set_property(uris.lv2_name, "Input"); - _ports->at(0) = _midi_in_port; - - _param_port = new InputPort(bufs, this, "controller", 1, 1, PortType::CONTROL, 0.0f); - _param_port->set_property(uris.lv2_minimum, 0.0f); - _param_port->set_property(uris.lv2_maximum, 127.0f); - _param_port->set_property(uris.lv2_integer, true); - _param_port->set_property(uris.lv2_name, "Controller"); - _ports->at(1) = _param_port; - - _log_port = new InputPort(bufs, this, "logarithmic", 2, 1, PortType::CONTROL, 0.0f); - _log_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _log_port->set_property(uris.lv2_name, "Logarithmic"); - _ports->at(2) = _log_port; - - _min_port = new InputPort(bufs, this, "minimum", 3, 1, PortType::CONTROL, 0.0f); - _min_port->set_property(uris.lv2_name, "Minimum"); - _ports->at(3) = _min_port; - - _max_port = new InputPort(bufs, this, "maximum", 4, 1, PortType::CONTROL, 1.0f); - _max_port->set_property(uris.lv2_name, "Maximum"); - _ports->at(4) = _max_port; - - _audio_port = new OutputPort(bufs, this, "ar_output", 5, 1, PortType::AUDIO, 0.0f); - _audio_port->set_property(uris.lv2_name, "Output"); - _ports->at(5) = _audio_port; -} - -void -ControllerNode::process(ProcessContext& context) -{ - NodeImpl::pre_process(context); - - uint32_t frames = 0; - uint32_t subframes = 0; - uint16_t type = 0; - uint16_t size = 0; - uint8_t* buf = NULL; - - EventBuffer* const midi_in = (EventBuffer*)_midi_in_port->buffer(0).get(); - - midi_in->rewind(); - - while (midi_in->get_event(&frames, &subframes, &type, &size, &buf)) { - // FIXME: type - if (size >= 3 && (buf[0] & 0xF0) == MIDI_CMD_CONTROL) - control(context, buf[1], buf[2], frames + context.start()); - - midi_in->increment(); - } - - NodeImpl::post_process(context); -} - -void -ControllerNode::control(ProcessContext& context, uint8_t control_num, uint8_t val, FrameTime time) -{ - Sample scaled_value; - - const Sample nval = (val / 127.0f); // normalized [0, 1] - - if (_learning) { - _param_port->set_value(control_num); - ((AudioBuffer*)_param_port->buffer(0).get())->set_value( - (float)control_num, context.start(), context.end()); - _param_port->broadcast_value(context, true); - _learning = false; - } - - const Sample min_port_val = ((AudioBuffer*)_min_port->buffer(0).get())->value_at(0); - const Sample max_port_val = ((AudioBuffer*)_max_port->buffer(0).get())->value_at(0); - const Sample log_port_val = ((AudioBuffer*)_log_port->buffer(0).get())->value_at(0); - - if (log_port_val > 0.0f) { - // haaaaack, stupid negatives and logarithms - Sample log_offset = 0; - if (min_port_val < 0) - log_offset = fabs(min_port_val); - const Sample min = log(min_port_val + 1 + log_offset); - const Sample max = log(max_port_val + 1 + log_offset); - scaled_value = expf(nval * (max - min) + min) - 1 - log_offset; - } else { - scaled_value = ((nval) * (max_port_val - min_port_val)) + min_port_val; - } - - if (control_num == ((AudioBuffer*)_param_port->buffer(0).get())->value_at(0)) - ((AudioBuffer*)_audio_port->buffer(0).get())->set_value(scaled_value, context.start(), time); -} - -} // namespace Internals -} // namespace Engine -} // namespace Ingen - diff --git a/src/engine/internals/Controller.hpp b/src/engine/internals/Controller.hpp deleted file mode 100644 index 54b1d3ac..00000000 --- a/src/engine/internals/Controller.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_INTERNALS_CONTROLLER_HPP -#define INGEN_INTERNALS_CONTROLLER_HPP - -#include <string> -#include "NodeImpl.hpp" - -namespace Ingen { -namespace Engine { - -class InputPort; -class OutputPort; -class InternalPlugin; - -namespace Internals { - -/** MIDI control input node. - * - * 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 -{ -public: - ControllerNode( - InternalPlugin* plugin, - BufferFactory& bufs, - const std::string& path, - bool polyphonic, - PatchImpl* parent, - SampleRate srate); - - void process(ProcessContext& context); - - void control(ProcessContext& context, uint8_t control_num, uint8_t val, FrameTime time); - - void learn() { _learning = true; } - - static InternalPlugin* internal_plugin(Shared::LV2URIMap& uris); - -private: - bool _learning; - - InputPort* _midi_in_port; - InputPort* _param_port; - InputPort* _log_port; - InputPort* _min_port; - InputPort* _max_port; - OutputPort* _audio_port; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Internals - -#endif // INGEN_INTERNALS_CONTROLLER_HPP diff --git a/src/engine/internals/Delay.cpp b/src/engine/internals/Delay.cpp deleted file mode 100644 index bded108a..00000000 --- a/src/engine/internals/Delay.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <cmath> -#include <limits.h> -#include "raul/log.hpp" -#include "raul/Array.hpp" -#include "raul/Maid.hpp" -#include "raul/midi_events.h" -#include "shared/LV2URIMap.hpp" -#include "internals/Delay.hpp" -#include "AudioBuffer.hpp" -#include "Driver.hpp" -#include "EventBuffer.hpp" -#include "InputPort.hpp" -#include "InternalPlugin.hpp" -#include "OutputPort.hpp" -#include "PatchImpl.hpp" -#include "ProcessContext.hpp" -#include "ingen-config.h" -#include "util.hpp" - -#define LOG(s) s << "[DelayNode] " - -#define CALC_DELAY(delaytime) \ - (f_clamp (delaytime * (float)sample_rate, 1.0f, (float)(buffer_mask + 1))) - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { -namespace Internals { - -static const float MAX_DELAY_SECONDS = 8.0f; - -InternalPlugin* DelayNode::internal_plugin(Shared::LV2URIMap& uris) { - return new InternalPlugin(uris, NS_INTERNALS "Delay", "delay"); -} - -DelayNode::DelayNode( - InternalPlugin* plugin, - BufferFactory& bufs, - const std::string& path, - bool polyphonic, - PatchImpl* parent, - SampleRate srate) - : NodeImpl(plugin, path, polyphonic, parent, srate) - , _buffer(0) - , _buffer_length(0) - , _buffer_mask(0) - , _write_phase(0) -{ - const Ingen::Shared::LV2URIMap& uris = bufs.uris(); - _ports = new Raul::Array<PortImpl*>(3); - - const float default_delay = 1.0f; - _last_delay_time = default_delay; - _delay_samples = default_delay; - - _delay_port = new InputPort(bufs, this, "delay", 1, _polyphony, PortType::CONTROL, default_delay); - _delay_port->set_property(uris.lv2_name, "Delay"); - _delay_port->set_property(uris.lv2_default, default_delay); - _delay_port->set_property(uris.lv2_minimum, (float)(1.0/(double)srate)); - _delay_port->set_property(uris.lv2_maximum, MAX_DELAY_SECONDS); - _ports->at(0) = _delay_port; - - _in_port = new InputPort(bufs, this, "in", 0, 1, PortType::AUDIO, 0.0f); - _in_port->set_property(uris.lv2_name, "Input"); - _ports->at(1) = _in_port; - - _out_port = new OutputPort(bufs, this, "out", 0, 1, PortType::AUDIO, 0.0f); - _out_port->set_property(uris.lv2_name, "Output"); - _ports->at(2) = _out_port; - - //_buffer = bufs.get(PortType::AUDIO, bufs.audio_buffer_size(buffer_length_frames), true); - -} - -DelayNode::~DelayNode() -{ - //_buffer.reset(); - free(_buffer); -} - -void -DelayNode::activate(BufferFactory& bufs) -{ - NodeImpl::activate(bufs); - const SampleCount min_size = MAX_DELAY_SECONDS * _srate; - - // Smallest power of two larger than min_size - SampleCount size = 1; - while (size < min_size) - size <<= 1; - - _buffer = (float*)calloc(size, sizeof(float)); - _buffer_mask = size - 1; - _buffer_length = size; - //_buffer->clear(); - _write_phase = 0; -} - -static inline float f_clamp(float x, float a, float b) -{ - const float x1 = fabs(x - a); - const float x2 = fabs(x - b); - - x = x1 + a + b; - x -= x2; - x *= 0.5; - - return x; -} - -static inline float cube_interp(const float fr, const float inm1, const float - in, const float inp1, const float inp2) -{ - return in + 0.5f * fr * (inp1 - inm1 + - fr * (4.0f * inp1 + 2.0f * inm1 - 5.0f * in - inp2 + - fr * (3.0f * (in - inp1) - inm1 + inp2))); -} - -void -DelayNode::process(ProcessContext& context) -{ - AudioBuffer* const delay_buf = (AudioBuffer*)_delay_port->buffer(0).get(); - AudioBuffer* const in_buf = (AudioBuffer*)_in_port->buffer(0).get(); - AudioBuffer* const out_buf = (AudioBuffer*)_out_port->buffer(0).get(); - - NodeImpl::pre_process(context); - - DelayNode* plugin_data = this; - - const float* const in = in_buf->data(); - float* const out = out_buf->data(); - const float delay_time = delay_buf->data()[0]; - const uint32_t buffer_mask = plugin_data->_buffer_mask; - const unsigned int sample_rate = plugin_data->_srate; - float delay_samples = plugin_data->_delay_samples; - long write_phase = plugin_data->_write_phase; - const uint32_t sample_count = context.nframes(); - - if (write_phase == 0) { - _last_delay_time = delay_time; - _delay_samples = delay_samples = CALC_DELAY(delay_time); - } - - if (delay_time == _last_delay_time) { - const long idelay_samples = (long)delay_samples; - const float frac = delay_samples - idelay_samples; - - for (uint32_t i = 0; i < sample_count; i++) { - long read_phase = write_phase - (long)delay_samples; - const float read = cube_interp(frac, - buffer_at(read_phase - 1), - buffer_at(read_phase), - buffer_at(read_phase + 1), - buffer_at(read_phase + 2)); - buffer_at(write_phase++) = in[i]; - out[i] = read; - } - } else { - const float next_delay_samples = CALC_DELAY(delay_time); - const float delay_samples_slope = (next_delay_samples - delay_samples) / sample_count; - - for (uint32_t i = 0; i < sample_count; i++) { - delay_samples += delay_samples_slope; - write_phase++; - const long read_phase = write_phase - (long)delay_samples; - const long idelay_samples = (long)delay_samples; - const float frac = delay_samples - idelay_samples; - const float read = cube_interp(frac, - buffer_at(read_phase - 1), - buffer_at(read_phase), - buffer_at(read_phase + 1), - buffer_at(read_phase + 2)); - buffer_at(write_phase) = in[i]; - out[i] = read; - } - - _last_delay_time = delay_time; - _delay_samples = delay_samples; - } - - _write_phase = write_phase; - - NodeImpl::post_process(context); -} - -} // namespace Internals -} // namespace Engine -} // namespace Ingen - diff --git a/src/engine/internals/Delay.hpp b/src/engine/internals/Delay.hpp deleted file mode 100644 index bc6f2682..00000000 --- a/src/engine/internals/Delay.hpp +++ /dev/null @@ -1,78 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_INTERNALS_DELAY_HPP -#define INGEN_INTERNALS_DELAY_HPP - -#include <string> -#include <math.h> -#include "types.hpp" -#include "NodeImpl.hpp" - -namespace Ingen { -namespace Engine { - -class InputPort; -class OutputPort; -class InternalPlugin; -class BufferFactory; - -namespace Internals { - -class DelayNode : public NodeImpl -{ -public: - DelayNode( - InternalPlugin* plugin, - BufferFactory& bufs, - const std::string& path, - bool polyphonic, - PatchImpl* parent, - SampleRate srate); - - ~DelayNode(); - - void activate(BufferFactory& bufs); - - void process(ProcessContext& context); - - static InternalPlugin* internal_plugin(Shared::LV2URIMap& uris); - - float delay_samples() const { return _delay_samples; } - -private: - inline float& buffer_at(long phase) const { return _buffer[phase & _buffer_mask]; } - - InputPort* _delay_port; - InputPort* _in_port; - OutputPort* _out_port; - - typedef long Phase; - - float* _buffer; - uint32_t _buffer_length; - uint32_t _buffer_mask; - Phase _write_phase; - float _last_delay_time; - float _delay_samples; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Internals - -#endif // INGEN_INTERNALS_DELAY_HPP diff --git a/src/engine/internals/Note.cpp b/src/engine/internals/Note.cpp deleted file mode 100644 index 8545857e..00000000 --- a/src/engine/internals/Note.cpp +++ /dev/null @@ -1,416 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <cmath> -#include "raul/log.hpp" -#include "raul/Array.hpp" -#include "raul/Maid.hpp" -#include "raul/midi_events.h" -#include "shared/LV2URIMap.hpp" -#include "internals/Note.hpp" -#include "AudioBuffer.hpp" -#include "Driver.hpp" -#include "EventBuffer.hpp" -#include "InputPort.hpp" -#include "InternalPlugin.hpp" -#include "OutputPort.hpp" -#include "PatchImpl.hpp" -#include "ProcessContext.hpp" -#include "util.hpp" -#include "ingen-config.h" - -#define LOG(s) s << "[NoteNode] " - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { -namespace Internals { - -InternalPlugin* NoteNode::internal_plugin(Shared::LV2URIMap& uris) { - return new InternalPlugin(uris, NS_INTERNALS "Note", "note"); -} - -NoteNode::NoteNode( - InternalPlugin* plugin, - BufferFactory& bufs, - const std::string& path, - bool polyphonic, - PatchImpl* parent, - SampleRate srate) - : NodeImpl(plugin, path, polyphonic, parent, srate) - , _voices(new Raul::Array<Voice>(_polyphony)) - , _prepared_voices(NULL) - , _sustain(false) -{ - const Ingen::Shared::LV2URIMap& uris = bufs.uris(); - _ports = new Raul::Array<PortImpl*>(5); - - _midi_in_port = new InputPort(bufs, this, "input", 0, 1, PortType::EVENTS, Raul::Atom()); - _midi_in_port->set_property(uris.lv2_name, "Input"); - _ports->at(0) = _midi_in_port; - - _freq_port = new OutputPort(bufs, this, "frequency", 1, _polyphony, PortType::AUDIO, 440.0f); - _freq_port->set_property(uris.lv2_name, "Frequency"); - _ports->at(1) = _freq_port; - - _vel_port = new OutputPort(bufs, this, "velocity", 2, _polyphony, PortType::AUDIO, 0.0f); - _vel_port->set_property(uris.lv2_minimum, 0.0f); - _vel_port->set_property(uris.lv2_maximum, 1.0f); - _vel_port->set_property(uris.lv2_name, "Velocity"); - _ports->at(2) = _vel_port; - - _gate_port = new OutputPort(bufs, this, "gate", 3, _polyphony, PortType::AUDIO, 0.0f); - _gate_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _gate_port->set_property(uris.lv2_name, "Gate"); - _ports->at(3) = _gate_port; - - _trig_port = new OutputPort(bufs, this, "trigger", 4, _polyphony, PortType::AUDIO, 0.0f); - _trig_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _trig_port->set_property(uris.lv2_name, "Trigger"); - _ports->at(4) = _trig_port; -} - -NoteNode::~NoteNode() -{ - delete _voices; -} - -bool -NoteNode::prepare_poly(BufferFactory& bufs, uint32_t poly) -{ - if (!_polyphonic) - return true; - - NodeImpl::prepare_poly(bufs, poly); - - if (_prepared_voices && poly <= _prepared_voices->size()) - return true; - - _prepared_voices = new Raul::Array<Voice>(poly, *_voices, Voice()); - - return true; -} - -bool -NoteNode::apply_poly(Raul::Maid& maid, uint32_t poly) -{ - if (!NodeImpl::apply_poly(maid, poly)) - return false; - - if (_prepared_voices) { - assert(_polyphony <= _prepared_voices->size()); - maid.push(_voices); - _voices = _prepared_voices; - _prepared_voices = NULL; - } - assert(_polyphony <= _voices->size()); - - return true; -} - -void -NoteNode::process(ProcessContext& context) -{ - EventBuffer* const midi_in = (EventBuffer*)_midi_in_port->buffer(0).get(); - NodeImpl::pre_process(context); - - uint32_t frames = 0; - uint32_t subframes = 0; - uint16_t type = 0; - uint16_t size = 0; - uint8_t* buf = NULL; - - midi_in->rewind(); - - if (midi_in->event_count() > 0) - for (midi_in->rewind(); midi_in->get_event(&frames, &subframes, &type, &size, &buf); - midi_in->increment()) { - -#ifdef RAUL_LOG_DEBUG - LOG(debug) << "EVENT TYPE " << type << " @ " << frames << "." << subframes << ": "; - for (uint16_t i = 0; i < size; ++i) - debug << (int)((char)buf[i]) << " "; - debug << endl; -#endif - - if (frames < context.offset()) - continue; - if (frames > context.nframes()) - break; - - const FrameTime time = context.start() + (FrameTime)frames; - - if (size >= 3) { - switch (buf[0] & 0xF0) { - case MIDI_CMD_NOTE_ON: - if (buf[2] == 0) - note_off(context, buf[1], time); - else - note_on(context, buf[1], buf[2], time); - break; - case MIDI_CMD_NOTE_OFF: - note_off(context, buf[1], time); - break; - case MIDI_CMD_CONTROL: - switch (buf[1]) { - case MIDI_CTL_ALL_NOTES_OFF: - case MIDI_CTL_ALL_SOUNDS_OFF: - all_notes_off(context, time); - break; - case MIDI_CTL_SUSTAIN: - if (buf[2] > 63) - sustain_on(context, time); - else - sustain_off(context, time); - break; - case MIDI_CMD_BENDER: - // ? - break; - default: - //warn << "Ignored controller " << buf[1] << endl; - break; - } - break; - default: - //fprintf(stderr, "Unknown (size %d) MIDI event %X\n", size, buf[0]); - break; - } - } else { - //fprintf(stderr, "Unknown (size %d) MIDI event %X\n", size, buf[0]); - } - } - - NodeImpl::post_process(context); -} - -void -NoteNode::note_on(ProcessContext& context, uint8_t note_num, uint8_t velocity, FrameTime time) -{ - assert(time >= context.start() && time <= context.end()); - assert(note_num <= 127); - - Key* key = &_keys[note_num]; - Voice* voice = NULL; - uint32_t voice_num = 0; - - if (key->state != Key::OFF) { -#ifdef RAUL_LOG_DEBUG - LOG(debug) << "Double midi note received" << endl; -#endif - return; - } - - // Look for free voices - for (uint32_t i=0; i < _polyphony; ++i) { - if ((*_voices)[i].state == Voice::Voice::FREE) { - voice = &(*_voices)[i]; - voice_num = i; - break; - } - } - - // If we didn't find a free one, steal the oldest - if (voice == NULL) { - voice_num = 0; - voice = &(*_voices)[0]; - FrameTime oldest_time = (*_voices)[0].time; - for (uint32_t i=1; i < _polyphony; ++i) { - if ((*_voices)[i].time < oldest_time) { - voice = &(*_voices)[i]; - voice_num = i; - oldest_time = voice->time; - } - } - } - assert(voice != NULL); - assert(voice == &(*_voices)[voice_num]); - -#ifdef RAUL_LOG_DEBUG - LOG(debug) << "Note " << (int)note_num << " on @ " << time - << ". Voice " << voice_num << " / " << _polyphony << endl; -#endif - - // Update stolen key, if applicable - if (voice->state == Voice::Voice::ACTIVE) { - assert(_keys[voice->note].state == Key::ON_ASSIGNED); - assert(_keys[voice->note].voice == voice_num); - _keys[voice->note].state = Key::Key::ON_UNASSIGNED; -#ifdef RAUL_LOG_DEBUG - LOG(debug) << "Stole voice " << voice_num << endl; -#endif - } - - // Store key information for later reallocation on note off - key->state = Key::Key::ON_ASSIGNED; - key->voice = voice_num; - key->time = time; - - // Trigger voice - voice->state = Voice::Voice::ACTIVE; - voice->note = note_num; - voice->time = time; - - assert(_keys[voice->note].state == Key::Key::ON_ASSIGNED); - assert(_keys[voice->note].voice == voice_num); - - ((AudioBuffer*)_freq_port->buffer(voice_num).get())->set_value( - note_to_freq(note_num), context.start(), time); - ((AudioBuffer*)_vel_port->buffer(voice_num).get())->set_value( - velocity/127.0, context.start(), time); - ((AudioBuffer*)_gate_port->buffer(voice_num).get())->set_value( - 1.0f, context.start(), time); - - // trigger (one sample) - ((AudioBuffer*)_trig_port->buffer(voice_num).get())->set_value( - 1.0f, context.start(), time); - ((AudioBuffer*)_trig_port->buffer(voice_num).get())->set_value( - 0.0f, context.start(), time + 1); - - assert(key->state == Key::Key::ON_ASSIGNED); - assert(voice->state == Voice::Voice::ACTIVE); - assert(key->voice == voice_num); - assert((*_voices)[key->voice].note == note_num); -} - -void -NoteNode::note_off(ProcessContext& context, uint8_t note_num, FrameTime time) -{ - assert(time >= context.start() && time <= context.end()); - - Key* key = &_keys[note_num]; - -#ifdef RAUL_LOG_DEBUG - debug << "Note " << (int)note_num << " off @ " << time << endl; -#endif - - if (key->state == Key::ON_ASSIGNED) { - // Assigned key, turn off voice and key - if ((*_voices)[key->voice].state == Voice::ACTIVE) { - assert((*_voices)[key->voice].note == note_num); - - if ( ! _sustain) { -#ifdef RAUL_LOG_DEBUG - debug << "Free voice " << key->voice << endl; -#endif - free_voice(context, key->voice, time); - } else { -#ifdef RAUL_LOG_DEBUG - debug << "Hold voice " << key->voice << endl; -#endif - (*_voices)[key->voice].state = Voice::HOLDING; - } - - } else { -#ifdef RAUL_LOG_DEBUG - debug << "WARNING: Assigned key, but voice not active" << endl; -#endif - } - } - - key->state = Key::OFF; -} - -void -NoteNode::free_voice(ProcessContext& context, uint32_t voice, FrameTime time) -{ - assert(time >= context.start() && time <= context.end()); - - // Find a key to reassign to the freed voice (the newest, if there is one) - Key* replace_key = NULL; - uint8_t replace_key_num = 0; - - for (uint8_t i = 0; i <= 127; ++i) { - if (_keys[i].state == Key::ON_UNASSIGNED) { - if (replace_key == NULL || _keys[i].time > replace_key->time) { - replace_key = &_keys[i]; - replace_key_num = i; - } - } - } - - if (replace_key != NULL) { // Found a key to assign to freed voice - assert(&_keys[replace_key_num] == replace_key); - assert(replace_key->state == Key::ON_UNASSIGNED); - - // Change the freq but leave the gate high and don't retrigger - ((AudioBuffer*)_freq_port->buffer(voice).get())->set_value(note_to_freq(replace_key_num), context.start(), time); - - replace_key->state = Key::ON_ASSIGNED; - replace_key->voice = voice; - _keys[(*_voices)[voice].note].state = Key::ON_UNASSIGNED; - (*_voices)[voice].note = replace_key_num; - (*_voices)[voice].state = Voice::ACTIVE; - } else { - // No new note for voice, deactivate (set gate low) -#ifdef RAUL_LOG_DEBUG - LOG(debug) << "Note off: key " << (*_voices)[voice].note << " voice " << voice << endl; -#endif - ((AudioBuffer*)_gate_port->buffer(voice).get())->set_value(0.0f, context.start(), time); - (*_voices)[voice].state = Voice::FREE; - } -} - -void -NoteNode::all_notes_off(ProcessContext& context, FrameTime time) -{ - assert(time >= context.start() && time <= context.end()); - -#ifdef RAUL_LOG_DEBUG - LOG(debug) << "All notes off @ " << time << endl; -#endif - - // FIXME: set all keys to Key::OFF? - - for (uint32_t i = 0; i < _polyphony; ++i) { - ((AudioBuffer*)_gate_port->buffer(i).get())->set_value(0.0f, context.start(), time); - (*_voices)[i].state = Voice::FREE; - } -} - -float -NoteNode::note_to_freq(int num) -{ - static const float A4 = 440.0f; - if (num >= 0 && num <= 119) - return A4 * powf(2.0f, (float)(num - 57.0f) / 12.0f); - return 1.0f; // Frequency of zero causes numerical problems... -} - -void -NoteNode::sustain_on(ProcessContext& context, FrameTime time) -{ - _sustain = true; -} - -void -NoteNode::sustain_off(ProcessContext& context, FrameTime time) -{ - assert(time >= context.start() && time <= context.end()); - - _sustain = false; - - for (uint32_t i=0; i < _polyphony; ++i) - if ((*_voices)[i].state == Voice::HOLDING) - free_voice(context, i, time); -} - -} // namespace Internals -} // namespace Engine -} // namespace Ingen - diff --git a/src/engine/internals/Note.hpp b/src/engine/internals/Note.hpp deleted file mode 100644 index 7a47dc76..00000000 --- a/src/engine/internals/Note.hpp +++ /dev/null @@ -1,101 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_INTERNALS_NOTE_HPP -#define INGEN_INTERNALS_NOTE_HPP - -#include <string> -#include "types.hpp" -#include "NodeImpl.hpp" - -namespace Ingen { -namespace Engine { - -class InputPort; -class OutputPort; -class InternalPlugin; - -namespace Internals { - -/** MIDI note input node. - * - * For pitched instruments like keyboard, etc. - * - * \ingroup engine - */ -class NoteNode : public NodeImpl -{ -public: - NoteNode( - InternalPlugin* plugin, - BufferFactory& bufs, - const std::string& path, - bool polyphonic, - PatchImpl* parent, - SampleRate srate); - - ~NoteNode(); - - bool prepare_poly(BufferFactory& bufs, uint32_t poly); - bool apply_poly(Raul::Maid& maid, uint32_t poly); - - void process(ProcessContext& context); - - void note_on(ProcessContext& context, uint8_t note_num, uint8_t velocity, FrameTime time); - void note_off(ProcessContext& context, uint8_t note_num, FrameTime time); - void all_notes_off(ProcessContext& context, FrameTime time); - - void sustain_on(ProcessContext& context, FrameTime time); - void sustain_off(ProcessContext& context, FrameTime time); - - static InternalPlugin* internal_plugin(Shared::LV2URIMap& uris); - -private: - /** Key, one for each key on the keyboard */ - struct Key { - enum State { OFF, ON_ASSIGNED, ON_UNASSIGNED }; - Key() : state(OFF), voice(0), time(0) {} - State state; uint32_t voice; SampleCount time; - }; - - /** Voice, one of these always exists for each voice */ - struct Voice { - enum State { FREE, ACTIVE, HOLDING }; - Voice() : state(FREE), note(0), time(0) {} - State state; uint8_t note; SampleCount time; - }; - - float note_to_freq(int num); - void free_voice(ProcessContext& context, uint32_t voice, FrameTime time); - - Raul::Array<Voice>* _voices; - Raul::Array<Voice>* _prepared_voices; - Key _keys[128]; - bool _sustain; ///< Whether or not hold pedal is depressed - - InputPort* _midi_in_port; - OutputPort* _freq_port; - OutputPort* _vel_port; - OutputPort* _gate_port; - OutputPort* _trig_port; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Internals - -#endif // INGEN_INTERNALS_NOTE_HPP diff --git a/src/engine/internals/Trigger.cpp b/src/engine/internals/Trigger.cpp deleted file mode 100644 index 55474618..00000000 --- a/src/engine/internals/Trigger.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <cmath> -#include "raul/log.hpp" -#include "raul/midi_events.h" -#include "shared/LV2URIMap.hpp" -#include "internals/Trigger.hpp" -#include "AudioBuffer.hpp" -#include "EventBuffer.hpp" -#include "InputPort.hpp" -#include "InternalPlugin.hpp" -#include "OutputPort.hpp" -#include "ProcessContext.hpp" -#include "util.hpp" -#include "ingen-config.h" - -#define LOG(s) s << "[TriggerNode] " - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Engine { -namespace Internals { - -InternalPlugin* TriggerNode::internal_plugin(Shared::LV2URIMap& uris) { - return new InternalPlugin(uris, NS_INTERNALS "Trigger", "trigger"); -} - -TriggerNode::TriggerNode( - InternalPlugin* plugin, - BufferFactory& bufs, - const std::string& path, - bool polyphonic, - PatchImpl* parent, - SampleRate srate) - : NodeImpl(plugin, path, false, parent, srate) - , _learning(false) -{ - const Ingen::Shared::LV2URIMap& uris = bufs.uris(); - _ports = new Raul::Array<PortImpl*>(5); - - _midi_in_port = new InputPort(bufs, this, "input", 0, 1, PortType::EVENTS, Raul::Atom()); - _midi_in_port->set_property(uris.lv2_name, "Input"); - _ports->at(0) = _midi_in_port; - - _note_port = new InputPort(bufs, this, "note", 1, 1, PortType::CONTROL, 60.0f); - _note_port->set_property(uris.lv2_minimum, 0.0f); - _note_port->set_property(uris.lv2_maximum, 127.0f); - _note_port->set_property(uris.lv2_integer, true); - _note_port->set_property(uris.lv2_name, "Note"); - _ports->at(1) = _note_port; - - _gate_port = new OutputPort(bufs, this, "gate", 2, 1, PortType::AUDIO, 0.0f); - _gate_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _gate_port->set_property(uris.lv2_name, "Gate"); - _ports->at(2) = _gate_port; - - _trig_port = new OutputPort(bufs, this, "trigger", 3, 1, PortType::AUDIO, 0.0f); - _trig_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _trig_port->set_property(uris.lv2_name, "Trigger"); - _ports->at(3) = _trig_port; - - _vel_port = new OutputPort(bufs, this, "velocity", 4, 1, PortType::AUDIO, 0.0f); - _vel_port->set_property(uris.lv2_minimum, 0.0f); - _vel_port->set_property(uris.lv2_maximum, 1.0f); - _vel_port->set_property(uris.lv2_name, "Velocity"); - _ports->at(4) = _vel_port; -} - -void -TriggerNode::process(ProcessContext& context) -{ - NodeImpl::pre_process(context); - - uint32_t frames = 0; - uint32_t subframes = 0; - uint16_t type = 0; - uint16_t size = 0; - uint8_t* buf = NULL; - - EventBuffer* const midi_in = (EventBuffer*)_midi_in_port->buffer(0).get(); - - midi_in->rewind(); - - while (midi_in->get_event(&frames, &subframes, &type, &size, &buf)) { - const FrameTime time = context.start() + (FrameTime)frames; - - if (size >= 3) { - switch (buf[0] & 0xF0) { - case MIDI_CMD_NOTE_ON: - if (buf[2] == 0) - note_off(context, buf[1], time); - else - note_on(context, buf[1], buf[2], time); - break; - case MIDI_CMD_NOTE_OFF: - note_off(context, buf[1], time); - break; - case MIDI_CMD_CONTROL: - if (buf[1] == MIDI_CTL_ALL_NOTES_OFF - || buf[1] == MIDI_CTL_ALL_SOUNDS_OFF) - ((AudioBuffer*)_gate_port->buffer(0).get())->set_value(0.0f, context.start(), time); - default: - break; - } - } - - midi_in->increment(); - } - - NodeImpl::post_process(context); -} - -void -TriggerNode::note_on(ProcessContext& context, uint8_t note_num, uint8_t velocity, FrameTime time) -{ - assert(time >= context.start() && time <= context.end()); - - if (_learning) { - _note_port->set_value(note_num); - ((AudioBuffer*)_note_port->buffer(0).get())->set_value( - (float)note_num, context.start(), context.end()); - _note_port->broadcast_value(context, true); - _learning = false; - } - -#ifdef RAUL_LOG_DEBUG - LOG(debug) << path() << " note " << (int)note_num << " on @ " << time << endl; -#endif - - Sample filter_note = ((AudioBuffer*)_note_port->buffer(0).get())->value_at(0); - if (filter_note >= 0.0 && filter_note < 127.0 && (note_num == (uint8_t)filter_note)) { - ((AudioBuffer*)_gate_port->buffer(0).get())->set_value(1.0f, context.start(), time); - ((AudioBuffer*)_trig_port->buffer(0).get())->set_value(1.0f, context.start(), time); - ((AudioBuffer*)_trig_port->buffer(0).get())->set_value(0.0f, context.start(), time + 1); - ((AudioBuffer*)_vel_port->buffer(0).get())->set_value(velocity / 127.0f, context.start(), time); - assert(((AudioBuffer*)_trig_port->buffer(0).get())->data()[time - context.start()] == 1.0f); - } -} - -void -TriggerNode::note_off(ProcessContext& context, uint8_t note_num, FrameTime time) -{ - assert(time >= context.start() && time <= context.end()); - - if (note_num == lrintf(((AudioBuffer*)_note_port->buffer(0).get())->value_at(0))) - ((AudioBuffer*)_gate_port->buffer(0).get())->set_value(0.0f, context.start(), time); -} - -} // namespace Internals -} // namespace Engine -} // namespace Ingen diff --git a/src/engine/internals/Trigger.hpp b/src/engine/internals/Trigger.hpp deleted file mode 100644 index da796f5e..00000000 --- a/src/engine/internals/Trigger.hpp +++ /dev/null @@ -1,77 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_INTERNALS_TRIGGER_HPP -#define INGEN_INTERNALS_TRIGGER_HPP - -#include <string> -#include "NodeImpl.hpp" - -namespace Ingen { -namespace Engine { - -class InputPort; -class OutputPort; -class InternalPlugin; - -namespace Internals { - -/** MIDI trigger input node. - * - * 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. - * (Should that change?) - * - * \ingroup engine - */ -class TriggerNode : public NodeImpl -{ -public: - TriggerNode( - InternalPlugin* plugin, - BufferFactory& bufs, - const std::string& path, - bool polyphonic, - PatchImpl* parent, - SampleRate srate); - - void process(ProcessContext& context); - - void note_on(ProcessContext& context, uint8_t note_num, uint8_t velocity, FrameTime time); - void note_off(ProcessContext& context, uint8_t note_num, FrameTime time); - - void learn() { _learning = true; } - - static InternalPlugin* internal_plugin(Shared::LV2URIMap& uris); - -private: - bool _learning; - - InputPort* _midi_in_port; - InputPort* _note_port; - OutputPort* _gate_port; - OutputPort* _trig_port; - OutputPort* _vel_port; -}; - -} // namespace Engine -} // namespace Ingen -} // namespace Internals - -#endif // INGEN_INTERNALS_TRIGGER_HPP diff --git a/src/engine/mix.hpp b/src/engine/mix.hpp deleted file mode 100644 index 3797396b..00000000 --- a/src/engine/mix.hpp +++ /dev/null @@ -1,91 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_MIX_HPP -#define INGEN_ENGINE_MIX_HPP - -#include "raul/log.hpp" -#include "ingen/PortType.hpp" -#include "Buffer.hpp" -#include "Context.hpp" - -using namespace Raul; - -namespace Ingen { -namespace Engine { - -inline void -mix(Context& context, Buffer* dst, const IntrusivePtr<Buffer>* srcs, uint32_t num_srcs) -{ - using Ingen::PortType; - switch (dst->type().symbol()) { - case PortType::AUDIO: - case PortType::CONTROL: - // Copy the first source - dst->copy(context, srcs[0].get()); - - // Mix in the rest - for (uint32_t i = 1; i < num_srcs; ++i) { - assert(srcs[i]->type() == PortType::AUDIO || srcs[i]->type() == PortType::CONTROL); - ((AudioBuffer*)dst)->accumulate(context, (AudioBuffer*)srcs[i].get()); - } - - break; - - case PortType::EVENTS: - dst->clear(); - for (uint32_t i = 0; i < num_srcs; ++i) { - assert(srcs[i]->type() == PortType::EVENTS); - srcs[i]->rewind(); - } - - while (true) { - const EventBuffer* first = NULL; - for (uint32_t i = 0; i < num_srcs; ++i) { - const EventBuffer* const src = (const EventBuffer*)srcs[i].get(); - if (src->is_valid()) { - if (!first || src->get_event()->frames < first->get_event()->frames) - first = src; - } - } - if (first) { - const LV2_Event* const ev = first->get_event(); - ((EventBuffer*)dst)->append( - ev->frames, ev->subframes, ev->type, ev->size, - (const uint8_t*)ev + sizeof(LV2_Event)); - first->increment(); - } else { - break; - } - } - - dst->rewind(); - break; - - default: - if (num_srcs == 1) - dst->copy(context, srcs[0].get()); - else - error << "Mix of unsupported buffer types" << std::endl; - return; - } -} - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_MIX_HPP diff --git a/src/engine/types.hpp b/src/engine/types.hpp deleted file mode 100644 index 1c6b217e..00000000 --- a/src/engine/types.hpp +++ /dev/null @@ -1,29 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_TYPES_HPP -#define INGEN_ENGINE_TYPES_HPP - -#include <stdint.h> -#include <cstddef> - -typedef float Sample; -typedef uint32_t SampleCount; -typedef uint32_t SampleRate; -typedef uint32_t FrameTime; - -#endif // INGEN_ENGINE_TYPES_HPP diff --git a/src/engine/util.hpp b/src/engine/util.hpp deleted file mode 100644 index fb9ba161..00000000 --- a/src/engine/util.hpp +++ /dev/null @@ -1,90 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard <http://drobilla.net> - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_UTIL_HPP -#define INGEN_ENGINE_UTIL_HPP - -#include <cstdlib> -#include <string> - -#include "raul/log.hpp" -#include "raul/Path.hpp" - -#include "ingen-config.h" - -#include <fenv.h> -#ifdef __SSE__ -#include <xmmintrin.h> -#endif - -#ifdef USE_ASSEMBLY -# if SIZEOF_VOID_P==8 -# define cpuid(a,b,c,d,n) asm("xchgq %%rbx, %1; cpuid; xchgq %%rbx, %1": "=a" (a), "=r" (b), "=c" (c), "=d" (d) : "a" (n)); -# else -# define cpuid(a,b,c,d,n) asm("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1": "=a" (a), "=r" (b), "=c" (c), "=d" (d) : "a" (n)); -# endif -#endif - -namespace Ingen { -namespace Engine { - -/** Set flags to disable denormal processing. - */ -inline void -set_denormal_flags() -{ -#ifdef USE_ASSEMBLY -#ifdef __SSE__ - unsigned long a, b, c, d0, d1; - int stepping, model, family, extfamily; - - cpuid(a,b,c,d1,1); - if (d1 & 1<<25) { /* It has SSE support */ - _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); - family = (a >> 8) & 0xf; - extfamily = (a >> 20) & 0xff; - model = (a >> 4) & 0xf; - stepping = a & 0xf; - cpuid(a,b,c,d0,0); - if (b == 0x756e6547) { /* It's an Intel */ - if (family == 15 && extfamily == 0 && model == 0 && stepping < 7) { - return; - } - } - if (d1 & 1<<26) { /* bit 26, SSE2 support */ - _mm_setcsr(_mm_getcsr() | 0x8040); // set DAZ and FZ bits of MXCSR - Raul::info << "Set SSE denormal fix flag" << endl; - } - } else { - Raul::warn << "This code has been built with SSE support, but your processor does" - << " not support the SSE instruction set, exiting." << std::endl; - exit(EXIT_FAILURE); - } -#endif -#endif -} - -static inline std::string -ingen_jack_port_name(const Raul::Path& path) -{ - return path.chop_start("/"); -} - -} // namespace Engine -} // namespace Ingen - -#endif // INGEN_ENGINE_UTIL_HPP diff --git a/src/engine/wscript b/src/engine/wscript deleted file mode 100644 index 2321da69..00000000 --- a/src/engine/wscript +++ /dev/null @@ -1,128 +0,0 @@ -#!/usr/bin/env python -from waflib.extras import autowaf as autowaf - -def build(bld): - # Headers - bld.install_files('${INCLUDEDIR}/ingen/engine', bld.path.ant_glob('*.hpp')) - - core_source = ''' - AudioBuffer.cpp - BufferFactory.cpp - ClientBroadcaster.cpp - ConnectionImpl.cpp - ControlBindings.cpp - DuplexPort.cpp - Engine.cpp - EngineStore.cpp - Event.cpp - EventBuffer.cpp - EventSink.cpp - EventSource.cpp - GraphObjectImpl.cpp - InputPort.cpp - InternalPlugin.cpp - MessageContext.cpp - NodeFactory.cpp - NodeImpl.cpp - ObjectBuffer.cpp - ObjectSender.cpp - OutputPort.cpp - PatchImpl.cpp - PluginImpl.cpp - PortImpl.cpp - PostProcessor.cpp - ProcessContext.cpp - ProcessSlave.cpp - QueuedEngineInterface.cpp - QueuedEvent.cpp - events/Connect.cpp - events/CreateNode.cpp - events/CreatePatch.cpp - events/CreatePort.cpp - events/Delete.cpp - events/Disconnect.cpp - events/DisconnectAll.cpp - events/Get.cpp - events/Move.cpp - events/RegisterClient.cpp - events/RequestMetadata.cpp - events/SendBinding.cpp - events/SendPortActivity.cpp - events/SendPortValue.cpp - events/SetMetadata.cpp - events/SetPortValue.cpp - events/UnregisterClient.cpp - ingen_engine.cpp - internals/Controller.cpp - internals/Delay.cpp - internals/Note.cpp - internals/Trigger.cpp - ''' - - if bld.is_defined('HAVE_SLV2'): - core_source += ' LV2Info.cpp LV2Plugin.cpp LV2Node.cpp ' - - obj = bld(features = 'cxx cxxshlib') - obj.source = core_source - obj.export_includes = ['.'] - obj.includes = ['.', '..', '../..', '../../include'] - obj.name = 'libingen_engine' - obj.target = 'ingen_engine' - obj.install_path = '${LIBDIR}' - obj.use = 'libingen_shared' - core_libs = 'GLIBMM GTHREAD LV2CORE SLV2 RAUL SORD' - autowaf.use_lib(bld, obj, core_libs) - - if bld.is_defined('HAVE_SOUP'): - obj = bld(features = 'cxx cxxshlib') - obj.source = ''' - EventSource.cpp - QueuedEngineInterface.cpp - HTTPClientSender.cpp - HTTPEngineReceiver.cpp - ingen_http.cpp - ''' - obj.includes = ['.', '..', '../..', '../../include', '../engine'] - obj.name = 'libingen_http' - obj.target = 'ingen_http' - obj.install_path = '${LIBDIR}' - autowaf.use_lib(bld, obj, core_libs + ' SOUP') - - if bld.is_defined('HAVE_LIBLO'): - obj = bld(features = 'cxx cxxshlib') - obj.source = ''' - EventSource.cpp - QueuedEngineInterface.cpp - OSCClientSender.cpp - OSCEngineReceiver.cpp - ingen_osc.cpp - ''' - obj.export_includes = ['.'] - obj.includes = ['.', '..', '../..', '../../include', '../engine'] - obj.name = 'libingen_osc' - obj.target = 'ingen_osc' - obj.install_path = '${LIBDIR}' - autowaf.use_lib(bld, obj, core_libs + ' LIBLO') - - if bld.is_defined('HAVE_JACK'): - obj = bld(features = 'cxx cxxshlib') - obj.source = 'JackDriver.cpp ingen_jack.cpp' - obj.export_includes = ['.'] - obj.includes = ['.', '..', '../..', '../../include', '../engine'] - obj.name = 'libingen_jack' - obj.target = 'ingen_jack' - obj.install_path = '${LIBDIR}' - obj.use = 'libingen_engine' - autowaf.use_lib(bld, obj, core_libs + ' JACK') - - # Ingen LV2 wrapper - obj = bld(features = 'cxx cxxshlib') - obj.source = ' ingen_lv2.cpp ' - obj.export_includes = ['.'] - obj.includes = ['.', '..', '../..', '../../include'] - obj.name = 'libingen_lv2' - obj.target = 'ingen_lv2' - obj.install_path = '${LIBDIR}' - obj.use = 'libingen_shared' - obj.add_objects = 'libingen_engine' - autowaf.use_lib(bld, obj, core_libs) |