diff options
author | David Robillard <d@drobilla.net> | 2012-03-19 20:16:46 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2012-03-19 20:16:46 +0000 |
commit | 254b434f0a79fea54bd963e8ff2e845a5b0cd3a6 (patch) | |
tree | ddf849fc5b64d1096846c28c1f1a742f54c3adff /src/server | |
parent | bc3afd8380d59c750c8f8e9bf1ed1b8d4a6826e9 (diff) | |
download | ingen-254b434f0a79fea54bd963e8ff2e845a5b0cd3a6.tar.gz ingen-254b434f0a79fea54bd963e8ff2e845a5b0cd3a6.tar.bz2 ingen-254b434f0a79fea54bd963e8ff2e845a5b0cd3a6.zip |
Partially functioning communication between Ingen LV2 plugin and UI.
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@4078 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/server')
48 files changed, 751 insertions, 1091 deletions
diff --git a/src/server/AudioBuffer.cpp b/src/server/AudioBuffer.cpp index fc73f9d7..2b837d0b 100644 --- a/src/server/AudioBuffer.cpp +++ b/src/server/AudioBuffer.cpp @@ -35,46 +35,31 @@ using namespace Raul; namespace Ingen { namespace Server { -AudioBuffer::AudioBuffer(BufferFactory& bufs, PortType type, size_t size) - : ObjectBuffer(bufs, size) +AudioBuffer::AudioBuffer(BufferFactory& bufs, LV2_URID type, uint32_t size) + : Buffer(bufs, type, size) , _state(OK) , _set_value(0) , _set_time(0) { assert(size >= sizeof(LV2_Atom) + sizeof(Sample)); - assert(this->size() >= size); + assert(this->capacity() >= 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 || type == PortType::CV); - atom()->type = 0;//map->vector_type; + if (type == bufs.uris().atom_Sound) { + // Audio port (Vector of float) LV2_Atom_Vector* body = (LV2_Atom_Vector*)atom(); - body->body.child_size = sizeof(Sample); - body->body.child_type = 0;//map->float_type; + body->body.child_size = sizeof(float); + body->body.child_type = bufs.uris().atom_Float; } - /*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;*/ + _atom->type = type; clear(); } void -AudioBuffer::resize(size_t size) +AudioBuffer::resize(uint32_t size) { - if (_type == PortType::AUDIO) { - ObjectBuffer::resize(size + sizeof(LV2_Atom_Vector)); - } + Buffer::resize(size); clear(); } @@ -164,7 +149,7 @@ AudioBuffer::copy(Context& context, const Buffer* src) // Control => Control if (src_abuf->is_control() == is_control()) { - ObjectBuffer::copy(context, src); + Buffer::copy(context, src); // Audio => Audio } else if (!src_abuf->is_control() && !is_control()) { diff --git a/src/server/AudioBuffer.hpp b/src/server/AudioBuffer.hpp index 262b03c1..eda5c3a3 100644 --- a/src/server/AudioBuffer.hpp +++ b/src/server/AudioBuffer.hpp @@ -24,8 +24,11 @@ #include <boost/utility.hpp> +#include "ingen/shared/URIs.hpp" + +#include "Buffer.hpp" +#include "BufferFactory.hpp" #include "Context.hpp" -#include "ObjectBuffer.hpp" #include "types.hpp" using namespace std; @@ -33,10 +36,10 @@ using namespace std; namespace Ingen { namespace Server { -class AudioBuffer : public ObjectBuffer +class AudioBuffer : public Buffer { public: - AudioBuffer(BufferFactory& bufs, PortType type, size_t capacity); + AudioBuffer(BufferFactory& bufs, LV2_URID type, uint32_t size); void clear(); @@ -48,7 +51,7 @@ public: float peak(Context& context) const; - inline bool is_control() const { return _type.symbol() == PortType::CONTROL; } + inline bool is_control() const { return _type == _factory.uris().atom_Float; } inline Sample* data() const { return (is_control()) @@ -59,7 +62,7 @@ public: inline SampleCount nframes() const { return (is_control()) ? 1 - : (_size - sizeof(LV2_Atom_Vector)) / sizeof(Sample); + : (_capacity - sizeof(LV2_Atom_Vector)) / sizeof(Sample); } inline Sample& value_at(size_t offset) const @@ -68,7 +71,7 @@ public: void prepare_read(Context& context); void prepare_write(Context& context) {} - void resize(size_t size); + void resize(uint32_t size); private: enum State { OK, HALF_SET_CYCLE_1, HALF_SET_CYCLE_2 }; diff --git a/src/server/Buffer.cpp b/src/server/Buffer.cpp new file mode 100644 index 00000000..a52b62eb --- /dev/null +++ b/src/server/Buffer.cpp @@ -0,0 +1,164 @@ +/* This file is part of Ingen. + * Copyright 2009-2012 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 <string.h> + +#include <algorithm> + +#include "ingen/shared/LV2Features.hpp" +#include "ingen/shared/LV2URIMap.hpp" +#include "ingen/shared/URIs.hpp" +#include "ingen/shared/World.hpp" +#include "ingen_config.h" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" +#include "raul/log.hpp" + +#include "Buffer.hpp" +#include "Engine.hpp" + +namespace Ingen { +namespace Server { + +Buffer::Buffer(BufferFactory& bufs, LV2_URID type, uint32_t capacity) + : _factory(bufs) + , _type(type) + , _capacity(capacity) + , _next(NULL) + , _refs(0) +{ + if (capacity > UINT32_MAX) { + Raul::error << "Event buffer size " << capacity << " too large, aborting." + << std::endl; + throw std::bad_alloc(); + } + +#ifdef HAVE_POSIX_MEMALIGN + int ret = posix_memalign((void**)&_atom, 16, capacity); +#else + _atom = (LV2_Atom_Sequence*)malloc(capacity); + int ret = (_atom != NULL) ? 0 : -1; +#endif + + if (ret != 0) { + Raul::error << "Failed to allocate event buffer." << std::endl; + throw std::bad_alloc(); + } + + memset(_atom, 0, capacity); + _atom->type = type; + assert(_atom->type != 1); + + clear(); +} + +Buffer::~Buffer() +{ + free(_atom); +} + +void +Buffer::clear() +{ + _atom->size = 0; +} + +void +Buffer::copy(Context& context, const Buffer* src) +{ + // Copy only if src is a POD object that fits + if (src->_atom->type != 0 && sizeof(LV2_Atom) + src->_atom->size <= capacity()) { + memcpy(_atom, src->_atom, sizeof(LV2_Atom) + src->_atom->size); + } + assert(_atom->type != 1); +} + +void +Buffer::resize(uint32_t capacity) +{ + _atom = (LV2_Atom*)realloc(_atom, capacity); + _capacity = capacity; + clear(); +} + +void* +Buffer::port_data(PortType port_type, SampleCount offset) +{ + switch (port_type.symbol()) { + case PortType::CONTROL: + case PortType::CV: + case PortType::AUDIO: + assert(_atom->type == _type); + if (_atom->type == _factory.uris().atom_Float) { + return (float*)LV2_ATOM_BODY(_atom); + } else if (_atom->type == _factory.uris().atom_Sound) { + return (float*)LV2_ATOM_CONTENTS(LV2_Atom_Vector, _atom) + offset; + } else { + Raul::warn << "Audio data requested from non-audio buffer " << this << " :: " + << _atom->type << " - " + << _factory.engine().world()->lv2_uri_map()->unmap_uri(_atom->type) + << std::endl; + assert(false); + return NULL; + } + break; + default: + return _atom; + } +} + +const void* +Buffer::port_data(PortType port_type, SampleCount offset) const +{ + return const_cast<void*>( + const_cast<Buffer*>(this)->port_data(port_type, offset)); +} + +void +Buffer::prepare_write(Context& context) +{ + _atom->size = 0; +} + +bool +Buffer::append_event(int64_t frames, + uint32_t size, + uint32_t type, + const uint8_t* data) +{ + if (sizeof(LV2_Atom) + _atom->size + lv2_atom_pad_size(size) > _capacity) { + return false; + } + + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)_atom; + LV2_Atom_Event* ev = (LV2_Atom_Event*)( + (uint8_t*)seq + sizeof(LV2_Atom) + lv2_atom_pad_size(seq->atom.size)); + + ev->time.frames = frames; + ev->body.size = size; + ev->body.type = type; + memcpy(LV2_ATOM_BODY(&ev->body), data, size); + + _atom->size += lv2_atom_pad_size(size); + + return true; +} + +} // namespace Server +} // namespace Ingen diff --git a/src/server/Buffer.hpp b/src/server/Buffer.hpp index 0b3c9348..c2d5ac05 100644 --- a/src/server/Buffer.hpp +++ b/src/server/Buffer.hpp @@ -24,6 +24,7 @@ #include <boost/intrusive_ptr.hpp> #include <boost/utility.hpp> +#include "lv2/lv2plug.in/ns/ext/atom/atom.h" #include "raul/AtomicInt.hpp" #include "raul/Deletable.hpp" #include "raul/SharedPtr.hpp" @@ -42,32 +43,28 @@ 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) - {} + Buffer(BufferFactory& bufs, LV2_URID type, uint32_t capacity); - /** 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; + virtual void clear(); + virtual void resize(uint32_t size); + virtual void copy(Context& context, const Buffer* src); + virtual void prepare_read(Context& context) {} + virtual void prepare_write(Context& context); - /** Rewind (ie reset read pointer), but leave contents unchanged */ - virtual void rewind() const {} + void* port_data(PortType port_type, SampleCount offset); + const void* port_data(PortType port_type, SampleCount offset) const; - virtual void copy(Context& context, const Buffer* src) = 0; + LV2_URID type() const { return _type; } + uint32_t capacity() const { return _capacity; } - virtual void prepare_read(Context& context) {} - virtual void prepare_write(Context& context) {} + /// Sequence buffers only + bool append_event(int64_t frames, + uint32_t size, + uint32_t type, + const uint8_t* data); - PortType type() const { return _type; } - size_t size() const { return _size; } + LV2_Atom* atom() { return _atom; } + const LV2_Atom* atom() const { return _atom; } inline void ref() { ++_refs; } @@ -78,11 +75,12 @@ public: protected: BufferFactory& _factory; - PortType _type; - size_t _size; + LV2_Atom* _atom; + LV2_URID _type; + uint32_t _capacity; friend class BufferFactory; - virtual ~Buffer() {} + virtual ~Buffer(); private: Buffer* _next; ///< Intrusive linked list for BufferFactory diff --git a/src/server/BufferFactory.cpp b/src/server/BufferFactory.cpp index f24f7270..6be8b2ea 100644 --- a/src/server/BufferFactory.cpp +++ b/src/server/BufferFactory.cpp @@ -16,15 +16,15 @@ */ #include <algorithm> -#include "raul/log.hpp" + #include "ingen/shared/LV2URIMap.hpp" #include "ingen/shared/URIs.hpp" +#include "raul/log.hpp" + #include "AudioBuffer.hpp" -#include "EventBuffer.hpp" -#include "ObjectBuffer.hpp" #include "BufferFactory.hpp" -#include "Engine.hpp" #include "Driver.hpp" +#include "Engine.hpp" #include "ThreadManager.hpp" using namespace Raul; @@ -48,11 +48,10 @@ BufferFactory::~BufferFactory() _silent_buffer.reset(); free_list(_free_audio.get()); free_list(_free_control.get()); - free_list(_free_event.get()); free_list(_free_object.get()); } -Raul::Forge& +Ingen::Forge& BufferFactory::forge() { return _engine.world()->forge(); @@ -71,33 +70,31 @@ BufferFactory::free_list(Buffer* head) void BufferFactory::set_block_length(SampleCount block_length) { - _silent_buffer = create(PortType::AUDIO, audio_buffer_size(block_length)); + _silent_buffer = create(_uris->atom_Sound, audio_buffer_size(block_length)); } -size_t +uint32_t BufferFactory::audio_buffer_size(SampleCount nframes) { return sizeof(LV2_Atom_Vector) + (nframes * sizeof(float)); } -size_t -BufferFactory::default_buffer_size(PortType type) +uint32_t +BufferFactory::default_buffer_size(LV2_URID type) { - switch (type.symbol()) { - case PortType::AUDIO: - case PortType::CV: - 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 + if (type == _uris->atom_Float) { + return sizeof(LV2_Atom_Float); + } else if (type == _uris->atom_Sound) { + return audio_buffer_size(_engine.driver()->block_length()); + } else if (type == _uris->atom_Sequence) { + return _engine.driver()->block_length() * EVENT_BYTES_PER_FRAME; + } else { + return 0; } } BufferFactory::Ref -BufferFactory::get(PortType type, size_t size, bool force_create) +BufferFactory::get(LV2_URID type, uint32_t capacity, bool force_create) { Raul::AtomicPtr<Buffer>& head_ptr = free_list(type); Buffer* try_head = NULL; @@ -114,7 +111,7 @@ BufferFactory::get(PortType type, size_t size, bool force_create) if (!try_head) { if (!ThreadManager::thread_is(THREAD_PROCESS)) { - return create(type, size); + return create(type, capacity); } else { assert(false); error << "Failed to obtain buffer" << endl; @@ -133,33 +130,31 @@ BufferFactory::silent_buffer() } BufferFactory::Ref -BufferFactory::create(PortType type, size_t size) +BufferFactory::create(LV2_URID type, uint32_t capacity) { 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, audio_buffer_size(size)); - ret->atom()->type = _uris->atom_Float.id; - buffer = ret; - } else if (type.is_audio() || type.is_cv()) { - AudioBuffer* ret = new AudioBuffer(*this, type, audio_buffer_size(size)); - ret->atom()->type = _uris->atom_Vector.id; - ((LV2_Atom_Vector*)ret->atom())->body.child_type = _uris->atom_Float.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*))); + if (capacity == 0) { + capacity = default_buffer_size(type); + } + + if (type == _uris->atom_Float) { + assert(capacity >= sizeof(LV2_Atom_Float)); + buffer = new AudioBuffer(*this, type, capacity); + info << "NEW FLOAT BUFFER " << buffer << " :: " << type << std::endl; + } else if (type == _uris->atom_Sound) { + assert(capacity >= default_buffer_size(_uris->atom_Sound)); + buffer = new AudioBuffer(*this, type, capacity); + info << "NEW AUDIO BUFFER " << buffer << " :: " << type << std::endl; } else { - error << "Failed to create buffer of unknown type" << endl; - return Ref(); + buffer = new Buffer(*this, type, capacity); + info << "NEW ATOM BUFFER " << buffer << " :: " << type << std::endl; } + buffer->atom()->type = type; + assert(buffer); return Ref(buffer); } diff --git a/src/server/BufferFactory.hpp b/src/server/BufferFactory.hpp index 15d5ebb8..6f700fce 100644 --- a/src/server/BufferFactory.hpp +++ b/src/server/BufferFactory.hpp @@ -25,9 +25,12 @@ #undef nil #include <glibmm/thread.h> +#include "raul/Atom.hpp" #include "raul/AtomicPtr.hpp" #include "raul/RingBuffer.hpp" #include "raul/SharedPtr.hpp" +#include "ingen/shared/Forge.hpp" +#include "ingen/shared/URIs.hpp" #include "PortType.hpp" #include "types.hpp" @@ -50,33 +53,32 @@ public: typedef boost::intrusive_ptr<Buffer> Ref; - static size_t audio_buffer_size(SampleCount nframes); - size_t default_buffer_size(PortType type); + static uint32_t audio_buffer_size(SampleCount nframes); + uint32_t default_buffer_size(LV2_URID type); - Ref get(PortType type, size_t size=0, bool force_create=false); + Ref get(LV2_URID type, uint32_t capacity, bool force_create=false); Ref silent_buffer(); void set_block_length(SampleCount block_length); - Raul::Forge& forge(); - Ingen::Shared::URIs& uris() { assert(_uris); return *_uris.get(); } + Ingen::Forge& forge(); + Ingen::Shared::URIs& uris() { assert(_uris); return *_uris.get(); } + Engine& engine() { return _engine; } 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: - case PortType::CV: 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; + Ref create(LV2_URID type, uint32_t capacity=0); + + inline Raul::AtomicPtr<Buffer>& free_list(LV2_URID type) { + if (type == _uris->atom_Float) { + return _free_control; + } else if (type == _uris->atom_Sound) { + return _free_audio; + } else { + return _free_object; } } @@ -84,7 +86,6 @@ private: Raul::AtomicPtr<Buffer> _free_audio; Raul::AtomicPtr<Buffer> _free_control; - Raul::AtomicPtr<Buffer> _free_event; Raul::AtomicPtr<Buffer> _free_object; Glib::Mutex _mutex; diff --git a/src/server/ConnectionImpl.cpp b/src/server/ConnectionImpl.cpp index bc0a5c53..7a4d7dda 100644 --- a/src/server/ConnectionImpl.cpp +++ b/src/server/ConnectionImpl.cpp @@ -17,15 +17,17 @@ #include <algorithm> #include <boost/intrusive_ptr.hpp> -#include "raul/log.hpp" -#include "raul/Maid.hpp" + #include "ingen/shared/LV2URIMap.hpp" #include "ingen/shared/URIs.hpp" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" +#include "raul/Maid.hpp" +#include "raul/log.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" @@ -109,27 +111,21 @@ ConnectionImpl::queue(Context& context) if (!must_queue()) return; - boost::intrusive_ptr<EventBuffer> src_buf = - boost::dynamic_pointer_cast<EventBuffer>(_src_port->buffer(0)); - if (!src_buf) { - error << "Queued connection but source is not an EventBuffer" << endl; + const Ingen::Shared::URIs& uris = _src_port->bufs().uris(); + + boost::intrusive_ptr<Buffer> src_buf = _src_port->buffer(0); + if (src_buf->atom()->type != uris.atom_Sequence) { + error << "Queued connection but source is not a Sequence" << endl; return; } - for (src_buf->rewind(); src_buf->is_valid(); src_buf->increment()) { - error << "Queued connections currently unsupported" << endl; - #if 0 - 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); - #endif + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)src_buf->atom(); + LV2_SEQUENCE_FOREACH(seq, i) { + LV2_Atom_Event* const ev = lv2_sequence_iter_get(i); + _queue->write(sizeof(LV2_Atom) + ev->body.size, &ev->body); + context.engine().message_context()->run( + _dst_port->parent_node(), context.start() + ev->time.frames); + } } @@ -171,25 +167,21 @@ ConnectionImpl::can_connect(const OutputPort* src, const InputPort* dst) || dst->is_a(PortType::AUDIO) || dst->is_a(PortType::CV))) - // (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))) + // Equal types + || (src->type() == dst->type() && + src->buffer_type() == dst->buffer_type()) // Control => atom:Float Value || (src->is_a(PortType::CONTROL) && dst->supports(uris.atom_Float)) - // Audio => atom:Vector Value - || (src->is_a(PortType::AUDIO) && dst->supports(uris.atom_Vector)) + // Audio => atom:Sound Value + || (src->is_a(PortType::AUDIO) && dst->supports(uris.atom_Sound)) // atom:Float Value => Control || (src->supports(uris.atom_Float) && dst->is_a(PortType::CONTROL)) - // atom:Vector Value => Audio - || (src->supports(uris.atom_Vector) && dst->is_a(PortType::AUDIO))); + // atom:Sound Value => Audio + || (src->supports(uris.atom_Sound) && dst->is_a(PortType::AUDIO))); } } // namespace Server diff --git a/src/server/ControlBindings.cpp b/src/server/ControlBindings.cpp index d8d0ec07..0394226f 100644 --- a/src/server/ControlBindings.cpp +++ b/src/server/ControlBindings.cpp @@ -16,16 +16,17 @@ */ #include <math.h> -#include "raul/log.hpp" -#include "raul/midi_events.h" -#include "ingen/shared/URIs.hpp" + #include "ingen/shared/LV2URIMap.hpp" +#include "ingen/shared/URIs.hpp" #include "ingen/shared/World.hpp" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" +#include "raul/log.hpp" +#include "raul/midi_events.h" #include "AudioBuffer.hpp" #include "ControlBindings.hpp" #include "Engine.hpp" -#include "EventBuffer.hpp" #include "Notification.hpp" #include "PortImpl.hpp" #include "ProcessContext.hpp" @@ -43,13 +44,15 @@ ControlBindings::ControlBindings(Engine& engine) : _engine(engine) , _learn_port(NULL) , _bindings(new Bindings()) - , _feedback(new EventBuffer(*_engine.buffer_factory(), 1024)) // FIXME: size + , _feedback(new Buffer(*_engine.buffer_factory(), + engine.world()->uris()->atom_Sequence, + 4096)) // FIXME: capacity? { } ControlBindings::~ControlBindings() { - delete _feedback; + _feedback.reset(); } ControlBindings::Key @@ -66,7 +69,7 @@ ControlBindings::binding_key(const Raul::Atom& binding) const { const Ingen::Shared::URIs& uris = *_engine.world()->uris().get(); Key key; - if (binding.type() == Atom::DICT) { + if (binding.type() == _engine.world()->forge().Dict) { const Atom::DictValue& dict = binding.get_dict(); Atom::DictValue::const_iterator t = dict.find(uris.rdf_type); Atom::DictValue::const_iterator n; @@ -88,7 +91,7 @@ ControlBindings::binding_key(const Raul::Atom& binding) const } ControlBindings::Key -ControlBindings::midi_event_key(uint16_t size, uint8_t* buf, uint16_t& value) +ControlBindings::midi_event_key(uint16_t size, const uint8_t* buf, uint16_t& value) { switch (buf[0] & 0xF0) { case MIDI_CMD_CONTROL: @@ -125,9 +128,8 @@ ControlBindings::port_value_changed(ProcessContext& context, Key key, const Raul::Atom& value_atom) { - Ingen::Shared::World* world = context.engine().world(); - const Ingen::Shared::URIs& uris = *world->uris().get(); - const Ingen::Shared::LV2URIMap& uri_map = *world->lv2_uri_map().get(); + Ingen::Shared::World* world = context.engine().world(); + const Ingen::Shared::URIs& uris = *world->uris().get(); if (key) { int16_t value = port_value_to_control( port, key.type, value_atom, port->minimum(), port->maximum()); @@ -164,9 +166,7 @@ ControlBindings::port_value_changed(ProcessContext& context, break; } if (size > 0) { - _feedback->append(0, 0, - uri_map.global_to_event(uris.midi_MidiEvent.id).second, - size, buf); + _feedback->append_event(0, size, uris.midi_MidiEvent.id, buf); } } } @@ -218,7 +218,7 @@ ControlBindings::port_value_to_control(PortImpl* port, const Raul::Atom& min_atom, const Raul::Atom& max_atom) const { - if (value_atom.type() != Atom::FLOAT) + if (value_atom.type() != port->bufs().forge().Float) return 0; const float min = min_atom.get_float(); @@ -262,7 +262,7 @@ ControlBindings::set_port_value(ProcessContext& context, port->set_value(port_value); - assert(port_value.type() == Atom::FLOAT); + assert(port_value.type() == port->bufs().forge().Float); assert(dynamic_cast<AudioBuffer*>(port->buffer(0).get())); for (uint32_t v = 0; v < port->poly(); ++v) @@ -341,71 +341,43 @@ ControlBindings::remove(PortImpl* port) } void -ControlBindings::pre_process(ProcessContext& context, EventBuffer* buffer) +ControlBindings::pre_process(ProcessContext& context, Buffer* 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; - + uint16_t value = 0; SharedPtr<Bindings> bindings = _bindings; _feedback->clear(); - Ingen::Shared::World* world = context.engine().world(); - const Ingen::Shared::URIs& uris = *world->uris().get(); - const Ingen::Shared::LV2URIMap& uri_map = *world->lv2_uri_map().get(); - - // TODO: cache - const uint32_t midi_event_type = uri_map.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; - } - } + Ingen::Shared::World* world = context.engine().world(); + const Ingen::Shared::URIs& uris = *world->uris().get(); - // If bindings are empty, no sense reading input - if (bindings->empty()) + if (!_learn_port && bindings->empty()) { + // Don't bother reading input 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); + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)buffer->atom(); + LV2_SEQUENCE_FOREACH(seq, i) { + LV2_Atom_Event* const ev = lv2_sequence_iter_get(i); + if (ev->body.type == uris.midi_MidiEvent) { + const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body); + const Key key = midi_event_key(ev->body.size, buf, value); + if (_learn_port && key) { + bind(context, key); + } + + Bindings::const_iterator i = bindings->find(key); + if (i != bindings->end()) { + set_port_value(context, i->second, key.type, value); + } + } } } void -ControlBindings::post_process(ProcessContext& context, EventBuffer* buffer) +ControlBindings::post_process(ProcessContext& context, Buffer* 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); - } + // TODO: merge buffer's existing contents (anything send to it in the patch) + buffer->copy(context, _feedback.get()); } } // namespace Server diff --git a/src/server/ControlBindings.hpp b/src/server/ControlBindings.hpp index f0858853..1e61bdcb 100644 --- a/src/server/ControlBindings.hpp +++ b/src/server/ControlBindings.hpp @@ -33,7 +33,6 @@ namespace Server { class Engine; class ProcessContext; -class EventBuffer; class PortImpl; class ControlBindings { @@ -77,8 +76,8 @@ public: Key key, const Raul::Atom& value); - void pre_process(ProcessContext& context, EventBuffer* control_in); - void post_process(ProcessContext& context, EventBuffer* control_out); + void pre_process(ProcessContext& context, Buffer* control_in); + void post_process(ProcessContext& context, Buffer* control_out); /** Remove all bindings for @a path or children of @a path. * The caller must safely drop the returned reference in the @@ -93,7 +92,7 @@ public: SharedPtr<Bindings> remove(PortImpl* port); private: - Key midi_event_key(uint16_t size, uint8_t* buf, uint16_t& value); + Key midi_event_key(uint16_t size, const 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); @@ -113,7 +112,7 @@ private: PortImpl* _learn_port; SharedPtr<Bindings> _bindings; - EventBuffer* _feedback; + BufferFactory::Ref _feedback; }; } // namespace Server diff --git a/src/server/DuplexPort.cpp b/src/server/DuplexPort.cpp index f2c2763b..01fc43f3 100644 --- a/src/server/DuplexPort.cpp +++ b/src/server/DuplexPort.cpp @@ -22,9 +22,9 @@ #include "ingen/shared/LV2URIMap.hpp" #include "ingen/shared/URIs.hpp" +#include "Buffer.hpp" #include "ConnectionImpl.hpp" #include "DuplexPort.hpp" -#include "EventBuffer.hpp" #include "NodeImpl.hpp" #include "OutputPort.hpp" #include "ProcessContext.hpp" @@ -43,12 +43,13 @@ DuplexPort::DuplexPort( bool polyphonic, uint32_t poly, PortType type, + LV2_URID buffer_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) + : PortImpl(bufs, parent, name, index, poly, type, buffer_type, value, buffer_size) + , InputPort(bufs, parent, name, index, poly, type, buffer_type, value, buffer_size) + , OutputPort(bufs, parent, name, index, poly, type, buffer_type, value, buffer_size) , _is_output(is_output) { assert(PortImpl::_parent == parent); diff --git a/src/server/DuplexPort.hpp b/src/server/DuplexPort.hpp index 3b715130..1c543608 100644 --- a/src/server/DuplexPort.hpp +++ b/src/server/DuplexPort.hpp @@ -46,6 +46,7 @@ public: bool polyphonic, uint32_t poly, PortType type, + LV2_URID buffer_type, const Raul::Atom& value, size_t buffer_size, bool is_output); diff --git a/src/server/Engine.cpp b/src/server/Engine.cpp index 3d5e981b..d4904f0c 100644 --- a/src/server/Engine.cpp +++ b/src/server/Engine.cpp @@ -22,7 +22,6 @@ #include "raul/Deletable.hpp" #include "raul/Maid.hpp" #include "raul/SharedPtr.hpp" -#include "lv2/lv2plug.in/ns/ext/uri-map/uri-map.h" #include "events/CreatePatch.hpp" #include "events/CreatePort.hpp" #include "ingen/shared/World.hpp" @@ -57,7 +56,7 @@ bool ThreadManager::single_threaded = true; Engine::Engine(Ingen::Shared::World* a_world) : _world(a_world) , _broadcaster(new ClientBroadcaster()) - , _control_bindings(new ControlBindings(*this)) + , _control_bindings(NULL) , _maid(new Raul::Maid(event_queue_size())) , _message_context(new MessageContext(*this)) , _node_factory(new NodeFactory(a_world)) @@ -73,6 +72,8 @@ Engine::Engine(Ingen::Shared::World* a_world) SharedPtr<Ingen::Shared::Store>( new EngineStore(SharedPtr<BufferFactory>(_buffer_factory)))); } + + _control_bindings = new ControlBindings(*this); } Engine::~Engine() @@ -104,7 +105,7 @@ Engine::engine_store() const size_t Engine::event_queue_size() const { - return world()->conf()->option("queue-size").get_int32(); + return world()->conf()->option("queue-size").get_int(); } void @@ -153,7 +154,7 @@ Engine::activate() _message_context->Thread::start(); const Ingen::Shared::URIs& uris = *world()->uris().get(); - Raul::Forge& forge = world()->forge(); + Ingen::Forge& forge = world()->forge(); // Create root patch PatchImpl* root_patch = _driver->root_patch(); @@ -173,14 +174,15 @@ Engine::activate() Resource::Properties control_properties; control_properties.insert(make_pair(uris.lv2_name, - forge.make("Control"))); + forge.alloc("Control"))); control_properties.insert(make_pair(uris.rdf_type, - uris.ev_EventPort)); + uris.atom_MessagePort)); + control_properties.insert(make_pair(uris.atom_bufferType, + uris.atom_Sequence)); // 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.rdf_type, uris.ev_EventPort)); in_properties.insert(make_pair(uris.lv2_index, forge.make(0))); in_properties.insert(make_pair(uris.lv2_portProperty, uris.lv2_connectionOptional)); @@ -198,7 +200,6 @@ Engine::activate() // 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.rdf_type, uris.ev_EventPort)); out_properties.insert(make_pair(uris.lv2_index, forge.make(1))); in_properties.insert(make_pair(uris.lv2_portProperty, uris.lv2_connectionOptional)); diff --git a/src/server/EventBuffer.cpp b/src/server/EventBuffer.cpp deleted file mode 100644 index 7f3c2b37..00000000 --- a/src/server/EventBuffer.cpp +++ /dev/null @@ -1,217 +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 Server { - -/** 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; - } -} - -#if 0 -/** 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; -} -#endif - -/** 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 Server -} // namespace Ingen diff --git a/src/server/EventBuffer.hpp b/src/server/EventBuffer.hpp deleted file mode 100644 index 52125ffd..00000000 --- a/src/server/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 "Buffer.hpp" - -namespace Ingen { -namespace Server { - -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 Server -} // namespace Ingen - -#endif // INGEN_ENGINE_EVENTBUFFER_HPP diff --git a/src/server/InputPort.cpp b/src/server/InputPort.cpp index a07ef183..42d6c83d 100644 --- a/src/server/InputPort.cpp +++ b/src/server/InputPort.cpp @@ -23,16 +23,15 @@ #include "AudioBuffer.hpp" #include "BufferFactory.hpp" #include "ConnectionImpl.hpp" -#include "EventBuffer.hpp" #include "InputPort.hpp" #include "NodeImpl.hpp" #include "Notification.hpp" #include "OutputPort.hpp" #include "ProcessContext.hpp" #include "ThreadManager.hpp" -#include "mix.hpp" #include "ingen/shared/LV2URIMap.hpp" #include "ingen/shared/URIs.hpp" +#include "mix.hpp" #include "util.hpp" using namespace std; @@ -46,9 +45,10 @@ InputPort::InputPort(BufferFactory& bufs, uint32_t index, uint32_t poly, PortType type, + LV2_URID buffer_type, const Raul::Atom& value, size_t buffer_size) - : PortImpl(bufs, parent, symbol, index, poly, type, value, buffer_size) + : PortImpl(bufs, parent, symbol, index, poly, type, buffer_type, value, buffer_size) , _num_connections(0) { const Ingen::Shared::URIs& uris = bufs.uris(); @@ -203,7 +203,7 @@ InputPort::pre_process(Context& context) c->get_sources(context, v, srcs, max_num_srcs, num_srcs); } - mix(context, buffer(v).get(), srcs, num_srcs); + mix(context, bufs().uris(), buffer(v).get(), srcs, num_srcs); buffer(v)->prepare_read(context); } } @@ -216,7 +216,7 @@ void InputPort::post_process(Context& context) { if (_set_by_user) { - if (is_a(PortType::EVENTS)) { + if (_buffer_type == _bufs.uris().atom_Sequence) { // Clear events received via a SetPortValue for (uint32_t v = 0; v < _poly; ++v) { buffer(v)->clear(); diff --git a/src/server/InputPort.hpp b/src/server/InputPort.hpp index 542c3dd1..6c790c9f 100644 --- a/src/server/InputPort.hpp +++ b/src/server/InputPort.hpp @@ -58,6 +58,7 @@ public: uint32_t index, uint32_t poly, PortType type, + LV2_URID buffer_type, const Raul::Atom& value, size_t buffer_size=0); diff --git a/src/server/JackDriver.cpp b/src/server/JackDriver.cpp index 2979a449..b81a25a6 100644 --- a/src/server/JackDriver.cpp +++ b/src/server/JackDriver.cpp @@ -27,17 +27,16 @@ #include "ingen/serialisation/Serialiser.hpp" #endif -#include "raul/log.hpp" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" #include "raul/List.hpp" - -#include "lv2/lv2plug.in/ns/ext/event/event.h" +#include "raul/log.hpp" #include "AudioBuffer.hpp" #include "ControlBindings.hpp" #include "DuplexPort.hpp" #include "Engine.hpp" #include "Event.hpp" -#include "EventBuffer.hpp" +#include "Event.hpp" #include "EventSource.hpp" #include "JackDriver.hpp" #include "MessageContext.hpp" @@ -45,11 +44,10 @@ #include "PortImpl.hpp" #include "PostProcessor.hpp" #include "ProcessSlave.hpp" -#include "Event.hpp" #include "ThreadManager.hpp" -#include "ingen/shared/World.hpp" #include "ingen/shared/LV2Features.hpp" #include "ingen/shared/LV2URIMap.hpp" +#include "ingen/shared/World.hpp" #include "util.hpp" #define LOG(s) s << "[JackDriver] " @@ -126,9 +124,9 @@ JackPort::pre_process(ProcessContext& context) patch_buf->copy(jack_buf, 0, nframes - 1); - } else if (_patch_port->is_a(PortType::EVENTS)) { - void* jack_buf = jack_port_get_buffer(_jack_port, nframes); - EventBuffer* patch_buf = (EventBuffer*)_patch_port->buffer(0).get(); + } else if (_patch_port->buffer_type() == _patch_port->bufs().uris().atom_Sequence) { + void* jack_buf = jack_port_get_buffer(_jack_port, nframes); + Buffer* patch_buf = (Buffer*)_patch_port->buffer(0).get(); const jack_nframes_t event_count = jack_midi_get_event_count(jack_buf); @@ -139,10 +137,10 @@ JackPort::pre_process(ProcessContext& context) 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)) + if (!patch_buf->append_event( + ev.time, ev.size, _driver->_midi_event_type, ev.buffer)) { LOG(warn) << "Failed to write MIDI to port buffer, event(s) lost!" << endl; + } } } } @@ -161,23 +159,20 @@ JackPort::post_process(ProcessContext& context) memcpy(jack_buf, patch_buf->data(), nframes * sizeof(Sample)); - } else if (_patch_port->is_a(PortType::EVENTS)) { - void* jack_buf = jack_port_get_buffer(_jack_port, context.nframes()); - EventBuffer* patch_buf = (EventBuffer*)_patch_port->buffer(0).get(); + } else if (_patch_port->buffer_type() == _patch_port->bufs().uris().atom_Sequence) { + void* jack_buf = jack_port_get_buffer(_jack_port, context.nframes()); + Buffer* patch_buf = (Buffer*)_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); + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)patch_buf->atom(); + LV2_SEQUENCE_FOREACH(seq, i) { + LV2_Atom_Event* const ev = lv2_sequence_iter_get(i); + const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body); + if (ev->body.type == _patch_port->bufs().uris().midi_MidiEvent) { + jack_midi_event_write(jack_buf, ev->time.frames, buf, ev->body.size); + } } } } @@ -195,8 +190,7 @@ JackDriver::JackDriver(Engine& engine) , _process_context(engine) , _root_patch(NULL) { - _midi_event_type = _engine.world()->lv2_uri_map()->uri_to_id( - LV2_EVENT_URI, "http://lv2plug.in/ns/ext/midi#MidiEvent"); + _midi_event_type = _engine.world()->uris()->midi_MidiEvent; } JackDriver::~JackDriver() @@ -286,7 +280,7 @@ JackDriver::activate() _is_activated = true; - _process_context.activate(world->conf()->option("parallelism").get_int32(), + _process_context.activate(world->conf()->option("parallelism").get_int(), is_realtime()); if (jack_activate(_client)) { @@ -376,10 +370,12 @@ JackDriver::create_port(DuplexPort* patch_port) { try { if (patch_port->is_a(PortType::AUDIO) - || patch_port->is_a(PortType::EVENTS)) + || (patch_port->is_a(PortType::MESSAGE) && + patch_port->buffer_type() == patch_port->bufs().uris().atom_Sequence)) { return new JackPort(this, patch_port); - else + } else { return NULL; + } } catch (...) { return NULL; } @@ -434,8 +430,8 @@ JackDriver::_process_cb(jack_nframes_t nframes) (*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.control_bindings()->pre_process( + _process_context, _root_patch->port_impl(0)->buffer(0).get()); _engine.post_processor()->set_end_time(_process_context.end()); @@ -459,8 +455,8 @@ JackDriver::_process_cb(jack_nframes_t nframes) } // Emit control binding feedback - _engine.control_bindings()->post_process(_process_context, - PtrCast<EventBuffer>(_root_patch->port_impl(1)->buffer(0)).get()); + _engine.control_bindings()->post_process( + _process_context, _root_patch->port_impl(1)->buffer(0).get()); // Signal message context to run if necessary if (_engine.message_context()->has_requests()) diff --git a/src/server/LV2Info.cpp b/src/server/LV2Info.cpp index 4fff9647..130d5dfe 100644 --- a/src/server/LV2Info.cpp +++ b/src/server/LV2Info.cpp @@ -42,7 +42,6 @@ LV2Info::LV2Info(Ingen::Shared::World* world) , control_class(lilv_new_uri(world->lilv_world(), LV2_CORE__ControlPort)) , cv_class(lilv_new_uri(world->lilv_world(), "http://lv2plug.in/ns/ext/cv-port#CVPort")) , audio_class(lilv_new_uri(world->lilv_world(), LV2_CORE__AudioPort)) - , event_class(lilv_new_uri(world->lilv_world(), LILV_URI_EVENT_PORT)) , value_port_class(lilv_new_uri(world->lilv_world(), LV2_ATOM__ValuePort)) , message_port_class(lilv_new_uri(world->lilv_world(), LV2_ATOM__MessagePort)) , _world(world) @@ -62,7 +61,6 @@ LV2Info::~LV2Info() lilv_node_free(control_class); lilv_node_free(cv_class); lilv_node_free(audio_class); - lilv_node_free(event_class); lilv_node_free(value_port_class); lilv_node_free(message_port_class); } diff --git a/src/server/LV2Info.hpp b/src/server/LV2Info.hpp index 297f3742..17132bcc 100644 --- a/src/server/LV2Info.hpp +++ b/src/server/LV2Info.hpp @@ -42,7 +42,6 @@ public: LilvNode* control_class; LilvNode* cv_class; LilvNode* audio_class; - LilvNode* event_class; LilvNode* value_port_class; LilvNode* message_port_class; diff --git a/src/server/LV2Node.cpp b/src/server/LV2Node.cpp index a22b0232..4dc9de0c 100644 --- a/src/server/LV2Node.cpp +++ b/src/server/LV2Node.cpp @@ -30,7 +30,6 @@ #include "ingen/shared/URIs.hpp" #include "AudioBuffer.hpp" -#include "EventBuffer.hpp" #include "InputPort.hpp" #include "LV2Node.hpp" #include "LV2Plugin.hpp" @@ -142,7 +141,7 @@ LV2Node::instantiate(BufferFactory& bufs) const Ingen::Shared::URIs& uris = bufs.uris(); SharedPtr<LV2Info> info = _lv2_plugin->lv2_info(); const LilvPlugin* plug = _lv2_plugin->lilv_plugin(); - Raul::Forge& forge = bufs.forge(); + Ingen::Forge& forge = bufs.forge(); uint32_t num_ports = lilv_plugin_get_num_ports(plug); assert(num_ports > 0); @@ -207,6 +206,9 @@ LV2Node::instantiate(BufferFactory& bufs) LilvNode* supports_pred = lilv_new_uri(info->lv2_world(), "http://lv2plug.in/ns/ext/atom#supports"); + LilvNode* bufferType_pred = lilv_new_uri(info->lv2_world(), + "http://lv2plug.in/ns/ext/atom#bufferType"); + //LilvNode as_large_as_pred = lilv_new_uri(info->lv2_world(), // "http://lv2plug.in/ns/ext/resize-port#asLargeAs"); @@ -228,24 +230,40 @@ LV2Node::instantiate(BufferFactory& bufs) port_path = path().child(port_name); Raul::Atom val; - PortType data_type = PortType::UNKNOWN; + PortType port_type = PortType::UNKNOWN; + LV2_URID buffer_type = 0; if (lilv_port_is_a(plug, id, info->control_class)) { - data_type = PortType::CONTROL; + port_type = PortType::CONTROL; + buffer_type = uris.atom_Float; } else if (lilv_port_is_a(plug, id, info->cv_class)) { - data_type = PortType::CV; + port_type = PortType::CV; + buffer_type = uris.atom_Sound; } else if (lilv_port_is_a(plug, id, info->audio_class)) { - data_type = PortType::AUDIO; - } else if (lilv_port_is_a(plug, id, info->event_class)) { - data_type = PortType::EVENTS; + port_type = PortType::AUDIO; + buffer_type = uris.atom_Sound; } else if (lilv_port_is_a(plug, id, info->value_port_class)) { - data_type = PortType::VALUE; + port_type = PortType::VALUE; } else if (lilv_port_is_a(plug, id, info->message_port_class)) { - data_type = PortType::MESSAGE; + port_type = PortType::MESSAGE; + } + + // Get buffer type if necessary (value and message ports) + if (!buffer_type) { + LilvNodes* types = lilv_port_get_value(plug, id, bufferType_pred); + LILV_FOREACH(nodes, i, types) { + const LilvNode* type = lilv_nodes_get(types, i); + if (lilv_node_is_uri(type)) { + port->add_property(uris.atom_bufferType, + forge.alloc_uri(lilv_node_as_uri(type))); + buffer_type = bufs.engine().world()->lv2_uri_map()->map_uri( + lilv_node_as_uri(type)); + } + } } - port_buffer_size = bufs.default_buffer_size(data_type); + port_buffer_size = bufs.default_buffer_size(buffer_type); - if (data_type == PortType::VALUE || data_type == PortType::MESSAGE) { + if (port_type == PortType::VALUE || port_type == PortType::MESSAGE) { // Get default value, and its length LilvNodes* defaults = lilv_port_get_value(plug, id, default_pred); LILV_FOREACH(nodes, i, defaults) { @@ -253,7 +271,7 @@ LV2Node::instantiate(BufferFactory& bufs) if (lilv_node_is_string(d)) { const char* str_val = lilv_node_as_string(d); const size_t str_val_len = strlen(str_val); - val = forge.make(str_val); + val = forge.alloc(str_val); port_buffer_size = str_val_len; } } @@ -276,23 +294,23 @@ LV2Node::instantiate(BufferFactory& bufs) direction = OUTPUT; } - if (data_type == PortType::UNKNOWN || direction == UNKNOWN) { + if (port_type == PortType::UNKNOWN || direction == UNKNOWN) { warn << "Unknown type or direction for port `" << port_name << "'" << endl; ret = false; break; } - if (val.type() == Atom::NIL) + if (!val.type()) val = forge.make(isnan(def_values[j]) ? 0.0f : def_values[j]); // TODO: set buffer size when necessary if (direction == INPUT) - port = new InputPort(bufs, this, port_name, j, _polyphony, data_type, val); + port = new InputPort(bufs, this, port_name, j, _polyphony, port_type, buffer_type, val); else - port = new OutputPort(bufs, this, port_name, j, _polyphony, data_type, val); + port = new OutputPort(bufs, this, port_name, j, _polyphony, port_type, buffer_type, val); - if (direction == INPUT && (data_type == PortType::CONTROL - || data_type == PortType::CV)) { + if (direction == INPUT && (port_type == PortType::CONTROL + || port_type == PortType::CV)) { port->set_value(val); if (!isnan(min_values[j])) { port->set_property(uris.lv2_minimum, forge.make(min_values[j])); @@ -309,7 +327,8 @@ LV2Node::instantiate(BufferFactory& bufs) LILV_FOREACH(nodes, i, properties) { const LilvNode* p = lilv_nodes_get(properties, i); if (lilv_node_is_uri(p)) { - port->add_property(uris.lv2_portProperty, Raul::URI(lilv_node_as_uri(p))); + port->add_property(uris.lv2_portProperty, + forge.alloc_uri(lilv_node_as_uri(p))); } } @@ -318,7 +337,8 @@ LV2Node::instantiate(BufferFactory& bufs) LILV_FOREACH(nodes, i, types) { const LilvNode* type = lilv_nodes_get(types, i); if (lilv_node_is_uri(type)) { - port->add_property(uris.atom_supports, Raul::URI(lilv_node_as_uri(type))); + port->add_property(uris.atom_supports, + forge.alloc_uri(lilv_node_as_uri(type))); } } @@ -411,7 +431,7 @@ LV2Node::set_port_buffer(uint32_t voice, uint32_t port_num, { NodeImpl::set_port_buffer(voice, port_num, buf, offset); lilv_instance_connect_port(instance(voice), port_num, - buf ? buf->port_data(_ports->at(port_num)->buffer_type(), offset) : NULL); + buf ? buf->port_data(_ports->at(port_num)->type(), offset) : NULL); } } // namespace Server diff --git a/src/server/NodeImpl.cpp b/src/server/NodeImpl.cpp index cee1cc0a..12cf2d61 100644 --- a/src/server/NodeImpl.cpp +++ b/src/server/NodeImpl.cpp @@ -155,8 +155,8 @@ NodeImpl::apply_poly(Raul::Maid& maid, uint32_t poly) void NodeImpl::set_buffer_size(Context& context, BufferFactory& bufs, - PortType type, - size_t size) + LV2_URID type, + uint32_t size) { if (_ports) { for (size_t i = 0; i < _ports->size(); ++i) { diff --git a/src/server/NodeImpl.hpp b/src/server/NodeImpl.hpp index d0d7b14e..a5c619fa 100644 --- a/src/server/NodeImpl.hpp +++ b/src/server/NodeImpl.hpp @@ -183,8 +183,8 @@ public: virtual void set_buffer_size(Context& context, BufferFactory& bufs, - PortType type, - size_t size); + LV2_URID type, + uint32_t size); /** The Patch this Node belongs to. */ inline PatchImpl* parent_patch() const { return (PatchImpl*)_parent; } diff --git a/src/server/Notification.cpp b/src/server/Notification.cpp index 44d21a2f..f661337e 100644 --- a/src/server/Notification.cpp +++ b/src/server/Notification.cpp @@ -30,7 +30,7 @@ Notification::post_process(Notification& note, Engine& engine) { const Ingen::Shared::URIs& uris = *engine.world()->uris().get(); - Raul::Forge& forge = engine.world()->forge(); + Ingen::Forge& forge = engine.world()->forge(); switch (note.type) { case PORT_VALUE: engine.broadcaster()->set_property(note.port->path(), diff --git a/src/server/ObjectBuffer.cpp b/src/server/ObjectBuffer.cpp deleted file mode 100644 index 407333d3..00000000 --- a/src/server/ObjectBuffer.cpp +++ /dev/null @@ -1,151 +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 "ingen/shared/LV2Features.hpp" -#include "ingen/shared/LV2URIMap.hpp" -#include "ObjectBuffer.hpp" -#include "Engine.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Server { - -/** 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::CV: - case PortType::AUDIO: - switch (_type.symbol()) { - case PortType::CONTROL: - return (float*)LV2_ATOM_BODY(atom()); - case PortType::CV: - case PortType::AUDIO: - return (float*)LV2_ATOM_CONTENTS(LV2_Atom_Vector, atom()) + 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::CV: - case PortType::AUDIO: - switch (_type.symbol()) { - case PortType::CONTROL: - return (float*)LV2_ATOM_BODY(atom()); - case PortType::CV: - case PortType::AUDIO: - return (float*)LV2_ATOM_CONTENTS(LV2_Atom_Vector, atom()) + 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 Server -} // namespace Ingen - diff --git a/src/server/ObjectBuffer.hpp b/src/server/ObjectBuffer.hpp deleted file mode 100644 index 93dc746b..00000000 --- a/src/server/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 "Buffer.hpp" - -namespace Ingen { -namespace Server { - -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 Server -} // namespace Ingen - -#endif // INGEN_ENGINE_OBJECTBUFFER_HPP diff --git a/src/server/OutputPort.cpp b/src/server/OutputPort.cpp index 11f637b3..8d454201 100644 --- a/src/server/OutputPort.cpp +++ b/src/server/OutputPort.cpp @@ -35,9 +35,10 @@ OutputPort::OutputPort(BufferFactory& bufs, uint32_t index, uint32_t poly, PortType type, + LV2_URID buffer_type, const Raul::Atom& value, size_t buffer_size) - : PortImpl(bufs, parent, symbol, index, poly, type, value, buffer_size) + : PortImpl(bufs, parent, symbol, index, poly, type, buffer_type, value, buffer_size) { if (!dynamic_cast<Patch*>(parent)) add_property(bufs.uris().rdf_type, bufs.uris().lv2_OutputPort); diff --git a/src/server/OutputPort.hpp b/src/server/OutputPort.hpp index 168ab7c4..906c9c64 100644 --- a/src/server/OutputPort.hpp +++ b/src/server/OutputPort.hpp @@ -46,6 +46,7 @@ public: uint32_t index, uint32_t poly, PortType type, + LV2_URID buffer_type, const Raul::Atom& value, size_t buffer_size=0); diff --git a/src/server/PatchImpl.cpp b/src/server/PatchImpl.cpp index c2d97d41..dca7f2ae 100644 --- a/src/server/PatchImpl.cpp +++ b/src/server/PatchImpl.cpp @@ -258,8 +258,8 @@ PatchImpl::process_single(ProcessContext& context) void PatchImpl::set_buffer_size(Context& context, BufferFactory& bufs, - PortType type, - size_t size) + LV2_URID type, + uint32_t size) { NodeImpl::set_buffer_size(context, bufs, type, size); @@ -346,7 +346,8 @@ PortImpl* PatchImpl::create_port(BufferFactory& bufs, const string& name, PortType type, - size_t buffer_size, + LV2_URID buffer_type, + uint32_t buffer_size, bool is_output, bool polyphonic) { @@ -360,7 +361,7 @@ PatchImpl::create_port(BufferFactory& bufs, value = bufs.forge().make(0.0f); return new DuplexPort(bufs, this, name, num_ports(), polyphonic, _polyphony, - type, value, buffer_size, is_output); + type, buffer_type, value, buffer_size, is_output); } /** Remove port from ports list used in pre-processing thread. diff --git a/src/server/PatchImpl.hpp b/src/server/PatchImpl.hpp index 004eb0cb..5704fad0 100644 --- a/src/server/PatchImpl.hpp +++ b/src/server/PatchImpl.hpp @@ -69,8 +69,8 @@ public: void set_buffer_size(Context& context, BufferFactory& bufs, - PortType type, - size_t size); + LV2_URID type, + uint32_t size); /** Prepare for a new (internal) polyphony value. * @@ -111,7 +111,8 @@ public: PortImpl* create_port(BufferFactory& bufs, const std::string& name, PortType type, - size_t buffer_size, + LV2_URID buffer_type, + uint32_t buffer_size, bool is_output, bool polyphonic); diff --git a/src/server/PortImpl.cpp b/src/server/PortImpl.cpp index 67255e5f..3cc8082c 100644 --- a/src/server/PortImpl.cpp +++ b/src/server/PortImpl.cpp @@ -27,10 +27,8 @@ #include "AudioBuffer.hpp" #include "BufferFactory.hpp" #include "Engine.hpp" -#include "EventBuffer.hpp" #include "NodeImpl.hpp" #include "Notification.hpp" -#include "ObjectBuffer.hpp" #include "PortImpl.hpp" #include "PortType.hpp" #include "ThreadManager.hpp" @@ -47,6 +45,7 @@ PortImpl::PortImpl(BufferFactory& bufs, uint32_t index, uint32_t poly, PortType type, + LV2_URID buffer_type, const Atom& value, size_t buffer_size) : GraphObjectImpl(bufs.uris(), node, name) @@ -55,6 +54,7 @@ PortImpl::PortImpl(BufferFactory& bufs, , _poly(poly) , _buffer_size(buffer_size) , _type(type) + , _buffer_type(buffer_type) , _value(value) , _min(bufs.forge().make(0.0f)) , _max(bufs.forge().make(1.0f)) @@ -68,11 +68,27 @@ PortImpl::PortImpl(BufferFactory& bufs, assert(node != NULL); assert(_poly > 0); - if (_buffer_size == 0) - _buffer_size = bufs.default_buffer_size(type); - const Ingen::Shared::URIs& uris = bufs.uris(); - add_property(uris.rdf_type, type.uri()); + + if (_buffer_size == 0) { + _buffer_size = bufs.default_buffer_size(buffer_type); + } + + if (_buffer_type == 0) { + switch (_type.symbol()) { + case PortType::CONTROL: + _buffer_type = uris.atom_Float; + break; + case PortType::AUDIO: + case PortType::CV: + _buffer_type = uris.atom_Sound; + break; + default: + break; + } + } + + add_property(uris.rdf_type, bufs.forge().alloc_uri(type.uri().str())); set_property(uris.lv2_index, bufs.forge().make((int32_t)index)); set_context(_context); } @@ -85,7 +101,8 @@ PortImpl::~PortImpl() bool PortImpl::supports(const Raul::URI& value_type) const { - return has_property(_bufs.uris().atom_supports, value_type); + return has_property(_bufs.uris().atom_supports, + _bufs.forge().alloc_uri(value_type.str())); } Raul::Array<BufferFactory::Ref>* @@ -108,9 +125,9 @@ bool PortImpl::prepare_poly(BufferFactory& bufs, uint32_t poly) { ThreadManager::assert_thread(THREAD_PRE_PROCESS); - if (buffer_type() != PortType::CONTROL && - buffer_type() != PortType::CV && - buffer_type() != PortType::AUDIO) { + if (_type != PortType::CONTROL && + _type != PortType::CV && + _type != PortType::AUDIO) { return false; } @@ -140,9 +157,9 @@ bool PortImpl::apply_poly(Maid& maid, uint32_t poly) { ThreadManager::assert_thread(THREAD_PROCESS); - if (buffer_type() != PortType::CONTROL && - buffer_type() != PortType::CV && - buffer_type() != PortType::AUDIO) { + if (_type != PortType::CONTROL && + _type != PortType::CV && + _type != PortType::AUDIO) { return false; } @@ -207,8 +224,8 @@ PortImpl::clear_buffers() void PortImpl::broadcast_value(Context& context, bool force) { - Raul::Forge& forge = context.engine().world()->forge(); - Raul::Atom val; + Ingen::Forge& forge = context.engine().world()->forge(); + Raul::Atom val; switch (_type.symbol()) { case PortType::UNKNOWN: break; @@ -224,21 +241,16 @@ PortImpl::broadcast_value(Context& context, bool force) case PortType::CV: val = forge.make(((AudioBuffer*)buffer(0).get())->value_at(0)); break; - case PortType::EVENTS: - if (((EventBuffer*)buffer(0).get())->event_count() > 0) { - const Notification note = Notification::make( - Notification::PORT_ACTIVITY, context.start(), this, forge.make(true)); - context.event_sink().write(sizeof(note), ¬e); - } - break; case PortType::VALUE: case PortType::MESSAGE: - std::cerr << "FIXME: Atom value" << std::endl; - /* - Ingen::Shared::LV2Atom::to_atom(_bufs.uris(), - ((ObjectBuffer*)buffer(0).get())->atom(), - val); - */ + if (_buffer_type == _bufs.uris().atom_Sequence) { + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)buffer(0)->atom(); + if (seq->atom.size > sizeof(LV2_Atom_Sequence_Body)) { + const Notification note = Notification::make( + Notification::PORT_ACTIVITY, context.start(), this, forge.make(true)); + context.event_sink().write(sizeof(note), ¬e); + } + } break; } @@ -265,11 +277,5 @@ PortImpl::set_context(Context::ID c) } } -PortType -PortImpl::buffer_type() const -{ - return _type; -} - } // namespace Server } // namespace Ingen diff --git a/src/server/PortImpl.hpp b/src/server/PortImpl.hpp index 2316a1d9..c67be49b 100644 --- a/src/server/PortImpl.hpp +++ b/src/server/PortImpl.hpp @@ -124,7 +124,8 @@ public: inline bool is_a(PortType type) const { return _type == type; } - PortType buffer_type() const; + PortType type() const { return _type; } + LV2_URID buffer_type() const { return _buffer_type; } bool supports(const Raul::URI& value_type) const; @@ -158,6 +159,7 @@ protected: uint32_t index, uint32_t poly, PortType type, + LV2_URID buffer_type, const Raul::Atom& value, size_t buffer_size); @@ -166,6 +168,7 @@ protected: uint32_t _poly; uint32_t _buffer_size; PortType _type; + LV2_URID _buffer_type; Raul::Atom _value; Raul::Atom _min; Raul::Atom _max; diff --git a/src/server/PortType.hpp b/src/server/PortType.hpp index b8fd747e..a2eac676 100644 --- a/src/server/PortType.hpp +++ b/src/server/PortType.hpp @@ -35,9 +35,8 @@ public: AUDIO = 1, CONTROL = 2, CV = 3, - EVENTS = 4, - VALUE = 5, - MESSAGE = 6, + VALUE = 4, + MESSAGE = 5, }; PortType(const Raul::URI& uri) @@ -49,8 +48,6 @@ public: _symbol = CONTROL; } else if (uri == type_uri(CV)) { _symbol = CV; - } else if (uri == type_uri(EVENTS)) { - _symbol = EVENTS; } else if (uri == type_uri(VALUE)) { _symbol = VALUE; } else if (uri == type_uri(MESSAGE)) { @@ -74,7 +71,6 @@ public: inline bool is_audio() { return _symbol == AUDIO; } inline bool is_control() { return _symbol == CONTROL; } inline bool is_cv() { return _symbol == CV; } - inline bool is_events() { return _symbol == EVENTS; } inline bool is_value() { return _symbol == VALUE; } inline bool is_message() { return _symbol == MESSAGE; } @@ -86,7 +82,6 @@ private: "http://lv2plug.in/ns/lv2core#AudioPort", "http://lv2plug.in/ns/lv2core#ControlPort", "http://lv2plug.in/ns/ext/cv-port#CVPort", - "http://lv2plug.in/ns/ext/event#EventPort", "http://lv2plug.in/ns/ext/atom#ValuePort", "http://lv2plug.in/ns/ext/atom#MessagePort" }; diff --git a/src/server/ServerInterfaceImpl.cpp b/src/server/ServerInterfaceImpl.cpp index f03294b2..69b26141 100644 --- a/src/server/ServerInterfaceImpl.cpp +++ b/src/server/ServerInterfaceImpl.cpp @@ -161,7 +161,7 @@ ServerInterfaceImpl::set_property(const URI& uri, const Atom& value) { if (uri == "ingen:engine" && predicate == "ingen:enabled" - && value.type() == Atom::BOOL) { + && value.type() == _engine.world()->forge().Bool) { if (value.get_bool()) { _engine.activate(); push_queued(new Events::Ping(_engine, _request_client, _request_id, now())); diff --git a/src/server/ServerInterfaceImpl.hpp b/src/server/ServerInterfaceImpl.hpp index 0ba3a1b9..21100222 100644 --- a/src/server/ServerInterfaceImpl.hpp +++ b/src/server/ServerInterfaceImpl.hpp @@ -51,6 +51,8 @@ public: Raul::URI uri() const { return "http://drobilla.net/ns/ingen#internal"; } + void set_response_interface(Interface* iface) { _request_client = iface; } + virtual void set_response_id(int32_t id); virtual void bundle_begin(); diff --git a/src/server/events/CreateNode.cpp b/src/server/events/CreateNode.cpp index d74b0b6c..7098196a 100644 --- a/src/server/events/CreateNode.cpp +++ b/src/server/events/CreateNode.cpp @@ -61,7 +61,7 @@ CreateNode::CreateNode(Engine& engine, { const Resource::Properties::const_iterator p = properties.find( engine.world()->uris()->ingen_polyphonic); - if (p != properties.end() && p->second.type() == Raul::Atom::BOOL + if (p != properties.end() && p->second.type() == engine.world()->forge().Bool && p->second.get_bool()) _polyphonic = true; } diff --git a/src/server/events/CreatePort.cpp b/src/server/events/CreatePort.cpp index 6fa4a6bf..cc6f7e93 100644 --- a/src/server/events/CreatePort.cpp +++ b/src/server/events/CreatePort.cpp @@ -49,7 +49,8 @@ CreatePort::CreatePort(Engine& engine, const Resource::Properties& properties) : Event(engine, client, id, timestamp) , _path(path) - , _data_type(PortType::UNKNOWN) + , _port_type(PortType::UNKNOWN) + , _buffer_type(0) , _patch(NULL) , _patch_port(NULL) , _ports_array(NULL) @@ -61,30 +62,31 @@ CreatePort::CreatePort(Engine& engine, typedef Resource::Properties::const_iterator Iterator; typedef std::pair<Iterator, Iterator> Range; + const Range types = properties.equal_range(uris.rdf_type); for (Iterator i = types.first; i != types.second; ++i) { const Raul::Atom& type = i->second; - if (type.type() != Atom::URI) { - warn << "Non-URI port type " << type << endl; - continue; - } - if (type == uris.lv2_AudioPort) { - _data_type = PortType::AUDIO; + _port_type = PortType::AUDIO; } else if (type == uris.lv2_ControlPort) { - _data_type = PortType::CONTROL; + _port_type = PortType::CONTROL; } else if (type == uris.cv_CVPort) { - _data_type = PortType::CV; - } else if (type == uris.ev_EventPort) { - _data_type = PortType::EVENTS; + _port_type = PortType::CV; } else if (type == uris.atom_ValuePort) { - _data_type = PortType::VALUE; + _port_type = PortType::VALUE; } else if (type == uris.atom_MessagePort) { - _data_type = PortType::MESSAGE; + _port_type = PortType::MESSAGE; + } + } + + const Range buffer_types = properties.equal_range(uris.atom_bufferType); + for (Iterator i = buffer_types.first; i != buffer_types.second; ++i) { + if (i->second.type() == _engine.world()->forge().URI) { + _buffer_type = _engine.world()->lv2_uri_map()->map_uri(i->second.get_uri()); } } - if (_data_type == PortType::UNKNOWN) { + if (_port_type == PortType::UNKNOWN) { _status = UNKNOWN_TYPE; } } @@ -104,7 +106,7 @@ CreatePort::pre_process() if (_patch != NULL) { assert(_patch->path() == _path.parent()); - size_t buffer_size = _engine.buffer_factory()->default_buffer_size(_data_type); + size_t buffer_size = _engine.buffer_factory()->default_buffer_size(_buffer_type); const uint32_t old_num_ports = (_patch->external_ports()) ? _patch->external_ports()->size() @@ -115,7 +117,7 @@ CreatePort::pre_process() index_i = _properties.insert( make_pair(uris.lv2_index, _engine.world()->forge().make(int32_t(old_num_ports)))); - } else if (index_i->second.type() != Atom::INT + } else if (index_i->second.type() != uris.forge.Int || index_i->second.get_int32() != static_cast<int32_t>(old_num_ports)) { Event::pre_process(); _status = BAD_INDEX; @@ -123,10 +125,12 @@ CreatePort::pre_process() } Resource::Properties::const_iterator poly_i = _properties.find(uris.ingen_polyphonic); - bool polyphonic = (poly_i != _properties.end() && poly_i->second.type() == Atom::BOOL + bool polyphonic = (poly_i != _properties.end() && poly_i->second.type() == uris.forge.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 = _patch->create_port(*_engine.buffer_factory(), _path.symbol(), + _port_type, _buffer_type, buffer_size, + _is_output, polyphonic); _patch_port->properties().insert(_properties.begin(), _properties.end()); diff --git a/src/server/events/CreatePort.hpp b/src/server/events/CreatePort.hpp index 331a1252..45fedebc 100644 --- a/src/server/events/CreatePort.hpp +++ b/src/server/events/CreatePort.hpp @@ -18,13 +18,13 @@ #ifndef INGEN_EVENTS_CREATEPORT_HPP #define INGEN_EVENTS_CREATEPORT_HPP +#include "ingen/Resource.hpp" +#include "lv2/lv2plug.in/ns/ext/urid/urid.h" #include "raul/Array.hpp" #include "raul/Path.hpp" -#include "ingen/Resource.hpp" - -#include "PortType.hpp" #include "Event.hpp" +#include "PortType.hpp" namespace Ingen { namespace Server { @@ -57,7 +57,8 @@ public: private: Raul::Path _path; Raul::URI _type; - PortType _data_type; + PortType _port_type; + LV2_URID _buffer_type; PatchImpl* _patch; PortImpl* _patch_port; Raul::Array<PortImpl*>* _ports_array; ///< New (external) ports array for Patch diff --git a/src/server/events/SetMetadata.cpp b/src/server/events/SetMetadata.cpp index e2621fae..1c4ac0e6 100644 --- a/src/server/events/SetMetadata.cpp +++ b/src/server/events/SetMetadata.cpp @@ -129,7 +129,7 @@ SetMetadata::pre_process() 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) + if (p != _properties.end() && p->second.is_valid() && p->second.type() == uris.forge.Int) poly = p->second.get_int32(); _create_event = new CreatePatch(_engine, _request_client, _request_id, _time, path, poly, _properties); @@ -186,7 +186,7 @@ SetMetadata::pre_process() PortImpl* port = dynamic_cast<PortImpl*>(_object); if (port) { if (key == uris.ingen_broadcast) { - if (value.type() == Atom::BOOL) { + if (value.type() == uris.forge.Bool) { op = ENABLE_BROADCAST; } else { _status = BAD_VALUE_TYPE; @@ -200,7 +200,7 @@ SetMetadata::pre_process() if (port->is_a(PortType::CONTROL) || port->is_a(PortType::CV)) { if (value == uris.wildcard) { _engine.control_bindings()->learn(port); - } else if (value.type() == Atom::DICT) { + } else if (value.type() == uris.forge.Dict) { op = CONTROL_BINDING; } else { _status = BAD_VALUE_TYPE; @@ -211,7 +211,7 @@ SetMetadata::pre_process() } } else if ((_patch = dynamic_cast<PatchImpl*>(_object))) { if (key == uris.ingen_enabled) { - if (value.type() == Atom::BOOL) { + if (value.type() == uris.forge.Bool) { op = ENABLE; // FIXME: defer this until all other metadata has been processed if (value.get_bool() && !_patch->enabled()) @@ -220,7 +220,7 @@ SetMetadata::pre_process() _status = BAD_VALUE_TYPE; } } else if (key == uris.ingen_polyphony) { - if (value.type() == Atom::INT) { + if (value.type() == uris.forge.Int) { op = POLYPHONY; _patch->prepare_internal_poly(*_engine.buffer_factory(), value.get_int32()); } else { @@ -230,7 +230,7 @@ SetMetadata::pre_process() } else if (key == uris.ingen_polyphonic) { PatchImpl* parent = dynamic_cast<PatchImpl*>(obj->parent()); if (parent) { - if (value.type() == Atom::BOOL) { + if (value.type() == uris.forge.Bool) { op = POLYPHONIC; obj->set_property(key, value, value.context()); NodeImpl* node = dynamic_cast<NodeImpl*>(obj); @@ -288,7 +288,7 @@ SetMetadata::execute(ProcessContext& context) std::vector<SpecialType>::const_iterator t = _types.begin(); for (Properties::const_iterator p = _properties.begin(); p != _properties.end(); ++p, ++t) { - const Raul::Atom& key = p->first; + const Raul::URI& key = p->first; const Raul::Atom& value = p->second; switch (*t) { case ENABLE_BROADCAST: diff --git a/src/server/events/SetPortValue.cpp b/src/server/events/SetPortValue.cpp index ecf9416e..00f72a51 100644 --- a/src/server/events/SetPortValue.cpp +++ b/src/server/events/SetPortValue.cpp @@ -22,7 +22,6 @@ #include "ingen/shared/LV2URIMap.hpp" #include "ingen/shared/URIs.hpp" #include "ingen/shared/World.hpp" -#include "lv2/lv2plug.in/ns/ext/event/event.h" #include "raul/log.hpp" #include "AudioBuffer.hpp" @@ -31,10 +30,8 @@ #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 "SetPortValue.hpp" @@ -129,6 +126,8 @@ SetPortValue::apply(Context& context) if (_status == SUCCESS && !_port) _port = _engine.engine_store()->find_port(_port_path); + Ingen::Shared::URIs& uris = *_engine.world()->uris().get(); + if (!_port) { if (_status == SUCCESS) _status = PORT_NOT_FOUND; @@ -138,7 +137,7 @@ SetPortValue::apply(Context& context) Buffer* const buf = _port->buffer(0).get(); AudioBuffer* const abuf = dynamic_cast<AudioBuffer*>(buf); if (abuf) { - if (_value.type() != Atom::FLOAT) { + if (_value.type() != uris.forge.Float) { _status = TYPE_MISMATCH; return; } @@ -150,44 +149,6 @@ SetPortValue::apply(Context& context) return; } - Ingen::Shared::URIs& uris = *_engine.world()->uris().get(); - Ingen::Shared::LV2URIMap& uri_map = *_engine.world()->lv2_uri_map().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 = uri_map.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, - uri_map.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; } } diff --git a/src/server/ingen_jack.cpp b/src/server/ingen_jack.cpp index 267b13aa..fd80d804 100644 --- a/src/server/ingen_jack.cpp +++ b/src/server/ingen_jack.cpp @@ -34,8 +34,11 @@ struct IngenJackModule : public Ingen::Shared::Module { Server::JackDriver* driver = new Server::JackDriver( *(Server::Engine*)world->local_engine().get()); - driver->attach(world->conf()->option("jack-server").get_string(), - world->conf()->option("jack-client").get_string(), NULL); + const Raul::Configuration::Value& s = world->conf()->option("jack-server"); + const std::string server_name = s.is_valid() ? s.get_string() : ""; + driver->attach(server_name, + world->conf()->option("jack-client").get_string(), + NULL); ((Server::Engine*)world->local_engine().get())->set_driver( SharedPtr<Server::Driver>(driver)); } diff --git a/src/server/ingen_lv2.cpp b/src/server/ingen_lv2.cpp index 3e9366ae..e6552e69 100644 --- a/src/server/ingen_lv2.cpp +++ b/src/server/ingen_lv2.cpp @@ -29,10 +29,13 @@ #include "lv2/lv2plug.in/ns/lv2core/lv2.h" #include "lv2/lv2plug.in/ns/ext/state/state.h" #include "lv2/lv2plug.in/ns/ext/urid/urid.h" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" #include "ingen/Interface.hpp" #include "ingen/serialisation/Parser.hpp" #include "ingen/serialisation/Serialiser.hpp" +#include "ingen/shared/AtomReader.hpp" +#include "ingen/shared/AtomWriter.hpp" #include "ingen/shared/Configuration.hpp" #include "ingen/shared/Store.hpp" #include "ingen/shared/World.hpp" @@ -54,7 +57,7 @@ #define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#" #define NS_RDFS "http://www.w3.org/2000/01/rdf-schema#" -/** Record of a patch in this Ingen LV2 bundle */ +/** Record of a patch in this bundle. */ struct LV2Patch { LV2Patch(const std::string& u, const std::string& f); @@ -63,6 +66,7 @@ struct LV2Patch { LV2_Descriptor descriptor; }; +/** Ingen LV2 library. */ class Lib { public: Lib(const char* bundle_path); @@ -77,6 +81,8 @@ namespace Server { class LV2Driver; +void handle_message(LV2Driver* driver, const LV2_Atom* msg); + class LV2Port : public DriverPort { public: @@ -92,26 +98,31 @@ public: void move(const Raul::Path& path) {} void pre_process(ProcessContext& context) { - if (!is_input() || !_buffer) + if (!is_input() || !_buffer) { return; + } if (_patch_port->is_a(PortType::AUDIO)) { AudioBuffer* patch_buf = (AudioBuffer*)_patch_port->buffer(0).get(); patch_buf->copy((Sample*)_buffer, 0, context.nframes() - 1); - } else if (_patch_port->is_a(PortType::EVENTS)) { - //Raul::warn << "TODO: LV2 event I/O" << std::endl; + } else { + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)_buffer; + LV2_SEQUENCE_FOREACH(seq, i) { + LV2_Atom_Event* ev = lv2_sequence_iter_get(i); + // FIXME: Not RT safe, need to send these through a ring + handle_message(_driver, &ev->body); + } } } void post_process(ProcessContext& context) { - if (is_input() || !_buffer) + if (is_input() || !_buffer) { return; + } if (_patch_port->is_a(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->is_a(PortType::EVENTS)) { - //Raul::warn << "TODO: LV2 event I/O" << std::endl; } } @@ -123,13 +134,23 @@ private: void* _buffer; }; -class LV2Driver : public Ingen::Server::Driver { +class LV2Driver : public Ingen::Server::Driver + , public Ingen::Shared::AtomSink +{ private: typedef std::vector<LV2Port*> Ports; public: LV2Driver(Engine& engine, SampleCount buffer_size, SampleCount sample_rate) : _context(engine) + , _reader(*engine.world()->lv2_uri_map().get(), + *engine.world()->uris().get(), + engine.world()->forge(), + *engine.world()->engine().get()) + , _writer(*engine.world()->lv2_uri_map().get(), + *engine.world()->uris().get(), + *this) + , _to_ui(8192) // FIXME: size , _root_patch(NULL) , _buffer_size(buffer_size) , _sample_rate(sample_rate) @@ -147,6 +168,8 @@ public: if (_root_patch) _root_patch->process(_context); + flush_to_ui(); + for (Ports::iterator i = _ports.begin(); i != _ports.end(); ++i) (*i)->post_process(_context); @@ -194,24 +217,88 @@ public: return NULL; } + void write(const LV2_Atom* atom) { + // Called from post-processor in main thread + if (_to_ui.write(lv2_atom_total_size(atom), atom) == 0) { + Raul::error << "To-UI ring overflow" << std::endl; + } + } + + void flush_to_ui() { + assert(ThreadManager::thread_is(THREAD_PROCESS)); + assert(_ports.size() >= 2); + + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)_ports[1]->buffer(); + if (!seq) { + Raul::warn << "Control out port not connected" << std::endl; + return; + } + + // Output port buffer is a Chunk with size set to the available space + const uint32_t capacity = seq->atom.size; + + // Initialise output port buffer to an empty Sequence + seq->atom.type = _context.engine().world()->uris()->atom_Sequence; + seq->atom.size = sizeof(LV2_Atom_Sequence_Body); + + const uint32_t read_space = _to_ui.read_space(); + for (uint32_t read = 0; read < read_space;) { + LV2_Atom atom; + if (!_to_ui.peek(sizeof(LV2_Atom), &atom)) { + Raul::error << "Error reading head from to-UI ring" << std::endl; + break; + } + + if (seq->atom.size + sizeof(LV2_Atom) + atom.size > capacity) { + break; // Output port buffer full, resume next time + } + + LV2_Atom_Event* ev = (LV2_Atom_Event*)( + (uint8_t*)seq + lv2_atom_total_size(&seq->atom)); + + ev->time.frames = 0; // TODO: Time? + ev->body = atom; + + _to_ui.skip(sizeof(LV2_Atom)); + if (!_to_ui.read(ev->body.size, LV2_ATOM_BODY(&ev->body))) { + Raul::error << "Error reading body from to-UI ring" << std::endl; + break; + } + + read += lv2_atom_total_size(&ev->body); + seq->atom.size += sizeof(LV2_Atom_Event) + ev->body.size; + } + } + 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; } + Shared::AtomReader& reader() { return _reader; } + Shared::AtomWriter& writer() { return _writer; } Ports& ports() { return _ports; } private: - ProcessContext _context; - PatchImpl* _root_patch; - SampleCount _buffer_size; - SampleCount _sample_rate; - SampleCount _frame_time; - Ports _ports; + ProcessContext _context; + Shared::AtomReader _reader; + Shared::AtomWriter _writer; + Raul::RingBuffer _to_ui; + PatchImpl* _root_patch; + SampleCount _buffer_size; + SampleCount _sample_rate; + SampleCount _frame_time; + Ports _ports; }; +void +handle_message(LV2Driver* driver, const LV2_Atom* msg) +{ + driver->reader().write(msg); +} + } // namespace Server } // namespace Ingen @@ -236,7 +323,7 @@ private: }; struct IngenPlugin { - Raul::Forge forge; + Ingen::Forge forge; Ingen::Shared::Configuration* conf; Ingen::Shared::World* world; MainThread* main; @@ -304,7 +391,7 @@ ingen_instantiate(const LV2_Descriptor* descriptor, } IngenPlugin* plugin = (IngenPlugin*)malloc(sizeof(IngenPlugin)); - plugin->conf = new Ingen::Shared::Configuration(&plugin->forge); + plugin->conf = new Ingen::Shared::Configuration(); plugin->main = NULL; plugin->map = NULL; LV2_URID_Unmap* unmap = NULL; @@ -341,6 +428,10 @@ ingen_instantiate(const LV2_Descriptor* descriptor, LV2Driver* driver = new LV2Driver(*engine.get(), rate, 4096); engine->set_driver(SharedPtr<Ingen::Server::Driver>(driver)); + interface->set_response_interface(&driver->writer()); + engine->register_client("http://drobilla.net/ns/ingen#internal", + &driver->writer()); + engine->activate(); Server::ThreadManager::single_threaded = true; @@ -350,7 +441,7 @@ ingen_instantiate(const LV2_Descriptor* descriptor, engine->post_processor()->set_end_time(UINT_MAX); // TODO: Load only necessary plugins - plugin->world->engine()->get("ingen:plugins"); + //plugin->world->engine()->get("ingen:plugins"); interface->process(*engine->post_processor(), context, false); engine->post_processor()->process(); @@ -365,7 +456,7 @@ ingen_instantiate(const LV2_Descriptor* descriptor, engine->deactivate(); - plugin->world->load_module("osc_server"); + //plugin->world->load_module("osc_server"); return (LV2_Handle)plugin; } @@ -381,6 +472,7 @@ ingen_connect_port(LV2_Handle instance, uint32_t port, void* data) if (port < driver->ports().size()) { driver->ports().at(port)->set_buffer(data); assert(driver->ports().at(port)->patch_port()->index() == port); + assert(driver->ports().at(port)->buffer() == data); } else { Raul::warn << "Connect to non-existent port " << port << std::endl; } @@ -391,6 +483,7 @@ ingen_activate(LV2_Handle instance) { IngenPlugin* me = (IngenPlugin*)instance; me->world->local_engine()->activate(); + ((ServerInterfaceImpl*)me->world->engine().get())->start(); me->main->start(); } diff --git a/src/server/internals/Controller.cpp b/src/server/internals/Controller.cpp index e93d5f27..3c29edd3 100644 --- a/src/server/internals/Controller.cpp +++ b/src/server/internals/Controller.cpp @@ -20,10 +20,10 @@ #include "ingen/shared/LV2URIMap.hpp" #include "ingen/shared/URIs.hpp" #include "internals/Controller.hpp" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" #include "raul/midi_events.h" #include "AudioBuffer.hpp" -#include "EventBuffer.hpp" #include "InputPort.hpp" #include "InternalPlugin.hpp" #include "Notification.hpp" @@ -54,37 +54,38 @@ ControllerNode::ControllerNode(InternalPlugin* plugin, const Ingen::Shared::URIs& 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, bufs.forge().make("Input")); + _midi_in_port = new InputPort(bufs, this, "input", 0, 1, + PortType::MESSAGE, uris.atom_Sequence, Raul::Atom()); + _midi_in_port->set_property(uris.lv2_name, bufs.forge().alloc("Input")); _ports->at(0) = _midi_in_port; _param_port = new InputPort(bufs, this, "controller", 1, 1, - PortType::CONTROL, bufs.forge().make(0.0f)); + PortType::CONTROL, 0, bufs.forge().make(0.0f)); _param_port->set_property(uris.lv2_minimum, bufs.forge().make(0.0f)); _param_port->set_property(uris.lv2_maximum, bufs.forge().make(127.0f)); _param_port->set_property(uris.lv2_integer, bufs.forge().make(true)); - _param_port->set_property(uris.lv2_name, bufs.forge().make("Controller")); + _param_port->set_property(uris.lv2_name, bufs.forge().alloc("Controller")); _ports->at(1) = _param_port; _log_port = new InputPort(bufs, this, "logarithmic", 2, 1, - PortType::CONTROL, bufs.forge().make(0.0f)); + PortType::CONTROL, 0, bufs.forge().make(0.0f)); _log_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _log_port->set_property(uris.lv2_name, bufs.forge().make("Logarithmic")); + _log_port->set_property(uris.lv2_name, bufs.forge().alloc("Logarithmic")); _ports->at(2) = _log_port; _min_port = new InputPort(bufs, this, "minimum", 3, 1, - PortType::CONTROL, bufs.forge().make(0.0f)); - _min_port->set_property(uris.lv2_name, bufs.forge().make("Minimum")); + PortType::CONTROL, 0, bufs.forge().make(0.0f)); + _min_port->set_property(uris.lv2_name, bufs.forge().alloc("Minimum")); _ports->at(3) = _min_port; _max_port = new InputPort(bufs, this, "maximum", 4, 1, - PortType::CONTROL, bufs.forge().make(1.0f)); - _max_port->set_property(uris.lv2_name, bufs.forge().make("Maximum")); + PortType::CONTROL, 0, bufs.forge().make(1.0f)); + _max_port->set_property(uris.lv2_name, bufs.forge().alloc("Maximum")); _ports->at(4) = _max_port; _audio_port = new OutputPort(bufs, this, "ar_output", 5, 1, - PortType::AUDIO, bufs.forge().make(0.0f)); - _audio_port->set_property(uris.lv2_name, bufs.forge().make("Output")); + PortType::AUDIO, 0, bufs.forge().make(0.0f)); + _audio_port->set_property(uris.lv2_name, bufs.forge().alloc("Output")); _ports->at(5) = _audio_port; } @@ -93,22 +94,15 @@ 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(); + Buffer* const midi_in = _midi_in_port->buffer(0).get(); + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)midi_in->atom(); + LV2_SEQUENCE_FOREACH(seq, i) { + LV2_Atom_Event* const ev = lv2_sequence_iter_get(i); + const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body); + if (ev->body.type == _midi_in_port->bufs().uris().midi_MidiEvent && + ev->body.size >= 3 && (buf[0] & 0xF0) == MIDI_CMD_CONTROL) { + control(context, buf[1], buf[2], ev->time.frames + context.start()); + } } NodeImpl::post_process(context); diff --git a/src/server/internals/Controller.hpp b/src/server/internals/Controller.hpp index d664bf55..ac412c10 100644 --- a/src/server/internals/Controller.hpp +++ b/src/server/internals/Controller.hpp @@ -57,14 +57,13 @@ public: static InternalPlugin* internal_plugin(Shared::URIs& uris); private: - bool _learning; - InputPort* _midi_in_port; InputPort* _param_port; InputPort* _log_port; InputPort* _min_port; InputPort* _max_port; OutputPort* _audio_port; + bool _learning; }; } // namespace Server diff --git a/src/server/internals/Delay.cpp b/src/server/internals/Delay.cpp index 21cc23d5..dc55355e 100644 --- a/src/server/internals/Delay.cpp +++ b/src/server/internals/Delay.cpp @@ -28,7 +28,6 @@ #include "internals/Delay.hpp" #include "AudioBuffer.hpp" #include "Driver.hpp" -#include "EventBuffer.hpp" #include "InputPort.hpp" #include "InternalPlugin.hpp" #include "OutputPort.hpp" @@ -75,22 +74,22 @@ DelayNode::DelayNode( _delay_samples = default_delay; _delay_port = new InputPort(bufs, this, "delay", 1, _polyphony, - PortType::CONTROL, bufs.forge().make(default_delay)); - _delay_port->set_property(uris.lv2_name, bufs.forge().make("Delay")); + PortType::CONTROL, 0, bufs.forge().make(default_delay)); + _delay_port->set_property(uris.lv2_name, bufs.forge().alloc("Delay")); _delay_port->set_property(uris.lv2_default, bufs.forge().make(default_delay)); _delay_port->set_property(uris.lv2_minimum, bufs.forge().make((float)(1.0/(double)srate))); _delay_port->set_property(uris.lv2_maximum, bufs.forge().make(MAX_DELAY_SECONDS)); _ports->at(0) = _delay_port; _in_port = new InputPort(bufs, this, "in", 0, 1, - PortType::AUDIO, bufs.forge().make(0.0f)); - _in_port->set_property(uris.lv2_name, bufs.forge().make("Input")); + PortType::AUDIO, 0, bufs.forge().make(0.0f)); + _in_port->set_property(uris.lv2_name, bufs.forge().alloc("Input")); _ports->at(1) = _in_port; _out_port = new OutputPort(bufs, this, "out", 0, 1, - PortType::AUDIO, bufs.forge().make(0.0f)); + PortType::AUDIO, 0, bufs.forge().make(0.0f)); _out_port->set_property(uris.lv2_name, - bufs.forge().make("Output")); + bufs.forge().alloc("Output")); _ports->at(2) = _out_port; //_buffer = bufs.get(PortType::AUDIO, bufs.audio_buffer_size(buffer_length_frames), true); diff --git a/src/server/internals/Note.cpp b/src/server/internals/Note.cpp index a44c0c36..e591bfd8 100644 --- a/src/server/internals/Note.cpp +++ b/src/server/internals/Note.cpp @@ -19,22 +19,22 @@ #include "ingen/shared/LV2URIMap.hpp" #include "ingen/shared/URIs.hpp" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" #include "raul/Array.hpp" #include "raul/Maid.hpp" #include "raul/log.hpp" #include "raul/midi_events.h" -#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" +#include "internals/Note.hpp" +#include "util.hpp" #define LOG(s) s << "[NoteNode] " @@ -65,32 +65,32 @@ NoteNode::NoteNode( _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, bufs.forge().make("Input")); + PortType::MESSAGE, uris.atom_Sequence, Raul::Atom()); + _midi_in_port->set_property(uris.lv2_name, bufs.forge().alloc("Input")); _ports->at(0) = _midi_in_port; _freq_port = new OutputPort(bufs, this, "frequency", 1, _polyphony, - PortType::AUDIO, bufs.forge().make(440.0f)); - _freq_port->set_property(uris.lv2_name, bufs.forge().make("Frequency")); + PortType::AUDIO, 0, bufs.forge().make(440.0f)); + _freq_port->set_property(uris.lv2_name, bufs.forge().alloc("Frequency")); _ports->at(1) = _freq_port; _vel_port = new OutputPort(bufs, this, "velocity", 2, _polyphony, - PortType::AUDIO, bufs.forge().make(0.0f)); + PortType::AUDIO, 0, bufs.forge().make(0.0f)); _vel_port->set_property(uris.lv2_minimum, bufs.forge().make(0.0f)); _vel_port->set_property(uris.lv2_maximum, bufs.forge().make(1.0f)); - _vel_port->set_property(uris.lv2_name, bufs.forge().make("Velocity")); + _vel_port->set_property(uris.lv2_name, bufs.forge().alloc("Velocity")); _ports->at(2) = _vel_port; _gate_port = new OutputPort(bufs, this, "gate", 3, _polyphony, - PortType::AUDIO, bufs.forge().make(0.0f)); + PortType::AUDIO, 0, bufs.forge().make(0.0f)); _gate_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _gate_port->set_property(uris.lv2_name, bufs.forge().make("Gate")); + _gate_port->set_property(uris.lv2_name, bufs.forge().alloc("Gate")); _ports->at(3) = _gate_port; _trig_port = new OutputPort(bufs, this, "trigger", 4, _polyphony, - PortType::AUDIO, bufs.forge().make(0.0f)); + PortType::AUDIO, 0, bufs.forge().make(0.0f)); _trig_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _trig_port->set_property(uris.lv2_name, bufs.forge().make("Trigger")); + _trig_port->set_property(uris.lv2_name, bufs.forge().alloc("Trigger")); _ports->at(4) = _trig_port; } @@ -135,42 +135,24 @@ NoteNode::apply_poly(Raul::Maid& maid, uint32_t poly) 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) { + + Buffer* const midi_in = _midi_in_port->buffer(0).get(); + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)midi_in->atom(); + LV2_SEQUENCE_FOREACH(seq, i) { + LV2_Atom_Event* const ev = lv2_sequence_iter_get(i); + const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body); + const FrameTime time = context.start() + (FrameTime)ev->time.frames; + + if (ev->body.type == _midi_in_port->bufs().uris().midi_MidiEvent && + ev->body.size >= 3) { switch (buf[0] & 0xF0) { case MIDI_CMD_NOTE_ON: - if (buf[2] == 0) + if (buf[2] == 0) { note_off(context, buf[1], time); - else + } else { note_on(context, buf[1], buf[2], time); + } break; case MIDI_CMD_NOTE_OFF: note_off(context, buf[1], time); @@ -182,10 +164,11 @@ NoteNode::process(ProcessContext& context) all_notes_off(context, time); break; case MIDI_CTL_SUSTAIN: - if (buf[2] > 63) + if (buf[2] > 63) { sustain_on(context, time); - else + } else { sustain_off(context, time); + } break; case MIDI_CMD_BENDER: // ? diff --git a/src/server/internals/Trigger.cpp b/src/server/internals/Trigger.cpp index 885144fe..3ccc44d7 100644 --- a/src/server/internals/Trigger.cpp +++ b/src/server/internals/Trigger.cpp @@ -19,11 +19,11 @@ #include "ingen/shared/LV2URIMap.hpp" #include "ingen/shared/URIs.hpp" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" #include "raul/log.hpp" #include "raul/midi_events.h" #include "AudioBuffer.hpp" -#include "EventBuffer.hpp" #include "InputPort.hpp" #include "InternalPlugin.hpp" #include "OutputPort.hpp" @@ -58,35 +58,36 @@ TriggerNode::TriggerNode( const Ingen::Shared::URIs& 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, bufs.forge().make("Input")); + _midi_in_port = new InputPort(bufs, this, "input", 0, 1, + PortType::MESSAGE, uris.atom_Sequence, Raul::Atom()); + _midi_in_port->set_property(uris.lv2_name, bufs.forge().alloc("Input")); _ports->at(0) = _midi_in_port; _note_port = new InputPort(bufs, this, "note", 1, 1, - PortType::CONTROL, bufs.forge().make(60.0f)); + PortType::CONTROL, 0, bufs.forge().make(60.0f)); _note_port->set_property(uris.lv2_minimum, bufs.forge().make(0.0f)); _note_port->set_property(uris.lv2_maximum, bufs.forge().make(127.0f)); _note_port->set_property(uris.lv2_integer, bufs.forge().make(true)); - _note_port->set_property(uris.lv2_name, bufs.forge().make("Note")); + _note_port->set_property(uris.lv2_name, bufs.forge().alloc("Note")); _ports->at(1) = _note_port; _gate_port = new OutputPort(bufs, this, "gate", 2, 1, - PortType::AUDIO, bufs.forge().make(0.0f)); + PortType::AUDIO, 0, bufs.forge().make(0.0f)); _gate_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _gate_port->set_property(uris.lv2_name, bufs.forge().make("Gate")); + _gate_port->set_property(uris.lv2_name, bufs.forge().alloc("Gate")); _ports->at(2) = _gate_port; _trig_port = new OutputPort(bufs, this, "trigger", 3, 1, - PortType::AUDIO, bufs.forge().make(0.0f)); + PortType::AUDIO, 0, bufs.forge().make(0.0f)); _trig_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _trig_port->set_property(uris.lv2_name, bufs.forge().make("Trigger")); + _trig_port->set_property(uris.lv2_name, bufs.forge().alloc("Trigger")); _ports->at(3) = _trig_port; _vel_port = new OutputPort(bufs, this, "velocity", 4, 1, - PortType::AUDIO, bufs.forge().make(0.0f)); + PortType::AUDIO, 0, bufs.forge().make(0.0f)); _vel_port->set_property(uris.lv2_minimum, bufs.forge().make(0.0f)); _vel_port->set_property(uris.lv2_maximum, bufs.forge().make(1.0f)); - _vel_port->set_property(uris.lv2_name, bufs.forge().make("Velocity")); + _vel_port->set_property(uris.lv2_name, bufs.forge().alloc("Velocity")); _ports->at(4) = _vel_port; } @@ -95,40 +96,35 @@ 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) { + Buffer* const midi_in = _midi_in_port->buffer(0).get(); + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)midi_in->atom(); + LV2_SEQUENCE_FOREACH(seq, i) { + LV2_Atom_Event* const ev = lv2_sequence_iter_get(i); + const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body); + if (ev->body.type == _midi_in_port->bufs().uris().midi_MidiEvent && + ev->body.size >= 3) { + const FrameTime time = context.start() + ev->time.frames; switch (buf[0] & 0xF0) { case MIDI_CMD_NOTE_ON: - if (buf[2] == 0) + if (buf[2] == 0) { note_off(context, buf[1], time); - else + } 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); + 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); diff --git a/src/server/mix.hpp b/src/server/mix.hpp index 21040c52..54f80dfc 100644 --- a/src/server/mix.hpp +++ b/src/server/mix.hpp @@ -20,36 +20,45 @@ #include <boost/intrusive_ptr.hpp> +#include "ingen/shared/URIs.hpp" #include "raul/log.hpp" #include "Buffer.hpp" #include "Context.hpp" -#include "PortType.hpp" using namespace Raul; namespace Ingen { namespace Server { +inline bool +is_audio(Shared::URIs& uris, LV2_URID type) +{ + return type == uris.atom_Float || type == uris.atom_Sound; +} + inline void -mix(Context& context, Buffer* dst, const boost::intrusive_ptr<Buffer>* srcs, uint32_t num_srcs) +mix(Context& context, + Shared::URIs& uris, + Buffer* dst, + const boost::intrusive_ptr<Buffer>* srcs, + uint32_t num_srcs) { - using Ingen::PortType; - switch (dst->type().symbol()) { - case PortType::AUDIO: - case PortType::CONTROL: - case PortType::CV: + if (num_srcs == 1) { + dst->copy(context, srcs[0].get()); + } else if (is_audio(uris, dst->type())) { // 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 || - srcs[i]->type() == PortType::CV); + assert(is_audio(uris, srcs[i]->type())); ((AudioBuffer*)dst)->accumulate(context, (AudioBuffer*)srcs[i].get()); } - break; + } else { + std::cerr << "FIXME: event mix" << std::endl; + } +#if 0 case PortType::EVENTS: dst->clear(); for (uint32_t i = 0; i < num_srcs; ++i) { @@ -77,14 +86,7 @@ mix(Context& context, Buffer* dst, const boost::intrusive_ptr<Buffer>* srcs, uin } } dst->rewind(); - break; - default: - if (num_srcs == 1) - dst->copy(context, srcs[0].get()); - else - error << "Mix of unsupported buffer types" << std::endl; - return; - } +#endif } } // namespace Server diff --git a/src/server/wscript b/src/server/wscript index 33ffc58a..58a3918a 100644 --- a/src/server/wscript +++ b/src/server/wscript @@ -4,6 +4,7 @@ from waflib.extras import autowaf as autowaf def build(bld): core_source = ''' AudioBuffer.cpp + Buffer.cpp BufferFactory.cpp ClientBroadcaster.cpp ConnectionImpl.cpp @@ -12,7 +13,6 @@ def build(bld): Engine.cpp EngineStore.cpp Event.cpp - EventBuffer.cpp EventSource.cpp GraphObjectImpl.cpp InputPort.cpp @@ -24,7 +24,6 @@ def build(bld): NodeFactory.cpp NodeImpl.cpp Notification.cpp - ObjectBuffer.cpp ObjectSender.cpp OutputPort.cpp PatchImpl.cpp |