summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/engine/AudioBuffer.cpp229
-rw-r--r--src/engine/AudioBuffer.hpp72
-rw-r--r--src/engine/Buffer.cpp12
-rw-r--r--src/engine/Buffer.hpp26
-rw-r--r--src/engine/BufferFactory.cpp124
-rw-r--r--src/engine/BufferFactory.hpp69
-rw-r--r--src/engine/ConnectionImpl.cpp179
-rw-r--r--src/engine/ConnectionImpl.hpp66
-rw-r--r--src/engine/DuplexPort.cpp53
-rw-r--r--src/engine/DuplexPort.hpp3
-rw-r--r--src/engine/Engine.cpp8
-rw-r--r--src/engine/Engine.hpp3
-rw-r--r--src/engine/EventBuffer.cpp38
-rw-r--r--src/engine/EventBuffer.hpp11
-rw-r--r--src/engine/InputPort.cpp191
-rw-r--r--src/engine/InputPort.hpp11
-rw-r--r--src/engine/InternalPlugin.cpp12
-rw-r--r--src/engine/InternalPlugin.hpp4
-rw-r--r--src/engine/JackAudioDriver.cpp47
-rw-r--r--src/engine/JackAudioDriver.hpp4
-rw-r--r--src/engine/JackMidiDriver.cpp4
-rw-r--r--src/engine/LADSPANode.cpp33
-rw-r--r--src/engine/LADSPANode.hpp6
-rw-r--r--src/engine/LADSPAPlugin.cpp5
-rw-r--r--src/engine/LADSPAPlugin.hpp3
-rw-r--r--src/engine/LV2Node.cpp25
-rw-r--r--src/engine/LV2Node.hpp6
-rw-r--r--src/engine/LV2Plugin.cpp5
-rw-r--r--src/engine/LV2Plugin.hpp3
-rw-r--r--src/engine/NodeBase.cpp16
-rw-r--r--src/engine/NodeBase.hpp6
-rw-r--r--src/engine/NodeFactory.cpp25
-rw-r--r--src/engine/NodeImpl.hpp12
-rw-r--r--src/engine/ObjectBuffer.cpp97
-rw-r--r--src/engine/ObjectBuffer.hpp17
-rw-r--r--src/engine/ObjectSender.cpp2
-rw-r--r--src/engine/OutputPort.cpp14
-rw-r--r--src/engine/OutputPort.hpp3
-rw-r--r--src/engine/PatchImpl.cpp16
-rw-r--r--src/engine/PatchImpl.hpp6
-rw-r--r--src/engine/PatchPlugin.hpp3
-rw-r--r--src/engine/PluginImpl.cpp1
-rw-r--r--src/engine/PluginImpl.hpp4
-rw-r--r--src/engine/PortImpl.cpp57
-rw-r--r--src/engine/PortImpl.hpp38
-rw-r--r--src/engine/QueuedEngineInterface.cpp4
-rw-r--r--src/engine/events/Connect.cpp2
-rw-r--r--src/engine/events/CreateNode.cpp2
-rw-r--r--src/engine/events/CreatePort.cpp2
-rw-r--r--src/engine/events/RequestMetadata.cpp4
-rw-r--r--src/engine/events/SetMetadata.cpp2
-rw-r--r--src/engine/events/SetPortValue.cpp16
-rw-r--r--src/engine/internals/Controller.cpp37
-rw-r--r--src/engine/internals/Controller.hpp2
-rw-r--r--src/engine/internals/Note.cpp39
-rw-r--r--src/engine/internals/Note.hpp4
-rw-r--r--src/engine/internals/Transport.cpp158
-rw-r--r--src/engine/internals/Transport.hpp47
-rw-r--r--src/engine/internals/Trigger.cpp34
-rw-r--r--src/engine/internals/Trigger.hpp2
-rw-r--r--src/engine/wscript3
-rw-r--r--src/shared/LV2URIMap.cpp1
-rw-r--r--src/shared/LV2URIMap.hpp1
63 files changed, 813 insertions, 1116 deletions
diff --git a/src/engine/AudioBuffer.cpp b/src/engine/AudioBuffer.cpp
index 53924ae4..1b5a582e 100644
--- a/src/engine/AudioBuffer.cpp
+++ b/src/engine/AudioBuffer.cpp
@@ -18,9 +18,13 @@
#include <iostream>
#include <cassert>
#include <stdlib.h>
+#include "raul/SharedPtr.hpp"
+#include "object.lv2/object.h"
#include "ingen-config.h"
#include "AudioBuffer.hpp"
#include "ProcessContext.hpp"
+#include "LV2Features.hpp"
+#include "LV2URIMap.hpp"
using namespace std;
@@ -32,96 +36,61 @@ namespace Ingen {
using namespace Shared;
-AudioBuffer::AudioBuffer(size_t size)
- : Buffer((size == 1) ? DataType::CONTROL : DataType::AUDIO, size)
- , _data(NULL)
- , _local_data(NULL)
- , _filled_size(0)
+AudioBuffer::AudioBuffer(Shared::DataType type, size_t size)
+ : ObjectBuffer(size + sizeof(LV2_Object)
+ + (type == DataType::AUDIO ? sizeof(LV2_Vector_Body) : 0))
+ , _port_type(type)
, _state(OK)
, _set_value(0)
, _set_time(0)
{
- assert(_size > 0);
- allocate();
+ assert(size >= sizeof(Sample));
+ assert(this->size() > size);
assert(data());
-}
-
-
-void
-AudioBuffer::alloc_local_data(size_t size)
-{
-#ifdef HAVE_POSIX_MEMALIGN
- const int ret = posix_memalign((void**)&_local_data, 16, size * sizeof(Sample));
-#else
- _local_data = (Sample*)malloc(size * sizeof(Sample));
- int ret = (_local_data != NULL) ? 0 : -1;
-#endif
- if (ret != 0) {
- cerr << "[Buffer] Failed to allocate buffer. Aborting." << endl;
- exit(EXIT_FAILURE);
+ _type = type;
+
+ // Control port / Single float object
+ if (type == DataType::CONTROL) {
+ object()->type = 0;//map->float_type;
+
+ // Audio port / Vector of float
+ } else {
+ assert(type == DataType::AUDIO);
+ object()->type = 0;//map->vector_type;
+ LV2_Vector_Body* body = (LV2_Vector_Body*)object()->body;
+ body->elem_count = size / sizeof(Sample);
+ body->elem_type = 0;//map->float_type;
}
-}
-void
-AudioBuffer::resize(size_t size)
-{
- _size = size;
-
- Sample* const old_data = _data;
-
- const bool using_local_data = (_data == _local_data);
-
- deallocate();
- alloc_local_data(_size * sizeof(Sample));
- assert(_local_data);
-
- if (using_local_data)
- _data = _local_data;
- else
- _data = old_data;
-
- set_block(0, 0, _size - 1);
+ /*cout << "Created Audio Buffer" << endl
+ << "\tobject @ " << (void*)object() << endl
+ << "\tbody @ " << (void*)object()->body
+ << "\t(offset " << (char*)object()->body - (char*)object() << ")" << endl
+ << "\tdata @ " << (void*)data()
+ << "\t(offset " << (char*)data() - (char*)object() << ")"
+ << endl;*/
}
-/** Allocate and use a locally managed buffer (data).
- */
void
-AudioBuffer::allocate()
+AudioBuffer::resize(size_t size)
{
- assert(!_joined_buf);
- assert(_local_data == NULL);
- assert(_size > 0);
-
- alloc_local_data(_size * sizeof(Sample));
- assert(_local_data);
-
- _data = _local_data;
-
+ if (_port_type == DataType::AUDIO) {
+ ObjectBuffer::resize(size + sizeof(LV2_Vector_Body));
+ vector()->elem_count = size / sizeof(Sample);
+ }
clear();
}
-/** Free locally allocated buffer.
- */
-void
-AudioBuffer::deallocate()
-{
- assert(!_joined_buf);
- free(_local_data);
- _local_data = NULL;
- _data = NULL;
-}
-
-
/** Empty (ie zero) the buffer.
*/
void
AudioBuffer::clear()
{
- set_block(0, 0, _size - 1);
+ assert(nframes() != 0);
+ set_block(0, 0, nframes() - 1);
_state = OK;
- _filled_size = 0;
}
@@ -134,14 +103,15 @@ AudioBuffer::clear()
void
AudioBuffer::set_value(Sample val, FrameTime cycle_start, FrameTime time)
{
- if (_size == 1)
+ if (_port_type == DataType::CONTROL)
time = cycle_start;
- FrameTime offset = time - cycle_start;
- assert(offset <= _size);
+ const FrameTime offset = time - cycle_start;
+ assert(nframes() != 0);
+ assert(offset <= nframes());
- if (offset < _size) {
- set_block(val, offset, _size - 1);
+ if (offset < nframes()) {
+ set_block(val, offset, nframes() - 1);
if (offset > 0)
_state = HALF_SET_CYCLE_1;
@@ -160,7 +130,7 @@ void
AudioBuffer::set_block(Sample val, size_t start_offset, size_t end_offset)
{
assert(end_offset >= start_offset);
- assert(end_offset < _size);
+ assert(end_offset < nframes());
Sample* const buf = data();
assert(buf);
@@ -170,52 +140,34 @@ AudioBuffer::set_block(Sample val, size_t start_offset, size_t end_offset)
}
-/** Scale a block of buffer by @a val.
- *
- * @a start_sample and @a end_sample define the inclusive range to be set.
- */
-void
-AudioBuffer::scale(Sample val, size_t start_sample, size_t end_sample)
-{
- assert(end_sample >= start_sample);
- assert(end_sample < _size);
-
- Sample* const buf = data();
- assert(buf);
-
- for (size_t i=start_sample; i <= end_sample; ++i)
- buf[i] *= val;
-}
-
-
/** Copy a block of @a src into buffer.
*
* @a start_sample and @a end_sample define the inclusive range to be set.
* This function only copies the same range in one buffer to another.
*/
void
-AudioBuffer::copy(const Buffer* src, size_t start_sample, size_t end_sample)
+AudioBuffer::copy(const Sample* src, size_t start_sample, size_t end_sample)
{
assert(end_sample >= start_sample);
- assert(src);
- assert(src->type() == DataType::CONTROL || DataType::AUDIO);
+ assert(nframes() != 0);
Sample* const buf = data();
assert(buf);
- const Sample* const src_buf = ((AudioBuffer*)src)->data();
- assert(src_buf);
-
- const size_t to_copy = std::min(end_sample, _size - 1);
- for (size_t i = start_sample; i <= to_copy; ++i)
- buf[i] = src_buf[i];
+ const size_t copy_end = std::min(end_sample, (size_t)nframes() - 1);
+ for (size_t i = start_sample; i <= copy_end; ++i)
+ buf[i] = src[i];
}
void
AudioBuffer::copy(Context& context, const Buffer* src)
{
- copy(src, context.start(), std::min(size(), src->size()));
+ if (_type == src->type()) {
+ ObjectBuffer::copy(context, src);
+ } else if (_type == DataType::AUDIO && src->type() == DataType::CONTROL) {
+ set_block(((AudioBuffer*)src)->data()[0], 0, nframes());
+ }
}
@@ -225,66 +177,42 @@ AudioBuffer::copy(Context& context, const Buffer* src)
* This function only adds the same range in one buffer to another.
*/
void
-AudioBuffer::accumulate(const AudioBuffer* const src, size_t start_sample, size_t end_sample)
-{
- assert(end_sample >= start_sample);
- assert(src);
- assert(src->type() == DataType::CONTROL || DataType::AUDIO);
-
- Sample* const buf = data();
- assert(buf);
-
- const Sample* const src_buf = src->data();
- assert(src_buf);
-
- const size_t to_copy = std::min(end_sample, _size - 1);
- for (size_t i = start_sample; i <= to_copy; ++i)
- buf[i] += src_buf[i];
-
-}
-
-
-/** Use another buffer's data instead of the local one.
- *
- * This buffer will essentially be identical to @a buf after this call.
- */
-bool
-AudioBuffer::join(Buffer* buf)
+AudioBuffer::mix(Context& context, const Buffer* const src)
{
- assert(buf != this);
- AudioBuffer* abuf = dynamic_cast<AudioBuffer*>(buf);
- if (!abuf)
- return false;
+ if (src->type() != DataType::CONTROL && src->type() != DataType::AUDIO)
+ return;
- assert(abuf->size() >= _size);
+ AudioBuffer* src_abuf = (AudioBuffer*)src;
- _joined_buf = abuf;
- _filled_size = abuf->filled_size();
+ Sample* const buf = data();
+ const Sample* const src_buf = src_abuf->data();
- assert(_filled_size <= _size);
-
- return true;
-}
+ const size_t frames = std::min(nframes(), src_abuf->nframes());
+ assert(frames != 0);
+ // Mix initial portions
+ SampleCount i = 0;
+ for (; i < frames; ++i)
+ buf[i] += src_buf[i];
-void
-AudioBuffer::unjoin()
-{
- _joined_buf = NULL;
- _data = _local_data;
+ // Extend/Mix the final sample of src if it is shorter
+ const Sample last = src_buf[i - 1];
+ while (i < frames)
+ buf[i++] = last;
}
void
AudioBuffer::prepare_read(Context& context)
{
+ assert(nframes() != 0);
switch (_state) {
case HALF_SET_CYCLE_1:
if (context.start() > _set_time)
_state = HALF_SET_CYCLE_2;
break;
case HALF_SET_CYCLE_2:
- set_block(_set_value, 0, _size - 1);
+ set_block(_set_value, 0, nframes() - 1);
_state = OK;
break;
default:
@@ -293,17 +221,4 @@ AudioBuffer::prepare_read(Context& context)
}
-/** Set the buffer (data) used.
- *
- * This is only to be used by Drivers (to provide zero-copy processing).
- */
-void
-AudioBuffer::set_data(Sample* buf)
-{
- assert(buf);
- assert(!_joined_buf);
- _data = buf;
-}
-
-
} // namespace Ingen
diff --git a/src/engine/AudioBuffer.hpp b/src/engine/AudioBuffer.hpp
index d072ddb3..7a8d119d 100644
--- a/src/engine/AudioBuffer.hpp
+++ b/src/engine/AudioBuffer.hpp
@@ -18,64 +18,74 @@
#ifndef AUDIOBUFFER_H
#define AUDIOBUFFER_H
+#include <iostream>
#include <cstddef>
#include <cassert>
#include <boost/utility.hpp>
#include "types.hpp"
-#include "Buffer.hpp"
+#include "ObjectBuffer.hpp"
+
+using namespace std;
namespace Ingen {
-class AudioBuffer : public Buffer
+class AudioBuffer : public ObjectBuffer
{
public:
- AudioBuffer(size_t capacity);
+ AudioBuffer(Shared::DataType type, size_t capacity);
void clear();
+
void set_value(Sample val, FrameTime cycle_start, FrameTime time);
void set_block(Sample val, size_t start_offset, size_t end_offset);
- void scale(Sample val, size_t start_sample, size_t end_sample);
- void copy(const Buffer* src, size_t start_sample, size_t end_sample);
+ void copy(const Sample* src, size_t start_sample, size_t end_sample);
void copy(Context& context, const Buffer* src);
- void accumulate(const AudioBuffer* src, size_t start_sample, size_t end_sample);
-
- bool join(Buffer* buf);
- void unjoin();
-
- /** For driver use only!! */
- void set_data(Sample* data);
-
- inline const void* raw_data() const { return _data; }
- inline void* raw_data() { return _data; }
-
- inline Sample* data() const { return _data; }
+ void mix(Context& context, const Buffer* src);
+
+ inline Sample* data() const {
+ switch (_port_type.symbol()) {
+ case Shared::DataType::CONTROL:
+ return (Sample*)object()->body;
+ case Shared::DataType::AUDIO:
+ return (Sample*)(object()->body + sizeof(LV2_Vector_Body));
+ default:
+ return NULL;
+ }
+ }
+
+ inline SampleCount nframes() const {
+ SampleCount ret = 0;
+ switch (_port_type.symbol()) {
+ case Shared::DataType::CONTROL:
+ ret = 1;
+ break;
+ case Shared::DataType::AUDIO:
+ ret = (_size - sizeof(LV2_Object) - sizeof(LV2_Vector_Body)) / sizeof(Sample);
+ break;
+ default:
+ ret = 0;
+ }
+ return ret;
+ }
inline Sample& value_at(size_t offset) const
- { assert(offset < _size); return data()[offset]; }
+ { assert(offset < nframes()); return data()[offset]; }
void prepare_read(Context& context);
void prepare_write(Context& context) {}
void resize(size_t size);
- void filled_size(size_t size) { _filled_size = size; }
- size_t filled_size() const { return _filled_size; }
- size_t size() const { return _size; }
-
private:
enum State { OK, HALF_SET_CYCLE_1, HALF_SET_CYCLE_2 };
- void alloc_local_data(size_t size);
- void allocate();
- void deallocate();
+ LV2_Vector_Body* vector() { return(LV2_Vector_Body*)object()->body; }
- Sample* _data; ///< Used data pointer (probably same as _local_data)
- Sample* _local_data; ///< Locally allocated buffer (possibly unused if joined or set_data used)
- size_t _filled_size; ///< Usable buffer size (for MIDI ports etc)
- State _state; ///< State of buffer for setting values next cycle
- Sample _set_value; ///< Value set by set_value (for completing the set next cycle)
- FrameTime _set_time; ///< Time _set_value was set (to reset next cycle)
+ Shared::DataType _port_type; ///< Type of port this buffer is for
+ State _state; ///< State of buffer for setting values next cycle
+ Sample _set_value; ///< Value set by set_value (for completing the set next cycle)
+ FrameTime _set_time; ///< Time _set_value was set (to reset next cycle)
};
diff --git a/src/engine/Buffer.cpp b/src/engine/Buffer.cpp
index 07498b36..b473c194 100644
--- a/src/engine/Buffer.cpp
+++ b/src/engine/Buffer.cpp
@@ -15,6 +15,7 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <algorithm>
#include "AudioBuffer.hpp"
#include "EventBuffer.hpp"
#include "ObjectBuffer.hpp"
@@ -23,17 +24,20 @@ namespace Ingen {
using namespace Shared;
+class Engine;
+
Buffer*
-Buffer::create(DataType type, size_t size)
+Buffer::create(Engine& engine, Shared::DataType type, size_t size)
{
if (type.is_control())
- return new AudioBuffer(1);
+ return new AudioBuffer(type, size);
else if (type.is_audio())
- return new AudioBuffer(size);
+ return new AudioBuffer(type, size);
else if (type.is_events())
return new EventBuffer(size);
else if (type.is_value())
- return new ObjectBuffer(size);
+ return new ObjectBuffer(std::max(size,
+ sizeof(LV2_Object) + sizeof(void*)));
else
throw;
}
diff --git a/src/engine/Buffer.hpp b/src/engine/Buffer.hpp
index adde37f2..f566f9b6 100644
--- a/src/engine/Buffer.hpp
+++ b/src/engine/Buffer.hpp
@@ -22,12 +22,14 @@
#include <cassert>
#include <boost/utility.hpp>
#include "raul/Deletable.hpp"
+#include "raul/SharedPtr.hpp"
#include "types.hpp"
#include "interface/DataType.hpp"
namespace Ingen {
class Context;
+class Engine;
class Buffer : public boost::noncopyable, public Raul::Deletable
{
@@ -35,42 +37,38 @@ public:
Buffer(Shared::DataType type, size_t size)
: _type(type)
, _size(size)
- , _joined_buf(NULL)
{}
- virtual ~Buffer() {}
-
- static Buffer* create(Shared::DataType type, size_t size);
-
/** Clear contents and reset state */
virtual void clear() = 0;
virtual void resize(size_t size) { _size = size; }
- virtual void* raw_data() = 0;
- virtual const void* raw_data() const = 0;
+ virtual void* port_data(Shared::DataType port_type) = 0;
+ virtual const void* port_data(Shared::DataType port_type) const = 0;
/** Rewind (ie reset read pointer), but leave contents unchanged */
virtual void rewind() const {}
virtual void copy(Context& context, const Buffer* src) = 0;
+ virtual void mix(Context& context, const Buffer* src) = 0;
virtual void prepare_read(Context& context) {}
virtual void prepare_write(Context& context) {}
- bool is_joined() const { return (_joined_buf != NULL); }
- Buffer* joined_buffer() const { return _joined_buf; }
-
- virtual bool join(Buffer* buf) = 0;
- virtual void unjoin() = 0;
-
Shared::DataType type() const { return _type; }
size_t size() const { return _size; }
protected:
Shared::DataType _type;
size_t _size;
- Buffer* _joined_buf;
+ bool _local;
+
+ friend class BufferFactory;
+ virtual ~Buffer() {}
+
+private:
+ Buffer* _next; ///< Intrusive linked list for BufferFactory
};
diff --git a/src/engine/BufferFactory.cpp b/src/engine/BufferFactory.cpp
new file mode 100644
index 00000000..63fd31ae
--- /dev/null
+++ b/src/engine/BufferFactory.cpp
@@ -0,0 +1,124 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2007-2009 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <algorithm>
+#include <iostream>
+#include "shared/LV2URIMap.hpp"
+#include "AudioBuffer.hpp"
+#include "EventBuffer.hpp"
+#include "ObjectBuffer.hpp"
+#include "BufferFactory.hpp"
+#include "Engine.hpp"
+#include "AudioDriver.hpp"
+#include "ThreadManager.hpp"
+
+namespace Ingen {
+
+using namespace Shared;
+
+BufferFactory::BufferFactory(Engine& engine, SharedPtr<Shared::LV2URIMap> map)
+ : _engine(engine)
+ , _map(map)
+{
+}
+
+struct BufferDeleter {
+ BufferDeleter(BufferFactory& bf) : _factory(bf) {}
+ void operator()(void* ptr) {
+ _factory.recycle((Buffer*)ptr);
+ }
+ BufferFactory& _factory;
+};
+
+
+SharedPtr<Buffer>
+BufferFactory::get(Shared::DataType type, size_t size)
+{
+ Raul::AtomicPtr<Buffer>& head_ptr = free_list(type);
+ Buffer* try_head;
+ Buffer* next;
+ do {
+ try_head = head_ptr.get();
+ if (!try_head)
+ break;
+ next = try_head->_next;
+ } while (!head_ptr.compare_and_exchange(try_head, next));
+
+ if (!try_head) {
+ if (ThreadManager::current_thread_id() != THREAD_PROCESS) {
+ return create(type, size);
+ } else {
+ cerr << "ERROR: Failed to obtain buffer" << endl;
+ return SharedPtr<Buffer>();
+ }
+ }
+
+ try_head->_next = NULL;
+ return SharedPtr<Buffer>(try_head, BufferDeleter(*this));
+}
+
+
+SharedPtr<Buffer>
+BufferFactory::create(Shared::DataType type, size_t size)
+{
+ assert(ThreadManager::current_thread_id() != THREAD_PROCESS);
+
+ Buffer* buffer = NULL;
+
+ if (type.is_control()) {
+ if (size == 0)
+ size = sizeof(LV2_Object) + sizeof(float);
+ AudioBuffer* ret = new AudioBuffer(type, size);
+ ret->object()->type = _map->object_class_vector;
+ ((LV2_Vector_Body*)ret->object()->body)->elem_type = _map->object_class_float32;
+ buffer = ret;
+ } else if (type.is_audio()) {
+ if (size == 0)
+ size = sizeof(LV2_Object) + sizeof(LV2_Vector_Body)
+ + _engine.audio_driver()->buffer_size() * sizeof(float);
+ AudioBuffer* ret = new AudioBuffer(type, size);
+ ret->object()->type = _map->object_class_float32;
+ buffer = ret;
+ } else if (type.is_events()) {
+ if (size == 0)
+ size = _engine.audio_driver()->buffer_size() * 4; // FIXME
+ buffer = new EventBuffer(size);
+ } else if (type.is_value()) {
+ if (size == 0)
+ size = 32; // FIXME
+ buffer = new ObjectBuffer(std::max(size, sizeof(LV2_Object) + sizeof(void*)));
+ } else {
+ cout << "ERROR: Failed to create buffer of unknown type" << endl;
+ return SharedPtr<Buffer>();
+ }
+
+ return SharedPtr<Buffer>(buffer, BufferDeleter(*this));
+}
+
+void
+BufferFactory::recycle(Buffer* buf)
+{
+ Raul::AtomicPtr<Buffer>& head_ptr = free_list(buf->type());
+ Buffer* try_head;
+ do {
+ try_head = head_ptr.get();
+ buf->_next = try_head;
+ } while (!head_ptr.compare_and_exchange(try_head, buf));
+}
+
+
+} // namespace Ingen
diff --git a/src/engine/BufferFactory.hpp b/src/engine/BufferFactory.hpp
new file mode 100644
index 00000000..dcc1e03f
--- /dev/null
+++ b/src/engine/BufferFactory.hpp
@@ -0,0 +1,69 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2009 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef BUFFER_FACTORY_H
+#define BUFFER_FACTORY_H
+
+#include <map>
+#include "interface/DataType.hpp"
+#include "glibmm/thread.h"
+#include "raul/RingBuffer.hpp"
+#include "raul/AtomicPtr.hpp"
+
+namespace Ingen {
+
+using namespace Shared;
+
+class Engine;
+
+namespace Shared { class LV2URIMap; }
+
+class BufferFactory {
+public:
+ BufferFactory(Engine& engine, SharedPtr<Shared::LV2URIMap> map);
+
+ SharedPtr<Buffer> get(Shared::DataType type, size_t size=0);
+
+private:
+ friend class BufferDeleter;
+ void recycle(Buffer* buf);
+
+ SharedPtr<Buffer> create(Shared::DataType type, size_t size=0);
+
+ inline Raul::AtomicPtr<Buffer>& free_list(Shared::DataType type) {
+ switch (type.symbol()) {
+ case DataType::AUDIO: return _free_audio;
+ case DataType::CONTROL: return _free_control;
+ case DataType::EVENTS: return _free_event;
+ case DataType::VALUE: return _free_object;
+ default: throw;
+ }
+ }
+
+ Raul::AtomicPtr<Buffer> _free_audio;
+ Raul::AtomicPtr<Buffer> _free_control;
+ Raul::AtomicPtr<Buffer> _free_event;
+ Raul::AtomicPtr<Buffer> _free_object;
+
+ Glib::Mutex _mutex;
+ Engine& _engine;
+ SharedPtr<Shared::LV2URIMap> _map;
+};
+
+} // namespace Ingen
+
+#endif // BUFFER_FACTORY_H
diff --git a/src/engine/ConnectionImpl.cpp b/src/engine/ConnectionImpl.cpp
index 6c7a63f0..715b1984 100644
--- a/src/engine/ConnectionImpl.cpp
+++ b/src/engine/ConnectionImpl.cpp
@@ -22,6 +22,8 @@
#include "PortImpl.hpp"
#include "AudioBuffer.hpp"
#include "ProcessContext.hpp"
+#include "InputPort.hpp"
+#include "BufferFactory.hpp"
namespace Ingen {
@@ -32,12 +34,10 @@ using namespace Shared;
* This handles both polyphonic and monophonic nodes, transparently to the
* user (InputPort).
*/
-ConnectionImpl::ConnectionImpl(PortImpl* src_port, PortImpl* dst_port)
- : _mode(DIRECT)
+ConnectionImpl::ConnectionImpl(BufferFactory& bufs, PortImpl* src_port, PortImpl* dst_port)
+ : _bufs(bufs)
, _src_port(src_port)
, _dst_port(dst_port)
- , _local_buffer(NULL)
- , _buffer_size(dst_port->buffer_size())
, _pending_disconnection(false)
{
assert(src_port);
@@ -51,83 +51,34 @@ ConnectionImpl::ConnectionImpl(PortImpl* src_port, PortImpl* dst_port)
/*assert((src_port->parent_node()->poly() == dst_port->parent_node()->poly())
|| (src_port->parent_node()->poly() == 1 || dst_port->parent_node()->poly() == 1));*/
- set_mode();
- if (need_buffer())
- _local_buffer = Buffer::create(dst_port->type(), _buffer_size);
-
- /* FIXME: 1->1 connections with a destination with fixed buffers copies unecessarily */
- //cerr << src_port->path() << " -> " << dst_port->path() << " must mix: " << _must_mix << endl;
-}
-
-
-ConnectionImpl::~ConnectionImpl()
-{
- delete _local_buffer;
-}
-
-
-void
-ConnectionImpl::set_mode()
-{
if (must_mix())
- _mode = MIX;
- else if (must_copy())
- _mode = COPY;
- else if (must_extend())
- _mode = EXTEND;
-
- if (_mode == MIX && type() == DataType::EVENTS)
- _mode = COPY;
-
- if (type() == DataType::VALUE)
- _mode = DIRECT;
+ _local_buffer = bufs.get(dst_port->type(), dst_port->buffer_size());
}
void
-ConnectionImpl::set_buffer_size(size_t size)
-{
- if (_mode == MIX || _mode == EXTEND) {
- assert(_local_buffer);
- delete _local_buffer;
-
- _local_buffer = Buffer::create(_dst_port->type(), _dst_port->buffer(0)->size());
- }
-
- _buffer_size = size;
-}
-
-
-bool
-ConnectionImpl::must_copy() const
-{
- return (_dst_port->fixed_buffers() && (_src_port->poly() != _dst_port->poly()));
-}
-
-
-bool
-ConnectionImpl::must_mix() const
+ConnectionImpl::dump() const
{
- return ( (_src_port->polyphonic() && !_dst_port->polyphonic())
- || (_src_port->parent()->polyphonic() && !_dst_port->parent()->polyphonic())
- || (_dst_port->fixed_buffers()) );
+ cerr << _src_port->path() << " -> " << _dst_port->path()
+ << (must_mix() ? " MIX" : " DIRECT") << endl;
}
-bool
-ConnectionImpl::must_extend() const
+void
+ConnectionImpl::set_buffer_size(BufferFactory& bufs, size_t size)
{
- return (_src_port->buffer_size() != _dst_port->buffer_size());
+ if (must_mix())
+ _local_buffer = bufs.get(_dst_port->type(), _dst_port->buffer(0)->size());
}
void
-ConnectionImpl::prepare_poly(uint32_t poly)
+ConnectionImpl::prepare_poly(BufferFactory& bufs, uint32_t poly)
{
- _src_port->prepare_poly(poly);
+ _src_port->prepare_poly(bufs, poly);
- if (need_buffer() && !_local_buffer)
- _local_buffer = Buffer::create(_dst_port->type(), _dst_port->buffer(0)->size());
+ if (must_mix())
+ _local_buffer = bufs.get(_dst_port->type(), _dst_port->buffer(0)->size());
}
@@ -135,101 +86,25 @@ void
ConnectionImpl::apply_poly(Raul::Maid& maid, uint32_t poly)
{
_src_port->apply_poly(maid, poly);
- set_mode();
-
- /*cerr << "CONNECTION APPLY: " << src_port()->path() << " * " << src_port()->poly()
- << " -> " << dst_port()->path() << " * " << dst_port()->poly()
- << "\t\tmust mix: " << must_mix() << ", extend: " << must_extend()
- << ", poly " << poly << endl;*/
// Recycle buffer if it's no longer needed
- if (_local_buffer && !need_buffer()) {
- maid.push(_local_buffer);
- _local_buffer = NULL;
- }
+ if (!must_mix() && _local_buffer)
+ _local_buffer.reset();
}
void
ConnectionImpl::process(Context& context)
{
- /* Thought: A poly output port can be connected to multiple mono input
- * ports, which means this mix down would have to happen many times.
- * Adding a method to OutputPort that mixes down all it's outputs into
- * a buffer (if it hasn't been done already this cycle) and returns that
- * would avoid having to mix multiple times. Probably not a very common
- * case, but it would be faster anyway. */
-
- std::cerr << src_port()->path() << " * " << src_port()->poly()
- << " -> " << dst_port()->path() << " * " << dst_port()->poly()
- << "\t\tmode: " << (int)_mode << std::endl;
-
- if (_mode == COPY) {
- assert(src_port()->poly() == dst_port()->poly());
- for (uint32_t i = 0; i < src_port()->poly(); ++i)
- dst_port()->buffer(i)->copy(context, src_port()->buffer(i));
-
- } else if (_mode == MIX) {
- assert(type() == DataType::AUDIO || type() == DataType::CONTROL);
-
- const AudioBuffer* const src_buffer = (AudioBuffer*)src_port()->buffer(0);
- AudioBuffer* mix_buf = (AudioBuffer*)_local_buffer;
-
- assert(mix_buf);
-
- const size_t copy_size = std::min(src_buffer->size(), mix_buf->size());
-
- // Copy src buffer to start of mix buffer
- mix_buf->copy(context, src_buffer);
-
- // Write last value of src buffer to remainder of dst buffer, if necessary
- if (copy_size < mix_buf->size())
- mix_buf->set_block(src_buffer->value_at(copy_size-1), copy_size, mix_buf->size()-1);
-
- // Accumulate the source's voices into local buffer starting at the second
- // voice (buffer is already set to first voice above)
- for (uint32_t j=1; j < src_port()->poly(); ++j) {
- mix_buf->accumulate((AudioBuffer*)src_port()->buffer(j), 0, copy_size-1);
- }
-
- // Find the summed value and write it to the remainder of dst buffer
- if (copy_size < mix_buf->size()) {
- float src_value = src_buffer->value_at(copy_size-1);
- for (uint32_t j=1; j < src_port()->poly(); ++j)
- src_value += ((AudioBuffer*)src_port()->buffer(j))->value_at(copy_size-1);
-
- mix_buf->set_block(src_value, copy_size, mix_buf->size()-1);
- }
-
- // Scale the buffer down.
- if (src_port()->poly() > 1)
- mix_buf->scale(1.0f/(float)src_port()->poly(), 0, mix_buf->size()-1);
-
- } else if (_mode == EXTEND) {
- assert(type() == DataType::AUDIO || type() == DataType::CONTROL);
- assert(src_port()->poly() == 1 || src_port()->poly() == dst_port()->poly());
-
- const uint32_t poly = dst_port()->poly();
- const uint32_t copy_size = std::min(src_port()->buffer(0)->size(),
- dst_port()->buffer(0)->size());
-
- for (uint32_t i = 0; i < poly; ++i) {
- uint32_t src_voice = std::min(i, src_port()->poly() - 1);
- AudioBuffer* src_buf = (AudioBuffer*)src_port()->buffer(src_voice);
- AudioBuffer* dst_buf = (AudioBuffer*)dst_port()->buffer(i);
-
- // Copy src to start of dst
- dst_buf->copy(src_buf, 0, copy_size-1);
-
- // Write last value of src buffer to remainder of dst buffer, if necessary
- if (copy_size < dst_buf->size())
- dst_buf->set_block(src_buf->value_at(copy_size - 1), copy_size, dst_buf->size() - 1);
- }
-
- } else if (_mode == DIRECT) {
- for (uint32_t j=0; j < src_port()->poly(); ++j)
- src_port()->buffer(j)->prepare_read(context);
- }
+ if (!must_mix())
+ return;
+
+ // Copy the first voice
+ _local_buffer->copy(context, src_port()->buffer(0).get());
+
+ // Mix in the rest
+ for (uint32_t v = 0; v < src_port()->poly(); ++v)
+ _local_buffer->mix(context, src_port()->buffer(v).get());
}
diff --git a/src/engine/ConnectionImpl.hpp b/src/engine/ConnectionImpl.hpp
index a4ad281b..c9101304 100644
--- a/src/engine/ConnectionImpl.hpp
+++ b/src/engine/ConnectionImpl.hpp
@@ -18,17 +18,22 @@
#ifndef CONNECTIONIMPL_H
#define CONNECTIONIMPL_H
+#include <iostream>
#include <cstdlib>
#include <boost/utility.hpp>
#include "raul/Deletable.hpp"
#include "interface/DataType.hpp"
#include "interface/Connection.hpp"
#include "PortImpl.hpp"
+#include "PortImpl.hpp"
+
+using namespace std;
namespace Ingen {
class PortImpl;
class Buffer;
+class BufferFactory;
/** Represents a single inbound connection for an InputPort.
@@ -44,8 +49,7 @@ class Buffer;
class ConnectionImpl : public Raul::Deletable, public Shared::Connection
{
public:
- ConnectionImpl(PortImpl* src_port, PortImpl* dst_port);
- virtual ~ConnectionImpl();
+ ConnectionImpl(BufferFactory& bufs, PortImpl* src_port, PortImpl* dst_port);
PortImpl* src_port() const { return _src_port; }
PortImpl* dst_port() const { return _dst_port; }
@@ -61,49 +65,35 @@ public:
/** Get the buffer for a particular voice.
* A Connection is smart - it knows the destination port requesting the
- * buffer, and will return accordingly (ie the same buffer for every voice
- * in a mono->poly connection).
+ * buffer, and will return accordingly (e.g. the same buffer for every
+ * voice in a mono->poly connection).
*/
- inline Buffer* buffer(uint32_t voice) const;
-
- inline size_t buffer_size() const { return _buffer_size; }
+ inline SharedPtr<Buffer> buffer(uint32_t voice) const {
+ if (must_mix()) {
+ return _local_buffer;
+ } else if ( ! _src_port->polyphonic()) {
+ return _src_port->buffer(0);
+ } else {
+ return _src_port->buffer(voice);
+ }
+ }
- void set_buffer_size(size_t size);
- void prepare_poly(uint32_t poly);
+ void set_buffer_size(BufferFactory& bufs, size_t size);
+ void prepare_poly(BufferFactory& bufs, uint32_t poly);
void apply_poly(Raul::Maid& maid, uint32_t poly);
- inline bool need_buffer() const { return must_mix(); }
- inline bool can_direct() const { return _mode == DIRECT; }
-
- Shared::DataType type() const { return _src_port->type(); }
+ /** Returns true if this connection must mix down voices into a local buffer */
+ inline bool must_mix() const { return _src_port->poly() > _dst_port->poly(); }
protected:
- enum { DIRECT, MIX, COPY, EXTEND } _mode;
- void set_mode();
-
- bool must_copy() const;
- bool must_mix() const;
- bool must_extend() const;
-
- PortImpl* const _src_port;
- PortImpl* const _dst_port;
- Buffer* _local_buffer;
- size_t _buffer_size;
- bool _pending_disconnection;
-};
-
+ void dump() const;
-inline Buffer*
-ConnectionImpl::buffer(uint32_t voice) const
-{
- if (_mode == MIX) {
- return _local_buffer;
- } else if ( ! _src_port->polyphonic()) {
- return _src_port->buffer(0);
- } else {
- return _src_port->buffer(voice);
- }
-}
+ BufferFactory& _bufs;
+ PortImpl* const _src_port;
+ PortImpl* const _dst_port;
+ SharedPtr<Buffer> _local_buffer;
+ bool _pending_disconnection;
+};
} // namespace Ingen
diff --git a/src/engine/DuplexPort.cpp b/src/engine/DuplexPort.cpp
index 78a2bb94..6cf1d908 100644
--- a/src/engine/DuplexPort.cpp
+++ b/src/engine/DuplexPort.cpp
@@ -34,6 +34,7 @@ using namespace Shared;
DuplexPort::DuplexPort(
+ BufferFactory& bufs,
NodeImpl* parent,
const string& name,
uint32_t index,
@@ -42,13 +43,12 @@ DuplexPort::DuplexPort(
const Raul::Atom& value,
size_t buffer_size,
bool is_output)
- : PortImpl(parent, name, index, poly, type, value, buffer_size)
- , InputPort(parent, name, index, poly, type, value, buffer_size)
- , OutputPort(parent, name, index, poly, type, value, buffer_size)
+ : PortImpl(bufs, parent, name, index, poly, type, value, buffer_size)
+ , InputPort(bufs, parent, name, index, poly, type, value, buffer_size)
+ , OutputPort(bufs, parent, name, index, poly, type, value, buffer_size)
, _is_output(is_output)
{
assert(PortImpl::_parent == parent);
- _fixed_buffers = true;
}
@@ -56,30 +56,17 @@ DuplexPort::DuplexPort(
void
DuplexPort::pre_process(Context& context)
{
- /*cerr << endl << "{ duplex pre" << endl;
- cerr << path() << " duplex pre: fixed buffers: " << fixed_buffers() << endl;
- cerr << path() << " duplex pre: buffer: " << buffer(0) << endl;
- cerr << path() << " duplex pre: is_output: " << _is_output << " { " << endl;*/
-
- // If we're a patch output, prepare buffers for write (so plugins can deliver to them)
+ // If we're a patch output, we're an input from the internal perspective.
+ // Prepare buffers for write (so plugins can deliver to them)
if (_is_output) {
- for (uint32_t i=0; i < _poly; ++i)
- if (!_buffers->at(i)->is_joined())
- _buffers->at(i)->prepare_write(context);
+ for (uint32_t v = 0; v < _poly; ++v)
+ _buffers->at(v)->prepare_write(context);
- // Otherwise, we're a patch input, do whatever a normal node's input port does
- // (mix down inputs from an outside "patch is a node" perspective)
+ // If we're a patch input, were an output from the internal perspective.
+ // Do whatever a normal node's input port does to prepare input for reading.
} else {
InputPort::pre_process(context);
}
-
- /*if (type() == DataType::EVENT)
- for (uint32_t i=0; i < _poly; ++i)
- cerr << path() << " (" << buffer(i) << ") # events: "
- << ((EventBuffer*)buffer(i))->event_count()
- << ", joined: " << _buffers->at(i)->is_joined()
- << ", is_output: " << _is_output << endl;*/
- //cerr << "} duplex pre " << path() << endl;
}
@@ -87,30 +74,14 @@ DuplexPort::pre_process(Context& context)
void
DuplexPort::post_process(Context& context)
{
- /*cerr << endl << "{ duplex post" << endl;
- cerr << path() << " duplex post: fixed buffers: " << fixed_buffers() << endl;
- cerr << path() << " duplex post: buffer: " << buffer(0) << endl;
- cerr << path() << " duplex post: is_output: " << _is_output << " { " << endl;
-
- if (type() == DataType::EVENT)
- for (uint32_t i=0; i < _poly; ++i)
- cerr << path() << " (" << buffer(i) << ") # events: "
- << ((EventBuffer*)buffer(i))->event_count()
- << ", joined: " << _buffers->at(i)->is_joined() << endl;*/
-
- // If we're a patch output
-
-
+ // If we're a patch output, we're an input from the internal perspective.
+ // Mix down input delivered by plugins so output (external perspective) is ready.
if (_is_output) {
- // Then we've been delivered to as an input (internal perspective)
- // Mix down this input so patch output ports (external perspective) are ready
InputPort::pre_process(context);
if (_broadcast)
broadcast_value(context, false);
}
-
- //cerr << "} duplex post " << path() << endl;
}
diff --git a/src/engine/DuplexPort.hpp b/src/engine/DuplexPort.hpp
index 882bab73..621d0c62 100644
--- a/src/engine/DuplexPort.hpp
+++ b/src/engine/DuplexPort.hpp
@@ -39,7 +39,8 @@ class NodeImpl;
class DuplexPort : public InputPort, public OutputPort
{
public:
- DuplexPort(NodeImpl* parent,
+ DuplexPort(BufferFactory& bufs,
+ NodeImpl* parent,
const std::string& name,
uint32_t index,
uint32_t poly,
diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp
index 619ead5e..1c17bf74 100644
--- a/src/engine/Engine.cpp
+++ b/src/engine/Engine.cpp
@@ -25,7 +25,12 @@
#include "common/interface/EventType.hpp"
#include "events/CreatePatch.hpp"
#include "module/World.hpp"
+#include "shared/LV2Features.hpp"
+#include "shared/LV2URIMap.hpp"
+#include "shared/Store.hpp"
+#include "uri-map.lv2/uri-map.h"
#include "AudioDriver.hpp"
+#include "BufferFactory.hpp"
#include "ClientBroadcaster.hpp"
#include "Engine.hpp"
#include "EngineStore.hpp"
@@ -41,7 +46,6 @@
#include "ProcessSlave.hpp"
#include "QueuedEventSource.hpp"
#include "ThreadManager.hpp"
-#include "shared/Store.hpp"
#include "tuning.hpp"
using namespace std;
@@ -60,6 +64,8 @@ Engine::Engine(Ingen::Shared::World* world)
, _broadcaster(new ClientBroadcaster())
, _node_factory(new NodeFactory(world))
, _message_context(new MessageContext(*this))
+ , _buffer_factory(new BufferFactory(*this, PtrCast<LV2URIMap>(
+ world->lv2_features->feature(LV2_URI_MAP_URI))))
, _quit_flag(false)
, _activated(false)
{
diff --git a/src/engine/Engine.hpp b/src/engine/Engine.hpp
index 16635561..93162ff4 100644
--- a/src/engine/Engine.hpp
+++ b/src/engine/Engine.hpp
@@ -47,6 +47,7 @@ class Driver;
class ProcessSlave;
class ProcessContext;
class MessageContext;
+class BufferFactory;
/** The main class for the Engine.
@@ -88,6 +89,7 @@ public:
ClientBroadcaster* broadcaster() const { return _broadcaster; }
NodeFactory* node_factory() const { return _node_factory; }
MessageContext* message_context() const { return _message_context; }
+ BufferFactory* buffer_factory() const { return _buffer_factory; }
SharedPtr<EngineStore> engine_store() const;
@@ -120,6 +122,7 @@ private:
ClientBroadcaster* _broadcaster;
NodeFactory* _node_factory;
MessageContext* _message_context;
+ BufferFactory* _buffer_factory;
bool _quit_flag;
bool _activated;
diff --git a/src/engine/EventBuffer.cpp b/src/engine/EventBuffer.cpp
index d92ecae1..380fe3b6 100644
--- a/src/engine/EventBuffer.cpp
+++ b/src/engine/EventBuffer.cpp
@@ -35,39 +35,11 @@ using namespace Shared;
*/
EventBuffer::EventBuffer(size_t capacity)
: Buffer(DataType(DataType::EVENTS), capacity)
- , _local_buf(new LV2EventBuffer(capacity))
+ , _buf(new LV2EventBuffer(capacity))
{
- _buf = _local_buf;
clear();
- //cerr << "Creating MIDI Buffer " << _buf << ", capacity = " << _buf->capacity << endl;
-}
-
-
-/** Use another buffer's data instead of the local one.
- *
- * This buffer will essentially be identical to @a buf after this call.
- */
-bool
-EventBuffer::join(Buffer* buf)
-{
- assert(buf != this);
- EventBuffer* ebuf = dynamic_cast<EventBuffer*>(buf);
- if (!ebuf)
- return false;
-
- _buf = ebuf->_local_buf;
- _joined_buf = ebuf;
-
- return true;
-}
-
-
-void
-EventBuffer::unjoin()
-{
- _joined_buf = NULL;
- _buf = _local_buf;
+ //cerr << "Creating Event Buffer " << _buf << ", capacity = " << _buf->capacity << endl;
}
@@ -101,6 +73,12 @@ EventBuffer::copy(Context& context, const Buffer* src_buf)
}
+void
+EventBuffer::mix(Context& context, const Buffer* src)
+{
+}
+
+
/** Clear, and merge \a a and \a b into this buffer.
*
* FIXME: This is slow.
diff --git a/src/engine/EventBuffer.hpp b/src/engine/EventBuffer.hpp
index cafa71bd..b5287f63 100644
--- a/src/engine/EventBuffer.hpp
+++ b/src/engine/EventBuffer.hpp
@@ -31,13 +31,10 @@ class EventBuffer : public Buffer {
public:
EventBuffer(size_t capacity);
- bool join(Buffer* buf);
- void unjoin();
-
void clear() { _buf->reset(); }
- void* raw_data() { return _buf; }
- const void* raw_data() const { return _buf; }
+ void* port_data(Shared::DataType port_type) { return _buf; }
+ const void* port_data(Shared::DataType port_type) const { return _buf; }
void rewind() const { _buf->rewind(); }
@@ -45,6 +42,7 @@ public:
void prepare_write(Context& context);
void copy(Context& context, const Buffer* src);
+ void mix(Context& contect, const Buffer* src);
bool merge(const EventBuffer& a, const EventBuffer& b);
bool increment() const { return _buf->increment(); }
@@ -75,8 +73,7 @@ public:
}
private:
- LV2EventBuffer* _buf; ///< Contents (maybe belong to _joined_buf)
- LV2EventBuffer* _local_buf; ///< Local contents
+ LV2EventBuffer* _buf; ///< Contents
};
diff --git a/src/engine/InputPort.cpp b/src/engine/InputPort.cpp
index 5d3a0627..4182e862 100644
--- a/src/engine/InputPort.cpp
+++ b/src/engine/InputPort.cpp
@@ -27,6 +27,7 @@
#include "OutputPort.hpp"
#include "ProcessContext.hpp"
#include "ThreadManager.hpp"
+#include "BufferFactory.hpp"
#include "util.hpp"
using namespace std;
@@ -36,14 +37,15 @@ namespace Ingen {
namespace Shared { class Patch; }
using namespace Shared;
-InputPort::InputPort(NodeImpl* parent,
+InputPort::InputPort(BufferFactory& bufs,
+ NodeImpl* parent,
const string& name,
uint32_t index,
uint32_t poly,
DataType type,
const Raul::Atom& value,
size_t buffer_size)
- : PortImpl(parent, name, index, poly, type, value, buffer_size)
+ : PortImpl(bufs, parent, name, index, poly, type, value, buffer_size)
{
if (!dynamic_cast<Patch*>(parent))
add_property("rdf:type", Raul::Atom(Raul::Atom::URI, "lv2:InputPort"));
@@ -53,28 +55,32 @@ InputPort::InputPort(NodeImpl* parent,
bool
InputPort::can_direct() const
{
- return _connections.size() == 1 && _connections.front()->can_direct();
+ return _connections.size() == 1
+ && _connections.front()->src_port()->poly() == poly()
+ && (_connections.front()->src_port()->type() == type()
+ || (_connections.front()->src_port()->type() == DataType::AUDIO
+ && type() == DataType::CONTROL));
}
void
-InputPort::set_buffer_size(size_t size)
+InputPort::set_buffer_size(BufferFactory& bufs, size_t size)
{
- PortImpl::set_buffer_size(size);
+ PortImpl::set_buffer_size(bufs, size);
assert(_buffer_size = size);
for (Connections::iterator c = _connections.begin(); c != _connections.end(); ++c)
- ((ConnectionImpl*)c->get())->set_buffer_size(size);
+ ((ConnectionImpl*)c->get())->set_buffer_size(bufs, size);
}
bool
-InputPort::prepare_poly(uint32_t poly)
+InputPort::prepare_poly(BufferFactory& bufs, uint32_t poly)
{
- PortImpl::prepare_poly(poly);
+ PortImpl::prepare_poly(bufs, poly);
for (Connections::iterator c = _connections.begin(); c != _connections.end(); ++c)
- ((ConnectionImpl*)c->get())->prepare_poly(poly);
+ ((ConnectionImpl*)c->get())->prepare_poly(bufs, poly);
return true;
}
@@ -92,47 +98,51 @@ InputPort::apply_poly(Raul::Maid& maid, uint32_t poly)
PortImpl::apply_poly(maid, poly);
assert(this->poly() == poly);
- if (can_direct()) {
+ if (_connections.size() == 1) {
ConnectionImpl* c = _connections.begin()->get();
- for (uint32_t i=_poly; i < poly; ++i)
- _buffers->at(i)->join(c->buffer(i));
+ for (uint32_t v = _poly; v < poly; ++v)
+ _buffers->at(v) = c->buffer(v);
}
- for (uint32_t i=0; i < _poly; ++i)
+ for (uint32_t i = 0; i < _poly; ++i)
PortImpl::parent_node()->set_port_buffer(i, _index, buffer(i));
return true;
}
+/** Connect buffers to the appropriate locations based on the current connections */
+void
+InputPort::connect_buffers()
+{
+ // Single connection now, use it directly
+ if (_connections.size() == 1) {
+ for (uint32_t v = 0; v < _poly; ++v)
+ _buffers->at(v) = _connections.front()->buffer(v);
+
+ // Use local buffers
+ } else {
+ for (uint32_t v = 0; v < _poly; ++v)
+ _buffers->at(v) = _bufs.get(type()); // Use local buffer
+ }
+
+ // Connect node to buffers
+ PortImpl::connect_buffers();
+}
+
+
/** Add a connection. Realtime safe.
*
* The buffer of this port will be set directly to the connection's buffer
- * if there is only one connection, since no mixing needs to take place.
+ * if there is only one connection, since no copying/mixing needs to take place.
*/
void
InputPort::add_connection(Connections::Node* const c)
{
assert(ThreadManager::current_thread_id() == THREAD_PROCESS);
- const bool could_direct = can_direct();
-
_connections.push_back(c);
-
- if (!_fixed_buffers) {
- if (can_direct()) {
- // Use buffer directly to avoid copying
- for (uint32_t i=0; i < _poly; ++i) {
- _buffers->at(i)->join(c->elem()->buffer(i));
- }
- } else if (could_direct) {
- // Used to directly use single connection's buffer(s),
- // but now there's two so use the local ones again and mix down
- for (uint32_t i=0; i < _poly; ++i) {
- _buffers->at(i)->unjoin();
- }
- }
- }
+ connect_buffers();
// Automatically broadcast connected control inputs
if (_type == DataType::CONTROL)
@@ -146,38 +156,23 @@ InputPort::remove_connection(const OutputPort* src_port)
{
assert(ThreadManager::current_thread_id() == THREAD_PROCESS);
- bool found = false;
Connections::Node* connection = NULL;
- for (Connections::iterator i = _connections.begin(); i != _connections.end(); ++i) {
- if ((*i)->src_port() == src_port) {
+ for (Connections::iterator i = _connections.begin(); i != _connections.end(); ++i)
+ if ((*i)->src_port() == src_port)
connection = _connections.erase(i);
- found = true;
- }
- }
- if ( ! found) {
- cerr << "WARNING: [InputPort::remove_connection] Connection not found !" << endl;
- exit(EXIT_FAILURE);
- } else {
- if (_connections.size() == 0) {
- for (uint32_t i=0; i < _poly; ++i) {
- // Use a local buffer
- if (!_fixed_buffers)
- _buffers->at(i)->unjoin();
- _buffers->at(i)->clear(); // Write silence
- }
- } else if (_connections.size() == 1 && !_fixed_buffers && can_direct()) {
- // Share a buffer
- for (uint32_t i=0; i < _poly; ++i) {
- _buffers->at(i)->join(_connections.front()->buffer(i));
- }
- }
+ if ( ! connection) {
+ cerr << "ERROR: [InputPort::remove_connection] Connection not found!" << endl;
+ return NULL;
}
- if (!_fixed_buffers)
- PortImpl::connect_buffers();
+ connect_buffers();
- // Turn off broadcasting if we're not connected any more (FIXME: not quite right..)
+ if (_connections.size() == 0)
+ for (uint32_t v = 0; v < _poly; ++v)
+ buffer(v)->clear();
+
+ // Turn off broadcasting if we're no longer connected
if (_type == DataType::CONTROL && _connections.size() == 0)
_broadcast = false;
@@ -190,74 +185,31 @@ InputPort::remove_connection(const OutputPort* src_port)
void
InputPort::pre_process(Context& context)
{
- // If value has been set (e.g. events pushed) by the user,
- // don't do anything this cycle to avoid smashing the value
+ // If value has been set (e.g. events pushed) by the user, don't smash it
if (_set_by_user)
return;
- // No connections, just prepare buffers for reading by our node
- if (_connections.size() == 0) {
- for (uint32_t i=0; i < _poly; ++i)
- buffer(i)->prepare_read(context);
- return;
- }
+ //connect_buffers();
+ // Process connections (mix down polyphony, if necessary)
for (Connections::iterator c = _connections.begin(); c != _connections.end(); ++c)
(*c)->process(context);
- if (!_fixed_buffers) {
- // Single (matching) connection, use buffer(s) directly (zero copy)
- if (can_direct()) {
- for (uint32_t i=0; i < _poly; ++i) {
- _buffers->at(i)->join(_connections.front()->buffer(i));
- _buffers->at(i)->prepare_read(context);
- }
- connect_buffers();
- return;
- }
-
- connect_buffers();
- }
-
- /*cerr << path() << " poly = " << _poly << ", fixed buffers: " << _fixed_buffers
- << ", joined: " << _buffers->at(0)->is_joined()
- << " to " << _buffers->at(0)->joined_buffer() << endl;*/
-
- /*if (type() == DataType::EVENT)
- for (uint32_t i=0; i < _poly; ++i)
- if (((EventBuffer*)buffer(i))->event_count() > 0)
- cerr << path() << " (" << buffer(i) << ") # events: "
- << ((EventBuffer*)buffer(i))->event_count()
- << ", joined: " << _buffers->at(i)->is_joined() << endl;*/
-
- // Mix down all incoming connection to buffers
-
- if (_type == DataType::CONTROL || _type == DataType::AUDIO) {
- for (uint32_t voice=0; voice < _poly; ++voice) {
+ // Multiple connections, mix them all into our local buffers
+ if (_connections.size() > 1) {
+ for (uint32_t v = 0; v < _poly; ++v) {
// Copy first connection
- buffer(voice)->copy(context, _connections.front()->buffer(voice));
-
- // Accumulate the rest
- if (_connections.size() > 1) {
- Connections::iterator c = _connections.begin();
- for (++c; c != _connections.end(); ++c)
- ((AudioBuffer*)buffer(voice))->accumulate(
- ((AudioBuffer*)(*c)->buffer(voice)), 0, _buffer_size-1);
- }
- }
- } else {
- assert(_poly == 1);
+ buffer(v)->copy(context, _connections.front()->buffer(v).get());
- // FIXME
- if (_connections.size() > 1)
- cerr << "WARNING: MIDI mixing not implemented, only first connection used." << endl;
-
- // Copy first connection
- buffer(0)->copy(context, _connections.front()->buffer(0));
+ // Mix in the rest
+ Connections::iterator c = _connections.begin();
+ for (++c; c != _connections.end(); ++c)
+ buffer(v)->mix(context, (*c)->buffer(v).get());
+ }
}
- for (uint32_t i=0; i < _poly; ++i)
- buffer(i)->prepare_read(context);
+ for (uint32_t v = 0; v < _poly; ++v)
+ buffer(v)->prepare_read(context);
if (_broadcast)
broadcast_value(context, false);
@@ -269,17 +221,10 @@ InputPort::post_process(Context& context)
{
// Prepare buffers for next cycle
if (!can_direct())
- for (uint32_t i=0; i < _poly; ++i)
- buffer(i)->prepare_write(context);
+ for (uint32_t v = 0; v < _poly; ++v)
+ buffer(v)->prepare_write(context);
_set_by_user = false;
-
- /*if (_broadcast && (_type == DataType::CONTROL)) {
- const Sample value = ((AudioBuffer*)(*_buffers)[0])->value_at(0);
-
- cerr << path() << " input post: buffer: " << buffer(0) << " value = "
- << value << " (last " << _last_broadcasted_value << ")" <<endl;
- }*/
}
diff --git a/src/engine/InputPort.hpp b/src/engine/InputPort.hpp
index 81702b34..971a8747 100644
--- a/src/engine/InputPort.hpp
+++ b/src/engine/InputPort.hpp
@@ -46,7 +46,8 @@ class NodeImpl;
class InputPort : virtual public PortImpl
{
public:
- InputPort(NodeImpl* parent,
+ InputPort(BufferFactory& bufs,
+ NodeImpl* parent,
const std::string& name,
uint32_t index,
uint32_t poly,
@@ -61,20 +62,20 @@ public:
void add_connection(Connections::Node* c);
Connections::Node* remove_connection(const OutputPort* src_port);
- bool prepare_poly(uint32_t poly);
+ void set_buffer_size(BufferFactory& bufs, size_t size);
+ bool prepare_poly(BufferFactory& bufs, uint32_t poly);
bool apply_poly(Raul::Maid& maid, uint32_t poly);
void pre_process(Context& context);
void post_process(Context& context);
- bool is_connected() const { return (_connections.size() > 0); }
+ size_t num_connections() const { return _connections.size(); }
bool is_input() const { return true; }
bool is_output() const { return false; }
- virtual void set_buffer_size(size_t size);
-
protected:
+ void connect_buffers();
bool can_direct() const;
Connections _connections;
diff --git a/src/engine/InternalPlugin.cpp b/src/engine/InternalPlugin.cpp
index 99061e6c..a3d22e10 100644
--- a/src/engine/InternalPlugin.cpp
+++ b/src/engine/InternalPlugin.cpp
@@ -20,7 +20,6 @@
#include "internals/Note.hpp"
#include "internals/Trigger.hpp"
#include "internals/Controller.hpp"
-#include "internals/Transport.hpp"
#include "Engine.hpp"
#include "AudioDriver.hpp"
@@ -40,7 +39,8 @@ InternalPlugin::InternalPlugin(const std::string& uri, const std::string& symbol
NodeImpl*
-InternalPlugin::instantiate(const string& name,
+InternalPlugin::instantiate(BufferFactory& bufs,
+ const string& name,
bool polyphonic,
Ingen::PatchImpl* parent,
Engine& engine)
@@ -52,13 +52,11 @@ InternalPlugin::instantiate(const string& name,
const string uri_str = uri().str();
if (uri_str == NS_INTERNALS "Note") {
- return new NoteNode(name, polyphonic, parent, srate, buffer_size);
+ return new NoteNode(bufs, name, polyphonic, parent, srate, buffer_size);
} else if (uri_str == NS_INTERNALS "Trigger") {
- return new TriggerNode(name, polyphonic, parent, srate, buffer_size);
+ return new TriggerNode(bufs, name, polyphonic, parent, srate, buffer_size);
} else if (uri_str == NS_INTERNALS "Controller") {
- return new ControllerNode(name, polyphonic, parent, srate, buffer_size);
- } else if (uri_str == NS_INTERNALS "Transport") {
- return new TransportNode(name, polyphonic, parent, srate, buffer_size);
+ return new ControllerNode(bufs, name, polyphonic, parent, srate, buffer_size);
} else {
return NULL;
}
diff --git a/src/engine/InternalPlugin.hpp b/src/engine/InternalPlugin.hpp
index d9d6b0b2..b7797b49 100644
--- a/src/engine/InternalPlugin.hpp
+++ b/src/engine/InternalPlugin.hpp
@@ -37,6 +37,7 @@
namespace Ingen {
class NodeImpl;
+class BufferFactory;
/** Implementation of an Internal plugin.
@@ -46,7 +47,8 @@ class InternalPlugin : public PluginImpl
public:
InternalPlugin(const std::string& uri, const std::string& symbol);
- NodeImpl* instantiate(const std::string& name,
+ NodeImpl* instantiate(BufferFactory& bufs,
+ const std::string& name,
bool polyphonic,
Ingen::PatchImpl* parent,
Engine& engine);
diff --git a/src/engine/JackAudioDriver.cpp b/src/engine/JackAudioDriver.cpp
index 667b6d91..86f946da 100644
--- a/src/engine/JackAudioDriver.cpp
+++ b/src/engine/JackAudioDriver.cpp
@@ -50,14 +50,12 @@ JackAudioPort::JackAudioPort(JackAudioDriver* driver, DuplexPort* patch_port)
, Raul::List<JackAudioPort*>::Node(this)
, _driver(driver)
, _jack_port(NULL)
- , _jack_buffer(NULL)
{
assert(patch_port->poly() == 1);
create();
patch_port->buffer(0)->clear();
- patch_port->fixed_buffers(true);
}
@@ -93,19 +91,28 @@ JackAudioPort::destroy()
void
-JackAudioPort::prepare_buffer(jack_nframes_t nframes)
+JackAudioPort::pre_process(jack_nframes_t nframes)
{
+ if (!is_input())
+ return;
+
jack_sample_t* jack_buf = (jack_sample_t*)jack_port_get_buffer(_jack_port, nframes);
- AudioBuffer* patch_buf = (AudioBuffer*)_patch_port->buffer(0);
+ AudioBuffer* patch_buf = (AudioBuffer*)_patch_port->buffer(0).get();
- //cerr << "[JACK] " << _patch_port->path() << " buffer: " << patch_buf << endl;
+ patch_buf->copy(jack_buf, 0, nframes - 1);
+}
- if (jack_buf != _jack_buffer) {
- patch_buf->set_data(jack_buf);
- _jack_buffer = jack_buf;
- }
- assert(patch_buf->data() == jack_buf);
+void
+JackAudioPort::post_process(jack_nframes_t nframes)
+{
+ if (is_input())
+ return;
+
+ jack_sample_t* jack_buf = (jack_sample_t*)jack_port_get_buffer(_jack_port, nframes);
+ AudioBuffer* patch_buf = (AudioBuffer*)_patch_port->buffer(0).get();
+
+ memcpy(jack_buf, patch_buf->data(), nframes * sizeof(Sample));
}
@@ -172,7 +179,7 @@ JackAudioDriver::attach(const std::string& server_name,
_local_client = (jack_client == NULL);
- _buffer_size = jack_get_buffer_size(_client);
+ _buffer_size = jack_get_buffer_size(_client) * sizeof(Sample);
_sample_rate = jack_get_sample_rate(_client);
jack_on_shutdown(_client, shutdown_cb, this);
@@ -334,7 +341,7 @@ JackAudioDriver::_process_cb(jack_nframes_t nframes)
// FIXME: all of this time stuff is screwy
// FIXME: support nframes != buffer_size, even though that never damn well happens
- assert(nframes == _buffer_size);
+ assert(nframes == _buffer_size / sizeof(Sample));
// Jack can elect to not call this function for a cycle, if overloaded
// FIXME: this doesn't make sense, and the start time isn't used anyway
@@ -360,11 +367,9 @@ JackAudioDriver::_process_cb(jack_nframes_t nframes)
// (Aiming for jitter-free 1 block event latency, ideally)
_engine.process_events(_process_context);
- // Set buffers of patch ports to Jack port buffers (zero-copy processing)
- for (Raul::List<JackAudioPort*>::iterator i = _ports.begin(); i != _ports.end(); ++i) {
- assert(*i);
- (*i)->prepare_buffer(nframes);
- }
+ // Read input
+ for (Raul::List<JackAudioPort*>::iterator i = _ports.begin(); i != _ports.end(); ++i)
+ (*i)->pre_process(nframes);
if (_engine.midi_driver())
_engine.midi_driver()->pre_process(_process_context);
@@ -376,6 +381,10 @@ JackAudioDriver::_process_cb(jack_nframes_t nframes)
if (_engine.midi_driver())
_engine.midi_driver()->post_process(_process_context);
+ // Write output
+ for (Raul::List<JackAudioPort*>::iterator i = _ports.begin(); i != _ports.end(); ++i)
+ (*i)->post_process(nframes);
+
_engine.post_processor()->set_end_time(_process_context.end());
return 0;
@@ -420,8 +429,8 @@ int
JackAudioDriver::_buffer_size_cb(jack_nframes_t nframes)
{
if (_root_patch) {
- _root_patch->set_buffer_size(nframes);
- _buffer_size = nframes;
+ _buffer_size = nframes * sizeof(Sample);
+ _root_patch->set_buffer_size(*_engine.buffer_factory(), _buffer_size);
}
return 0;
}
diff --git a/src/engine/JackAudioDriver.hpp b/src/engine/JackAudioDriver.hpp
index c4f7990c..0e062b22 100644
--- a/src/engine/JackAudioDriver.hpp
+++ b/src/engine/JackAudioDriver.hpp
@@ -55,14 +55,14 @@ public:
void set_name(const std::string& name) { jack_port_set_name(_jack_port, name.c_str()); };
- void prepare_buffer(jack_nframes_t nframes);
+ void pre_process(jack_nframes_t nframes);
+ void post_process(jack_nframes_t nframes);
jack_port_t* jack_port() const { return _jack_port; }
private:
JackAudioDriver* _driver;
jack_port_t* _jack_port;
- jack_sample_t* _jack_buffer; ///< Cached for output ports
};
diff --git a/src/engine/JackMidiDriver.cpp b/src/engine/JackMidiDriver.cpp
index 1cb46c3e..6de97f68 100644
--- a/src/engine/JackMidiDriver.cpp
+++ b/src/engine/JackMidiDriver.cpp
@@ -100,7 +100,7 @@ JackMidiPort::pre_process(ProcessContext& context)
assert(_patch_port->poly() == 1);
- EventBuffer* patch_buf = dynamic_cast<EventBuffer*>(_patch_port->buffer(0));
+ EventBuffer* patch_buf = dynamic_cast<EventBuffer*>(_patch_port->buffer(0).get());
assert(patch_buf);
void* jack_buffer = jack_port_get_buffer(_jack_port, context.nframes());
@@ -134,7 +134,7 @@ JackMidiPort::post_process(ProcessContext& context)
if (is_input())
return;
- EventBuffer* patch_buf = dynamic_cast<EventBuffer*>(_patch_port->buffer(0));
+ EventBuffer* patch_buf = dynamic_cast<EventBuffer*>(_patch_port->buffer(0).get());
void* jack_buf = jack_port_get_buffer(_jack_port, context.nframes());
assert(_patch_port->poly() == 1);
diff --git a/src/engine/LADSPANode.cpp b/src/engine/LADSPANode.cpp
index e761ff60..04ffa3f9 100644
--- a/src/engine/LADSPANode.cpp
+++ b/src/engine/LADSPANode.cpp
@@ -62,9 +62,9 @@ LADSPANode::~LADSPANode()
bool
-LADSPANode::prepare_poly(uint32_t poly)
+LADSPANode::prepare_poly(BufferFactory& bufs, uint32_t poly)
{
- NodeBase::prepare_poly(poly);
+ NodeBase::prepare_poly(bufs, poly);
if ( (!_polyphonic)
|| (_prepared_instances && poly <= _prepared_instances->size()) ) {
@@ -82,7 +82,7 @@ LADSPANode::prepare_poly(uint32_t poly)
// Initialize the values of new ports
for (unsigned long j=0; j < num_ports(); ++j) {
PortImpl* const port = _ports->at(j);
- Buffer *buffer = port->prepared_buffer(i);
+ Buffer* buffer = port->prepared_buffer(i).get();
// FIXME: Preserve individual voice values
if (port->type() == DataType::CONTROL) {
@@ -142,7 +142,7 @@ nameify_if_invalid(const string& name)
* value is false, this object may not be used.
*/
bool
-LADSPANode::instantiate()
+LADSPANode::instantiate(BufferFactory& bufs)
{
if (!_ports)
_ports = new Raul::Array<PortImpl*>(_descriptor->PortCount);
@@ -193,11 +193,11 @@ LADSPANode::instantiate()
Path port_path(path().child(port_name));
DataType type = DataType::AUDIO;
- port_buffer_size = _buffer_size;
+ port_buffer_size = _buffer_size * sizeof(Sample);
if (LADSPA_IS_PORT_CONTROL(_descriptor->PortDescriptors[j])) {
type = DataType::CONTROL;
- port_buffer_size = 1;
+ port_buffer_size = sizeof(Sample);
} else {
assert(LADSPA_IS_PORT_AUDIO(_descriptor->PortDescriptors[j]));
}
@@ -210,10 +210,10 @@ LADSPANode::instantiate()
const float value = default_val ? default_val.get() : 0.0f;
if (LADSPA_IS_PORT_INPUT(_descriptor->PortDescriptors[j])) {
- port = new InputPort(this, port_name, j, _polyphony, type, value, port_buffer_size);
+ port = new InputPort(bufs, this, port_name, j, _polyphony, type, value, port_buffer_size);
_ports->at(j) = port;
} else if (LADSPA_IS_PORT_OUTPUT(_descriptor->PortDescriptors[j])) {
- port = new OutputPort(this, port_name, j, _polyphony, type, value, port_buffer_size);
+ port = new OutputPort(bufs, this, port_name, j, _polyphony, type, value, port_buffer_size);
_ports->at(j) = port;
}
@@ -236,7 +236,7 @@ LADSPANode::instantiate()
// Set initial/default value
if (port->buffer_size() == 1) {
for (uint32_t i=0; i < _polyphony; ++i)
- ((AudioBuffer*)port->buffer(i))->set_value(value, 0, 0);
+ ((AudioBuffer*)port->buffer(i).get())->set_value(value, 0, 0);
}
if (port->is_input() && port->buffer_size() == 1) {
@@ -265,9 +265,9 @@ LADSPANode::activate()
set_port_buffer(i, j, port->buffer(i));
if (port->type() == DataType::CONTROL) {
- ((AudioBuffer*)port->buffer(i))->set_value(port->value().get_float(), 0, 0);
+ ((AudioBuffer*)port->buffer(i).get())->set_value(port->value().get_float(), 0, 0);
} else if (port->type() == DataType::AUDIO) {
- ((AudioBuffer*)port->buffer(i))->set_value(0.0f, 0, 0);
+ ((AudioBuffer*)port->buffer(i).get())->set_value(0.0f, 0, 0);
}
}
if (_descriptor->activate != NULL)
@@ -300,16 +300,11 @@ LADSPANode::process(ProcessContext& context)
void
-LADSPANode::set_port_buffer(uint32_t voice, uint32_t port_num, Buffer* buf)
+LADSPANode::set_port_buffer(uint32_t voice, uint32_t port_num, SharedPtr<Buffer> buf)
{
assert(voice < _polyphony);
-
- AudioBuffer* audio_buffer = dynamic_cast<AudioBuffer*>(buf);
- assert(audio_buffer);
-
- if (port_num < _descriptor->PortCount)
- _descriptor->connect_port((*_instances)[voice], port_num,
- audio_buffer->data());
+ _descriptor->connect_port((*_instances)[voice], port_num,
+ (LADSPA_Data*)buf->port_data(_ports->at(port_num)->type()));
}
diff --git a/src/engine/LADSPANode.hpp b/src/engine/LADSPANode.hpp
index 008319b0..29f8fc5b 100644
--- a/src/engine/LADSPANode.hpp
+++ b/src/engine/LADSPANode.hpp
@@ -45,9 +45,9 @@ public:
~LADSPANode();
- bool instantiate();
+ bool instantiate(BufferFactory& bufs);
- bool prepare_poly(uint32_t poly);
+ bool prepare_poly(BufferFactory& bufs, uint32_t poly);
bool apply_poly(Raul::Maid& maid, uint32_t poly);
void activate();
@@ -55,7 +55,7 @@ public:
void process(ProcessContext& context);
- void set_port_buffer(uint32_t voice, uint32_t port_num, Buffer* buf);
+ void set_port_buffer(uint32_t voice, uint32_t port_num, SharedPtr<Buffer> buf);
protected:
void get_port_limits(unsigned long port_index,
diff --git a/src/engine/LADSPAPlugin.cpp b/src/engine/LADSPAPlugin.cpp
index 44df77b0..dd95bfbe 100644
--- a/src/engine/LADSPAPlugin.cpp
+++ b/src/engine/LADSPAPlugin.cpp
@@ -58,7 +58,8 @@ LADSPAPlugin::get_property(const Raul::URI& uri) const
NodeImpl*
-LADSPAPlugin::instantiate(const string& name,
+LADSPAPlugin::instantiate(BufferFactory& bufs,
+ const string& name,
bool polyphonic,
Ingen::PatchImpl* parent,
Engine& engine)
@@ -97,7 +98,7 @@ LADSPAPlugin::instantiate(const string& name,
if (descriptor != NULL) {
n = new LADSPANode(this, name, polyphonic, parent, descriptor, srate, buffer_size);
- if ( ! n->instantiate() ) {
+ if ( ! n->instantiate(bufs) ) {
delete n;
n = NULL;
}
diff --git a/src/engine/LADSPAPlugin.hpp b/src/engine/LADSPAPlugin.hpp
index 0a9bbdd7..332bdd8e 100644
--- a/src/engine/LADSPAPlugin.hpp
+++ b/src/engine/LADSPAPlugin.hpp
@@ -44,7 +44,8 @@ public:
const std::string& label,
const std::string& name);
- NodeImpl* instantiate(const std::string& name,
+ NodeImpl* instantiate(BufferFactory& bufs,
+ const std::string& name,
bool polyphonic,
Ingen::PatchImpl* parent,
Engine& engine);
diff --git a/src/engine/LV2Node.cpp b/src/engine/LV2Node.cpp
index 1515344a..9ac478a8 100644
--- a/src/engine/LV2Node.cpp
+++ b/src/engine/LV2Node.cpp
@@ -70,9 +70,9 @@ LV2Node::~LV2Node()
bool
-LV2Node::prepare_poly(uint32_t poly)
+LV2Node::prepare_poly(BufferFactory& bufs, uint32_t poly)
{
- NodeBase::prepare_poly(poly);
+ NodeBase::prepare_poly(bufs, poly);
if ( (!_polyphonic)
|| (_prepared_instances && poly <= _prepared_instances->size()) ) {
@@ -93,7 +93,7 @@ LV2Node::prepare_poly(uint32_t poly)
// Initialize the values of new ports
for (unsigned long j=0; j < num_ports(); ++j) {
PortImpl* const port = _ports->at(j);
- Buffer *buffer = port->prepared_buffer(i);
+ Buffer* buffer = port->prepared_buffer(i).get();
// FIXME: Preserve individual voice values
if (port->type() == DataType::CONTROL) {
@@ -140,7 +140,7 @@ LV2Node::apply_poly(Raul::Maid& maid, uint32_t poly)
* value is false, this object may not be used.
*/
bool
-LV2Node::instantiate()
+LV2Node::instantiate(BufferFactory& bufs)
{
SharedPtr<LV2Info> info = _lv2_plugin->lv2_info();
SLV2Plugin plug = _lv2_plugin->slv2_plugin();
@@ -210,7 +210,7 @@ LV2Node::instantiate()
DataType data_type = DataType::UNKNOWN;
if (slv2_port_is_a(plug, id, info->control_class)) {
data_type = DataType::CONTROL;
- port_buffer_size = 1;
+ port_buffer_size = sizeof(Sample);
} else if (slv2_port_is_a(plug, id, info->audio_class)) {
data_type = DataType::AUDIO;
port_buffer_size = _buffer_size;
@@ -266,12 +266,12 @@ LV2Node::instantiate()
val = isnan(def_values[j]) ? 0.0f : def_values[j];
if (direction == INPUT)
- port = new InputPort(this, port_name, j, _polyphony, data_type, val, port_buffer_size);
+ port = new InputPort(bufs, this, port_name, j, _polyphony, data_type, val, port_buffer_size);
else
- port = new OutputPort(this, port_name, j, _polyphony, data_type, val, port_buffer_size);
+ port = new OutputPort(bufs, this, port_name, j, _polyphony, data_type, val, port_buffer_size);
if (direction == INPUT && data_type == DataType::CONTROL)
- ((AudioBuffer*)port->buffer(0))->set_value(val.get_float(), 0, 0);
+ ((AudioBuffer*)port->buffer(0).get())->set_value(val.get_float(), 0, 0);
SLV2Values contexts = slv2_port_get_value(plug, id, context_pred);
for (uint32_t i = 0; i < slv2_values_size(contexts); ++i) {
@@ -312,9 +312,9 @@ LV2Node::activate()
set_port_buffer(i, j, port->buffer(i));
if (port->type() == DataType::CONTROL) {
- ((AudioBuffer*)port->buffer(i))->set_value(port->value().get_float(), 0, 0);
+ ((AudioBuffer*)port->buffer(i).get())->set_value(port->value().get_float(), 0, 0);
} else if (port->type() == DataType::AUDIO) {
- ((AudioBuffer*)port->buffer(i))->set_value(0.0f, 0, 0);
+ ((AudioBuffer*)port->buffer(i).get())->set_value(0.0f, 0, 0);
}
}
slv2_instance_activate((*_instances)[i]);
@@ -361,10 +361,11 @@ LV2Node::process(ProcessContext& context)
void
-LV2Node::set_port_buffer(uint32_t voice, uint32_t port_num, Buffer* buf)
+LV2Node::set_port_buffer(uint32_t voice, uint32_t port_num, SharedPtr<Buffer> buf)
{
assert(voice < _polyphony);
- slv2_instance_connect_port((*_instances)[voice], port_num, buf->raw_data());
+ slv2_instance_connect_port((*_instances)[voice], port_num,
+ buf->port_data(_ports->at(port_num)->type()));
}
diff --git a/src/engine/LV2Node.hpp b/src/engine/LV2Node.hpp
index 8a543f2d..e971b1d0 100644
--- a/src/engine/LV2Node.hpp
+++ b/src/engine/LV2Node.hpp
@@ -46,9 +46,9 @@ public:
~LV2Node();
- bool instantiate();
+ bool instantiate(BufferFactory& bufs);
- bool prepare_poly(uint32_t poly);
+ bool prepare_poly(BufferFactory& bufs, uint32_t poly);
bool apply_poly(Raul::Maid& maid, uint32_t poly);
void activate();
@@ -58,7 +58,7 @@ public:
void process(ProcessContext& context);
- void set_port_buffer(uint32_t voice, uint32_t port_num, Buffer* buf);
+ void set_port_buffer(uint32_t voice, uint32_t port_num, SharedPtr<Buffer> buf);
protected:
LV2Plugin* _lv2_plugin;
diff --git a/src/engine/LV2Plugin.cpp b/src/engine/LV2Plugin.cpp
index 7b289c32..3f3e25c2 100644
--- a/src/engine/LV2Plugin.cpp
+++ b/src/engine/LV2Plugin.cpp
@@ -60,7 +60,8 @@ LV2Plugin::symbol() const
NodeImpl*
-LV2Plugin::instantiate(const string& name,
+LV2Plugin::instantiate(BufferFactory& bufs,
+ const string& name,
bool polyphonic,
Ingen::PatchImpl* parent,
Engine& engine)
@@ -73,7 +74,7 @@ LV2Plugin::instantiate(const string& name,
Glib::Mutex::Lock lock(engine.world()->rdf_world->mutex());
LV2Node* n = new LV2Node(this, name, polyphonic, parent, srate, buffer_size);
- if ( ! n->instantiate() ) {
+ if ( ! n->instantiate(bufs) ) {
delete n;
n = NULL;
}
diff --git a/src/engine/LV2Plugin.hpp b/src/engine/LV2Plugin.hpp
index 29c987d4..fdb90a22 100644
--- a/src/engine/LV2Plugin.hpp
+++ b/src/engine/LV2Plugin.hpp
@@ -48,7 +48,8 @@ class LV2Plugin : public PluginImpl
public:
LV2Plugin(SharedPtr<LV2Info> lv2_info, const std::string& uri);
- NodeImpl* instantiate(const std::string& name,
+ NodeImpl* instantiate(BufferFactory& bufs,
+ const std::string& name,
bool polyphonic,
Ingen::PatchImpl* parent,
Engine& engine);
diff --git a/src/engine/NodeBase.cpp b/src/engine/NodeBase.cpp
index 25660c37..ab8b7054 100644
--- a/src/engine/NodeBase.cpp
+++ b/src/engine/NodeBase.cpp
@@ -102,7 +102,7 @@ NodeBase::deactivate()
bool
-NodeBase::prepare_poly(uint32_t poly)
+NodeBase::prepare_poly(BufferFactory& bufs, uint32_t poly)
{
assert(ThreadManager::current_thread_id() == THREAD_PRE_PROCESS);
@@ -111,7 +111,7 @@ NodeBase::prepare_poly(uint32_t poly)
if (_ports)
for (size_t i=0; i < _ports->size(); ++i)
- _ports->at(i)->prepare_poly(poly);
+ _ports->at(i)->prepare_poly(bufs, poly);
return true;
}
@@ -139,7 +139,7 @@ NodeBase::apply_poly(Raul::Maid& maid, uint32_t poly)
void
-NodeBase::set_buffer_size(size_t size)
+NodeBase::set_buffer_size(BufferFactory& bufs, size_t size)
{
assert(ThreadManager::current_thread_id() == THREAD_PROCESS);
@@ -147,7 +147,7 @@ NodeBase::set_buffer_size(size_t size)
if (_ports)
for (size_t i=0; i < _ports->size(); ++i)
- _ports->at(i)->set_buffer_size(size);
+ _ports->at(i)->set_buffer_size(bufs, size);
}
@@ -209,8 +209,8 @@ NodeBase::pre_process(Context& context)
{
assert(ThreadManager::current_thread_id() == THREAD_PROCESS);
- // Mix down any ports with multiple inputs
- for (size_t i=0; i < num_ports(); ++i) {
+ // Mix down input ports
+ for (uint32_t i = 0; i < num_ports(); ++i) {
PortImpl* const port = _ports->at(i);
if (port->context() == Context::AUDIO)
port->pre_process(context);
@@ -225,8 +225,8 @@ NodeBase::post_process(Context& context)
{
assert(ThreadManager::current_thread_id() == THREAD_PROCESS);
- /* Write output ports */
- for (size_t i=0; _ports && i < _ports->size(); ++i) {
+ // Write output ports
+ for (size_t i = 0; _ports && i < _ports->size(); ++i) {
PortImpl* const port = _ports->at(i);
if (port->context() == Context::AUDIO)
_ports->at(i)->post_process(context);
diff --git a/src/engine/NodeBase.hpp b/src/engine/NodeBase.hpp
index 15772551..7a7db8e1 100644
--- a/src/engine/NodeBase.hpp
+++ b/src/engine/NodeBase.hpp
@@ -60,7 +60,7 @@ public:
virtual void deactivate();
bool activated() { return _activated; }
- virtual bool prepare_poly(uint32_t poly);
+ virtual bool prepare_poly(BufferFactory& bufs, uint32_t poly);
virtual bool apply_poly(Raul::Maid& maid, uint32_t poly);
virtual void reset_input_ready();
@@ -82,9 +82,9 @@ public:
virtual void process(ProcessContext& context) = 0;
virtual void post_process(Context& context);
- virtual void set_port_buffer(uint32_t voice, uint32_t port_num, Buffer* buf) {}
+ virtual void set_port_buffer(uint32_t voice, uint32_t port_num, SharedPtr<Buffer> buf) {}
- virtual void set_buffer_size(size_t size);
+ virtual void set_buffer_size(BufferFactory& bufs, size_t size);
SampleRate sample_rate() const { return _srate; }
size_t buffer_size() const { return _buffer_size; }
diff --git a/src/engine/NodeFactory.cpp b/src/engine/NodeFactory.cpp
index 8b2e93d9..c6dca64b 100644
--- a/src/engine/NodeFactory.cpp
+++ b/src/engine/NodeFactory.cpp
@@ -24,14 +24,14 @@
#include "redlandmm/World.hpp"
#include "raul/Atom.hpp"
#include "module/World.hpp"
-#include "NodeFactory.hpp"
-#include "ThreadManager.hpp"
#include "internals/Note.hpp"
#include "internals/Trigger.hpp"
#include "internals/Controller.hpp"
-#include "internals/Transport.hpp"
-#include "PatchImpl.hpp"
+#include "Engine.hpp"
#include "InternalPlugin.hpp"
+#include "NodeFactory.hpp"
+#include "PatchImpl.hpp"
+#include "ThreadManager.hpp"
#ifdef HAVE_LADSPA_H
#include "LADSPANode.hpp"
#include "LADSPAPlugin.hpp"
@@ -137,21 +137,22 @@ NodeFactory::load_plugins()
void
NodeFactory::load_internal_plugins()
{
- // This is a touch gross...
+ // FIXME: This is a touch gross...
+
+ const SampleRate r = 48000;
+ const size_t s = sizeof(Sample);
- PatchImpl* parent = new PatchImpl(*_world->local_engine, "dummy", 1, NULL, 1, 1, 1);
+ Engine& engine = *_world->local_engine;
+ PatchImpl* parent = new PatchImpl(engine, "dummy", 1, NULL, r, s, 1);
NodeImpl* n = NULL;
- n = new NoteNode("foo", 1, parent, 1, 1);
- _plugins.insert(make_pair(n->plugin_impl()->uri(), n->plugin_impl()));
- delete n;
- n = new TriggerNode("foo", 1, parent, 1, 1);
+ n = new NoteNode(*engine.buffer_factory(), "foo", 1, parent, r, s);
_plugins.insert(make_pair(n->plugin_impl()->uri(), n->plugin_impl()));
delete n;
- n = new ControllerNode("foo", 1, parent, 1, 1);
+ n = new TriggerNode(*engine.buffer_factory(), "foo", 1, parent, r, s);
_plugins.insert(make_pair(n->plugin_impl()->uri(), n->plugin_impl()));
delete n;
- n = new TransportNode("foo", 1, parent, 1, 1);
+ n = new ControllerNode(*engine.buffer_factory(), "foo", 1, parent, r, s);
_plugins.insert(make_pair(n->plugin_impl()->uri(), n->plugin_impl()));
delete n;
diff --git a/src/engine/NodeImpl.hpp b/src/engine/NodeImpl.hpp
index 67ab0898..55ff5417 100644
--- a/src/engine/NodeImpl.hpp
+++ b/src/engine/NodeImpl.hpp
@@ -29,10 +29,12 @@ namespace Ingen {
namespace Shared { class Plugin; class Node; class Port; }
class Buffer;
-class PluginImpl;
+class BufferFactory;
+class Engine;
+class MessageContext;
class PatchImpl;
+class PluginImpl;
class PortImpl;
-class MessageContext;
class ProcessContext;
@@ -69,7 +71,7 @@ public:
* Preprocessor thread, poly is actually applied by apply_poly.
* \return true on success.
*/
- virtual bool prepare_poly(uint32_t poly) = 0;
+ virtual bool prepare_poly(BufferFactory& bufs, uint32_t poly) = 0;
/** Apply a new (external) polyphony value.
*
@@ -131,7 +133,7 @@ public:
*/
virtual void process(ProcessContext& context) = 0;
- virtual void set_port_buffer(uint32_t voice, uint32_t port_num, Buffer* buf) = 0;
+ virtual void set_port_buffer(uint32_t voice, uint32_t port_num, SharedPtr<Buffer> buf) = 0;
virtual uint32_t num_ports() const = 0;
@@ -167,7 +169,7 @@ public:
*/
virtual const Shared::Plugin* plugin() const = 0;
- virtual void set_buffer_size(size_t size) = 0;
+ virtual void set_buffer_size(BufferFactory& bufs, size_t size) = 0;
};
diff --git a/src/engine/ObjectBuffer.cpp b/src/engine/ObjectBuffer.cpp
index a26eaea5..f96c910f 100644
--- a/src/engine/ObjectBuffer.cpp
+++ b/src/engine/ObjectBuffer.cpp
@@ -34,56 +34,41 @@ namespace Ingen {
using namespace Shared;
-/** Allocate a new string buffer.
- * \a capacity is in bytes.
+/** Allocate a new object buffer.
+ * \a capacity is in bytes, including LV2_Object header
*/
ObjectBuffer::ObjectBuffer(size_t capacity)
: Buffer(DataType(DataType::VALUE), capacity)
{
- capacity = std::max(capacity, (size_t)32);
- cerr << "Creating Object Buffer " << _buf << " capacity = " << capacity << endl;
- _local_buf = (LV2_Object*)malloc(sizeof(LV2_Object) + capacity);
- _buf = _local_buf;
- clear();
+ //cerr << "Creating Object Buffer capacity = " << capacity << endl;
+ assert(capacity >= sizeof(LV2_Object));
+
+#ifdef HAVE_POSIX_MEMALIGN
+ const int ret = posix_memalign((void**)&_buf, 16, capacity);
+#else
+ _buf = (LV2_Object*)malloc(capacity);
+ const int ret = (_buf != NULL) ? 0 : -1;
+#endif
+
+ if (ret != 0) {
+ cerr << "Failed to allocate buffer. Aborting." << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ object()->type = 0;
+ object()->size = capacity;
}
void
ObjectBuffer::clear()
{
- // nil
+ // null
_buf->type = 0;
_buf->size = 0;
}
-/** Use another buffer's data instead of the local one.
- *
- * This buffer will essentially be identical to @a buf after this call.
- */
-bool
-ObjectBuffer::join(Buffer* buf)
-{
- assert(buf != this);
- ObjectBuffer* sbuf = dynamic_cast<ObjectBuffer*>(buf);
- if (!sbuf)
- return false;
-
- _buf = sbuf->_local_buf;
- _joined_buf = sbuf;
-
- return true;
-}
-
-
-void
-ObjectBuffer::unjoin()
-{
- _joined_buf = NULL;
- _buf = _local_buf;
-}
-
-
void
ObjectBuffer::copy(Context& context, const Buffer* src_buf)
{
@@ -91,27 +76,51 @@ ObjectBuffer::copy(Context& context, const Buffer* src_buf)
if (!src || src == this || src->_buf == _buf)
return;
- // Copy if src is a POD object only, that fits
- if (src->_buf->type != 0 && src->_buf->size <= size())
- memcpy(_buf, src->_buf, sizeof(LV2_Object) + src->_buf->size);
+ // 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_Object) + src_buf->size());
}
void
ObjectBuffer::resize(size_t size)
{
- const bool using_local_data = (_buf == _local_buf);
- const uint32_t contents_size = sizeof(LV2_Object) + _buf->size;
+ const uint32_t contents_size = sizeof(LV2_Object) + _buf->size;
- _local_buf = (LV2_Object*)realloc(_buf, sizeof(LV2_Object) + size);
- _size = size;
+ _buf = (LV2_Object*)realloc(_buf, sizeof(LV2_Object) + size);
+ _size = size;
// If we shrunk and chopped the current contents, clear corrupt data
if (size < contents_size)
clear();
+}
+
- if (using_local_data)
- _buf = _local_buf;
+void*
+ObjectBuffer::port_data(DataType port_type)
+{
+ switch (port_type.symbol()) {
+ case DataType::CONTROL:
+ return object()->body;
+ case DataType::AUDIO:
+ return ((LV2_Vector_Body*)object()->body)->elems;
+ default:
+ return _buf;
+ }
+}
+
+
+const void*
+ObjectBuffer::port_data(DataType port_type) const
+{
+ switch (port_type.symbol()) {
+ case DataType::CONTROL:
+ return _buf + sizeof(LV2_Object);
+ case DataType::AUDIO:
+ return _buf + sizeof(LV2_Object) + sizeof(LV2_Vector_Body);
+ default:
+ return _buf;
+ }
}
diff --git a/src/engine/ObjectBuffer.hpp b/src/engine/ObjectBuffer.hpp
index a1d198e9..ec28453b 100644
--- a/src/engine/ObjectBuffer.hpp
+++ b/src/engine/ObjectBuffer.hpp
@@ -33,22 +33,19 @@ public:
void clear();
- void* raw_data() { return (void*)_buf; }
- const void* raw_data() const { return (void*)_buf; }
-
- LV2_Object* data() { return _buf; }
- const LV2_Object* data() const { return _buf; }
-
- bool join(Buffer* buf);
- void unjoin();
+ void* port_data(Shared::DataType port_type);
+ const void* port_data(Shared::DataType port_type) const;
void copy(Context& context, const Buffer* src);
+ void mix(Context& context, const Buffer* src) {}
void resize(size_t size);
+ LV2_Object* object() { return _buf; }
+ const LV2_Object* object() const { return _buf; }
+
private:
- LV2_Object* _buf; ///< Contents (_local_buf or belongs to _joined_buf)
- LV2_Object* _local_buf; ///< Local contents
+ LV2_Object* _buf; ///< Contents
};
diff --git a/src/engine/ObjectSender.cpp b/src/engine/ObjectSender.cpp
index 072d6c52..02886be5 100644
--- a/src/engine/ObjectSender.cpp
+++ b/src/engine/ObjectSender.cpp
@@ -142,7 +142,7 @@ ObjectSender::send_port(ClientInterface* client, const PortImpl* port, bool bund
// Send control value
if (port->type() == DataType::CONTROL) {
- const Sample& value = dynamic_cast<const AudioBuffer*>(port->buffer(0))->value_at(0);
+ const Sample& value = PtrCast<const AudioBuffer>(port->buffer(0))->value_at(0);
client->set_port_value(port->path(), value);
}
diff --git a/src/engine/OutputPort.cpp b/src/engine/OutputPort.cpp
index 8f6b7751..30d29fa0 100644
--- a/src/engine/OutputPort.cpp
+++ b/src/engine/OutputPort.cpp
@@ -29,14 +29,15 @@ namespace Ingen {
namespace Shared { class Patch; }
using namespace Shared;
-OutputPort::OutputPort(NodeImpl* parent,
+OutputPort::OutputPort(BufferFactory& bufs,
+ NodeImpl* parent,
const string& name,
uint32_t index,
uint32_t poly,
DataType type,
const Raul::Atom& value,
size_t buffer_size)
- : PortImpl(parent, name, index, poly, type, value, buffer_size)
+ : PortImpl(bufs, parent, name, index, poly, type, value, buffer_size)
{
if (!dynamic_cast<Patch*>(parent))
add_property("rdf:type", Raul::Atom(Raul::Atom::URI, "lv2:OutputPort"));
@@ -49,16 +50,17 @@ OutputPort::OutputPort(NodeImpl* parent,
void
OutputPort::pre_process(Context& context)
{
- for (uint32_t i=0; i < _poly; ++i)
- buffer(i)->prepare_write(context);
+ connect_buffers();
+ for (uint32_t v = 0; v < _poly; ++v)
+ buffer(v)->prepare_write(context);
}
void
OutputPort::post_process(Context& context)
{
- for (uint32_t i=0; i < _poly; ++i)
- buffer(i)->prepare_read(context);
+ for (uint32_t v = 0; v < _poly; ++v)
+ buffer(v)->prepare_read(context);
//cerr << path() << " output post: buffer: " << buffer(0) << endl;
diff --git a/src/engine/OutputPort.hpp b/src/engine/OutputPort.hpp
index 15382332..baaa6680 100644
--- a/src/engine/OutputPort.hpp
+++ b/src/engine/OutputPort.hpp
@@ -39,7 +39,8 @@ namespace Ingen {
class OutputPort : virtual public PortImpl
{
public:
- OutputPort(NodeImpl* parent,
+ OutputPort(BufferFactory& bufs,
+ NodeImpl* parent,
const std::string& name,
uint32_t index,
uint32_t poly,
diff --git a/src/engine/PatchImpl.cpp b/src/engine/PatchImpl.cpp
index b4fb8c31..2e02355f 100644
--- a/src/engine/PatchImpl.cpp
+++ b/src/engine/PatchImpl.cpp
@@ -98,17 +98,17 @@ PatchImpl::disable()
bool
-PatchImpl::prepare_internal_poly(uint32_t poly)
+PatchImpl::prepare_internal_poly(BufferFactory& bufs, uint32_t poly)
{
assert(ThreadManager::current_thread_id() == THREAD_PRE_PROCESS);
/* TODO: ports? internal/external poly? */
for (List<NodeImpl*>::iterator i = _nodes.begin(); i != _nodes.end(); ++i)
- (*i)->prepare_poly(poly);
+ (*i)->prepare_poly(bufs, poly);
for (Connections::iterator i = _connections.begin(); i != _connections.end(); ++i)
- ((ConnectionImpl*)i->get())->prepare_poly(poly);
+ ((ConnectionImpl*)i->get())->prepare_poly(bufs, poly);
/* FIXME: Deal with failure */
@@ -242,15 +242,15 @@ PatchImpl::process_single(ProcessContext& context)
void
-PatchImpl::set_buffer_size(size_t size)
+PatchImpl::set_buffer_size(BufferFactory& bufs, size_t size)
{
- NodeBase::set_buffer_size(size);
+ NodeBase::set_buffer_size(bufs, size);
assert(_buffer_size == size);
CompiledPatch* const cp = _compiled_patch;
for (size_t i=0; i < cp->size(); ++i)
- (*cp)[i].node()->set_buffer_size(size);
+ (*cp)[i].node()->set_buffer_size(bufs, size);
}
@@ -342,7 +342,7 @@ PatchImpl::num_ports() const
/** Create a port. Not realtime safe.
*/
PortImpl*
-PatchImpl::create_port(const string& name, DataType type, size_t buffer_size, bool is_output)
+PatchImpl::create_port(BufferFactory& bufs, const string& name, DataType type, size_t buffer_size, bool is_output)
{
if (type == DataType::UNKNOWN) {
cerr << "[PatchImpl::create_port] Unknown port type " << type.uri() << endl;
@@ -351,7 +351,7 @@ PatchImpl::create_port(const string& name, DataType type, size_t buffer_size, bo
assert( !(type == DataType::UNKNOWN) );
- return new DuplexPort(this, name, num_ports(), _polyphony, type, Raul::Atom(), buffer_size, is_output);
+ return new DuplexPort(bufs, this, name, num_ports(), _polyphony, type, Raul::Atom(), buffer_size, is_output);
}
diff --git a/src/engine/PatchImpl.hpp b/src/engine/PatchImpl.hpp
index 8bdbd21a..67f35869 100644
--- a/src/engine/PatchImpl.hpp
+++ b/src/engine/PatchImpl.hpp
@@ -63,14 +63,14 @@ public:
void process(ProcessContext& context);
- void set_buffer_size(size_t size);
+ void set_buffer_size(BufferFactory& bufs, size_t size);
/** Prepare for a new (internal) polyphony value.
*
* Preprocessor thread, poly is actually applied by apply_internal_poly.
* \return true on success.
*/
- bool prepare_internal_poly(uint32_t poly);
+ bool prepare_internal_poly(BufferFactory& bufs, uint32_t poly);
/** Apply a new (internal) polyphony value.
*
@@ -96,7 +96,7 @@ public:
uint32_t num_ports() const;
- PortImpl* create_port(const std::string& name, Shared::DataType type, size_t buffer_size, bool is_output);
+ PortImpl* create_port(BufferFactory& bufs, const std::string& name, Shared::DataType type, size_t buffer_size, bool is_output);
void add_input(Raul::List<PortImpl*>::Node* port) { _input_ports.push_back(port); } ///< Preprocesser thread
void add_output(Raul::List<PortImpl*>::Node* port) { _output_ports.push_back(port); } ///< Preprocessor thread
Raul::List<PortImpl*>::Node* remove_port(const std::string& name);
diff --git a/src/engine/PatchPlugin.hpp b/src/engine/PatchPlugin.hpp
index 4a5a39e9..99c9359f 100644
--- a/src/engine/PatchPlugin.hpp
+++ b/src/engine/PatchPlugin.hpp
@@ -41,7 +41,8 @@ public:
: PluginImpl(Plugin::Patch, uri)
{}
- NodeImpl* instantiate(const std::string& name,
+ NodeImpl* instantiate(BufferFactory& bufs,
+ const std::string& name,
bool polyphonic,
Ingen::PatchImpl* parent,
Engine& engine)
diff --git a/src/engine/PluginImpl.cpp b/src/engine/PluginImpl.cpp
index 7a481c55..cdc6ffb2 100644
--- a/src/engine/PluginImpl.cpp
+++ b/src/engine/PluginImpl.cpp
@@ -20,7 +20,6 @@
#include "internals/Note.hpp"
#include "internals/Trigger.hpp"
#include "internals/Controller.hpp"
-#include "internals/Transport.hpp"
using namespace std;
diff --git a/src/engine/PluginImpl.hpp b/src/engine/PluginImpl.hpp
index 38b6ad53..6dcf77a5 100644
--- a/src/engine/PluginImpl.hpp
+++ b/src/engine/PluginImpl.hpp
@@ -32,6 +32,7 @@ namespace Ingen {
class PatchImpl;
class NodeImpl;
class Engine;
+class BufferFactory;
/** Implementation of a plugin (internal code, or a loaded shared library).
@@ -50,7 +51,8 @@ public:
, _module(NULL)
{}
- virtual NodeImpl* instantiate(const std::string& name,
+ virtual NodeImpl* instantiate(BufferFactory& bufs,
+ const std::string& name,
bool polyphonic,
Ingen::PatchImpl* parent,
Engine& engine) = 0;
diff --git a/src/engine/PortImpl.cpp b/src/engine/PortImpl.cpp
index ecb0d20b..169c7289 100644
--- a/src/engine/PortImpl.cpp
+++ b/src/engine/PortImpl.cpp
@@ -24,6 +24,7 @@
#include "AudioBuffer.hpp"
#include "EventBuffer.hpp"
#include "Engine.hpp"
+#include "BufferFactory.hpp"
#include "LV2Object.hpp"
#include "NodeImpl.hpp"
#include "ObjectBuffer.hpp"
@@ -38,7 +39,8 @@ namespace Ingen {
using namespace Shared;
-PortImpl::PortImpl(NodeImpl* const node,
+PortImpl::PortImpl(BufferFactory& bufs,
+ NodeImpl* const node,
const string& name,
uint32_t index,
uint32_t poly,
@@ -46,23 +48,27 @@ PortImpl::PortImpl(NodeImpl* const node,
const Atom& value,
size_t buffer_size)
: GraphObjectImpl(node, name, (type == DataType::AUDIO || type == DataType::CONTROL))
+ , _bufs(bufs)
, _index(index)
, _poly(poly)
, _buffer_size(buffer_size)
, _type(type)
, _value(value)
- , _fixed_buffers(false)
, _broadcast(false)
, _set_by_user(false)
, _last_broadcasted_value(_value.type() == Atom::FLOAT ? _value.get_float() : 0.0f) // default?
, _context(Context::AUDIO)
- , _buffers(new Array<Buffer*>(poly))
+ , _buffers(new Array< SharedPtr<Buffer> >(poly))
, _prepared_buffers(NULL)
{
assert(node != NULL);
assert(_poly > 0);
- allocate_buffers();
+ _buffers->alloc(_poly);
+ for (uint32_t v = 0; v < _poly; ++v)
+ _buffers->at(v) = bufs.get(_type, _buffer_size);
+
+ _prepared_buffers = _buffers;
if (node->parent() == NULL)
_polyphonic = false;
@@ -80,9 +86,8 @@ PortImpl::PortImpl(NodeImpl* const node,
PortImpl::~PortImpl()
{
- if (!_fixed_buffers)
- for (uint32_t i=0; i < _poly; ++i)
- delete _buffers->at(i);
+ for (uint32_t v = 0; v < _poly; ++v)
+ _buffers->at(v).reset();
delete _buffers;
}
@@ -99,16 +104,16 @@ PortImpl::set_polyphonic(Maid& maid, bool p)
bool
-PortImpl::prepare_poly(uint32_t poly)
+PortImpl::prepare_poly(BufferFactory& bufs, uint32_t poly)
{
if (!_polyphonic || !_parent->polyphonic())
return true;
/* FIXME: poly never goes down, harsh on memory.. */
if (poly > _poly) {
- _prepared_buffers = new Array<Buffer*>(poly, *_buffers);
+ _prepared_buffers = new Array< SharedPtr<Buffer> >(poly, *_buffers);
for (uint32_t i = _poly; i < _prepared_buffers->size(); ++i)
- _prepared_buffers->at(i) = Buffer::create(_type, _buffer_size);
+ _prepared_buffers->at(i) = bufs.get(_type, _buffer_size);
}
return true;
@@ -138,24 +143,12 @@ PortImpl::apply_poly(Maid& maid, uint32_t poly)
void
-PortImpl::allocate_buffers()
-{
- _buffers->alloc(_poly);
-
- for (uint32_t i=0; i < _poly; ++i)
- _buffers->at(i) = Buffer::create(_type, _buffer_size);
-
- _prepared_buffers = _buffers;
-}
-
-
-void
-PortImpl::set_buffer_size(size_t size)
+PortImpl::set_buffer_size(BufferFactory& bufs, size_t size)
{
_buffer_size = size;
- for (uint32_t i=0; i < _poly; ++i)
- _buffers->at(i)->resize(size);
+ for (uint32_t v = 0; v < _poly; ++v)
+ _buffers->at(v)->resize(size);
connect_buffers();
}
@@ -164,16 +157,16 @@ PortImpl::set_buffer_size(size_t size)
void
PortImpl::connect_buffers()
{
- for (uint32_t i=0; i < _poly; ++i)
- PortImpl::parent_node()->set_port_buffer(i, _index, buffer(i));
+ for (uint32_t v = 0; v < _poly; ++v)
+ PortImpl::parent_node()->set_port_buffer(v, _index, buffer(v));
}
void
PortImpl::clear_buffers()
{
- for (uint32_t i=0; i < _poly; ++i)
- buffer(i)->clear();
+ for (uint32_t v = 0; v < _poly; ++v)
+ buffer(v)->clear();
}
@@ -186,16 +179,16 @@ PortImpl::broadcast_value(Context& context, bool force)
break;
case DataType::AUDIO:
case DataType::CONTROL:
- val = ((AudioBuffer*)buffer(0))->value_at(0);
+ val = ((AudioBuffer*)buffer(0).get())->value_at(0);
break;
case DataType::EVENTS:
- if (((EventBuffer*)buffer(0))->event_count() > 0) {
+ if (((EventBuffer*)buffer(0).get())->event_count() > 0) {
const Events::SendPortActivity ev(context.engine(), context.start(), this);
context.event_sink().write(sizeof(ev), &ev);
}
break;
case DataType::VALUE:
- LV2Object::to_atom(context.engine().world(), ((ObjectBuffer*)buffer(0))->data(), val);
+ LV2Object::to_atom(context.engine().world(), ((ObjectBuffer*)buffer(0).get())->object(), val);
break;
}
diff --git a/src/engine/PortImpl.hpp b/src/engine/PortImpl.hpp
index b9c8dc52..6b8c1b56 100644
--- a/src/engine/PortImpl.hpp
+++ b/src/engine/PortImpl.hpp
@@ -36,6 +36,7 @@ namespace Ingen {
class NodeImpl;
class Buffer;
class ProcessContext;
+class BufferFactory;
/** A port on a Node.
@@ -49,8 +50,6 @@ class ProcessContext;
class PortImpl : public GraphObjectImpl, public Ingen::Shared::Port
{
public:
- virtual ~PortImpl();
-
/** A port's parent is always a node, so static cast should be safe */
NodeImpl* parent_node() const { return (NodeImpl*)_parent; }
@@ -60,7 +59,7 @@ public:
*
* Preprocessor thread, poly is actually applied by apply_poly.
*/
- virtual bool prepare_poly(uint32_t poly);
+ virtual bool prepare_poly(BufferFactory& bufs, uint32_t poly);
/** Apply a new polyphony value.
*
@@ -73,16 +72,10 @@ public:
const Raul::Atom& value() const { return _value; }
void set_value(const Raul::Atom& v) { _value = v; }
- inline Buffer* buffer(uint32_t voice) const {
- Buffer* const buf = _buffers->at(voice);
- if (buf->is_joined()) {
- assert(buf->joined_buffer());
- return buf->joined_buffer();
- } else {
- return buf;
- }
+ inline SharedPtr<Buffer> buffer(uint32_t voice) const {
+ return _buffers->at(voice);
}
- inline Buffer* prepared_buffer(uint32_t voice) const {
+ inline SharedPtr<Buffer> prepared_buffer(uint32_t voice) const {
return _prepared_buffers->at(voice);
}
@@ -105,10 +98,7 @@ public:
return (_type == Shared::DataType::CONTROL) ? 1 : _buffer_size;
}
- virtual void set_buffer_size(size_t size);
-
- void fixed_buffers(bool b) { _fixed_buffers = b; }
- bool fixed_buffers() { return _fixed_buffers; }
+ void set_buffer_size(BufferFactory& factory, size_t size);
void broadcast(bool b) { _broadcast = b; }
bool broadcast() { return _broadcast; }
@@ -121,7 +111,8 @@ public:
void set_context(Context::ID c) { _context = c; }
protected:
- PortImpl(NodeImpl* node,
+ PortImpl(BufferFactory& bufs,
+ NodeImpl* node,
const std::string& name,
uint32_t index,
uint32_t poly,
@@ -129,23 +120,24 @@ protected:
const Raul::Atom& value,
size_t buffer_size);
- virtual void allocate_buffers();
-
+ BufferFactory& _bufs;
uint32_t _index;
uint32_t _poly;
uint32_t _buffer_size;
Shared::DataType _type;
Raul::Atom _value;
- bool _fixed_buffers;
bool _broadcast;
bool _set_by_user;
Raul::Atom _last_broadcasted_value;
- Context::ID _context;
- Raul::Array<Buffer*>* _buffers;
+ Context::ID _context;
+ Raul::Array< SharedPtr<Buffer> >* _buffers;
// Dynamic polyphony
- Raul::Array<Buffer*>* _prepared_buffers;
+ Raul::Array< SharedPtr<Buffer> >* _prepared_buffers;
+
+ friend class Engine;
+ virtual ~PortImpl();
};
diff --git a/src/engine/QueuedEngineInterface.cpp b/src/engine/QueuedEngineInterface.cpp
index 55e02206..d2ff74df 100644
--- a/src/engine/QueuedEngineInterface.cpp
+++ b/src/engine/QueuedEngineInterface.cpp
@@ -158,11 +158,11 @@ QueuedEngineInterface::put(const URI& uri,
bool meta = uri.substr(0, 6) == "meta:#";
URI subject(meta ? (string("path:/") + uri.substr(6)) : uri.str());
- cerr << "ENGINE PUT " << subject << " {" << endl;
+ /*cerr << "ENGINE PUT " << subject << " {" << endl;
typedef Resource::Properties::const_iterator iterator;
for (iterator i = properties.begin(); i != properties.end(); ++i)
cerr << "\t" << i->first << " = " << i->second << " :: " << i->second.type() << endl;
- cerr << "}" << endl;
+ cerr << "}" << endl;*/
push_queued(new Events::SetMetadata(_engine, _responder, now(), this, true, meta, subject, properties));
}
diff --git a/src/engine/events/Connect.cpp b/src/engine/events/Connect.cpp
index 6c7bf2fe..62e32916 100644
--- a/src/engine/events/Connect.cpp
+++ b/src/engine/events/Connect.cpp
@@ -133,7 +133,7 @@ Connect::pre_process()
return;
}
- _connection = SharedPtr<ConnectionImpl>(new ConnectionImpl(_src_port, _dst_port));
+ _connection = SharedPtr<ConnectionImpl>(new ConnectionImpl(*_engine.buffer_factory(), _src_port, _dst_port));
_patch_listnode = new PatchImpl::Connections::Node(_connection);
_port_listnode = new InputPort::Connections::Node(_connection);
diff --git a/src/engine/events/CreateNode.cpp b/src/engine/events/CreateNode.cpp
index 6c70d481..9a9e0826 100644
--- a/src/engine/events/CreateNode.cpp
+++ b/src/engine/events/CreateNode.cpp
@@ -90,7 +90,7 @@ CreateNode::pre_process()
if (_patch && _plugin) {
- _node = _plugin->instantiate(_path.name(), _polyphonic, _patch, _engine);
+ _node = _plugin->instantiate(*_engine.buffer_factory(), _path.name(), _polyphonic, _patch, _engine);
if (_node != NULL) {
_node->properties().insert(_properties.begin(), _properties.end());
diff --git a/src/engine/events/CreatePort.cpp b/src/engine/events/CreatePort.cpp
index 5ea78fb0..848092b1 100644
--- a/src/engine/events/CreatePort.cpp
+++ b/src/engine/events/CreatePort.cpp
@@ -98,7 +98,7 @@ CreatePort::pre_process()
const uint32_t old_num_ports = _patch->num_ports();
- _patch_port = _patch->create_port(_path.name(), _data_type, buffer_size, _is_output);
+ _patch_port = _patch->create_port(*_engine.buffer_factory(), _path.name(), _data_type, buffer_size, _is_output);
if (_patch->parent())
_patch_port->set_property("rdf:instanceOf",
Atom(Atom::URI, _patch_port->meta_uri().str()));
diff --git a/src/engine/events/RequestMetadata.cpp b/src/engine/events/RequestMetadata.cpp
index e6ba7f5d..2ef3edda 100644
--- a/src/engine/events/RequestMetadata.cpp
+++ b/src/engine/events/RequestMetadata.cpp
@@ -95,10 +95,10 @@ RequestMetadata::execute(ProcessContext& context)
PortImpl* port = dynamic_cast<PortImpl*>(_resource);
if (port) {
if (port->type() == DataType::CONTROL || port->type() == DataType::AUDIO)
- _value = ((AudioBuffer*)port->buffer(0))->value_at(0); // TODO: offset
+ _value = ((AudioBuffer*)port->buffer(0).get())->value_at(0); // TODO: offset
else if (port->type() == DataType::VALUE)
LV2Object::to_atom(context.engine().world(),
- ((ObjectBuffer*)port->buffer(0))->data(), _value);
+ ((ObjectBuffer*)port->buffer(0).get())->object(), _value);
} else {
_resource = 0;
}
diff --git a/src/engine/events/SetMetadata.cpp b/src/engine/events/SetMetadata.cpp
index 3d62781d..caed4909 100644
--- a/src/engine/events/SetMetadata.cpp
+++ b/src/engine/events/SetMetadata.cpp
@@ -162,7 +162,7 @@ SetMetadata::pre_process()
} else if (key.str() == "ingen:polyphony") {
if (value.type() == Atom::INT) {
op = POLYPHONY;
- _patch->prepare_internal_poly(value.get_int32());
+ _patch->prepare_internal_poly(*_engine.buffer_factory(), value.get_int32());
} else {
_error = BAD_TYPE;
}
diff --git a/src/engine/events/SetPortValue.cpp b/src/engine/events/SetPortValue.cpp
index 6b9d8d9e..2a33b798 100644
--- a/src/engine/events/SetPortValue.cpp
+++ b/src/engine/events/SetPortValue.cpp
@@ -151,7 +151,7 @@ SetPortValue::apply(Context& context)
/*} else if (_port->buffer(0)->capacity() < _data_size) {
_error = NO_SPACE;*/
} else {
- Buffer* const buf = _port->buffer(0);
+ Buffer* const buf = _port->buffer(0).get();
AudioBuffer* const abuf = dynamic_cast<AudioBuffer*>(buf);
if (abuf) {
if (_value.type() != Atom::FLOAT) {
@@ -160,12 +160,12 @@ SetPortValue::apply(Context& context)
}
if (_omni) {
- for (uint32_t i=0; i < _port->poly(); ++i)
- ((AudioBuffer*)_port->buffer(i))->set_value(
+ for (uint32_t v = 0; v < _port->poly(); ++v)
+ ((AudioBuffer*)_port->buffer(v).get())->set_value(
_value.get_float(), start, _time);
} else {
if (_voice_num < _port->poly())
- ((AudioBuffer*)_port->buffer(_voice_num))->set_value(
+ ((AudioBuffer*)_port->buffer(_voice_num).get())->set_value(
_value.get_float(), start, _time);
else
_error = ILLEGAL_VOICE;
@@ -198,10 +198,10 @@ SetPortValue::apply(Context& context)
ObjectBuffer* const obuf = dynamic_cast<ObjectBuffer*>(buf);
if (obuf) {
- obuf->data()->size = obuf->size() - sizeof(LV2_Object);
- if (LV2Object::from_atom(_engine.world(), _value, obuf->data())) {
- cout << "Converted atom " << _value << " :: " << obuf->data()->type
- << " * " << obuf->data()->size << " @ " << obuf->data() << endl;
+ obuf->object()->size = obuf->size() - sizeof(LV2_Object);
+ if (LV2Object::from_atom(_engine.world(), _value, obuf->object())) {
+ cout << "Converted atom " << _value << " :: " << obuf->object()->type
+ << " * " << obuf->object()->size << " @ " << obuf->object() << endl;
return;
} else {
cerr << "WARNING: Failed to convert atom to LV2 object" << endl;
diff --git a/src/engine/internals/Controller.cpp b/src/engine/internals/Controller.cpp
index 9788206e..3d003a43 100644
--- a/src/engine/internals/Controller.cpp
+++ b/src/engine/internals/Controller.cpp
@@ -38,36 +38,37 @@ using namespace Shared;
static InternalPlugin controller_plugin(NS_INTERNALS "Controller", "controller");
-ControllerNode::ControllerNode(const string& path,
- bool polyphonic,
- PatchImpl* parent,
- SampleRate srate,
- size_t buffer_size)
+ControllerNode::ControllerNode(BufferFactory& bufs,
+ const string& path,
+ bool polyphonic,
+ PatchImpl* parent,
+ SampleRate srate,
+ size_t buffer_size)
: NodeBase(&controller_plugin, path, false, parent, srate, buffer_size)
, _learning(false)
{
_ports = new Raul::Array<PortImpl*>(6);
- _midi_in_port = new InputPort(this, "input", 0, 1, DataType::EVENTS, Raul::Atom(), _buffer_size);
+ _midi_in_port = new InputPort(bufs, this, "input", 0, 1, DataType::EVENTS, Raul::Atom(), _buffer_size);
_ports->at(0) = _midi_in_port;
- _param_port = new InputPort(this, "controller", 1, 1, DataType::CONTROL, 0.0f, 1);
+ _param_port = new InputPort(bufs, this, "controller", 1, 1, DataType::CONTROL, 0.0f, sizeof(Sample));
_param_port->set_property("lv2:minimum", 0.0f);
_param_port->set_property("lv2:maximum", 127.0f);
_param_port->set_property("lv2:integer", true);
_ports->at(1) = _param_port;
- _log_port = new InputPort(this, "logarithmic", 2, 1, DataType::CONTROL, 0.0f, 1);
+ _log_port = new InputPort(bufs, this, "logarithmic", 2, 1, DataType::CONTROL, 0.0f, sizeof(Sample));
_log_port->set_property("lv2:toggled", true);
_ports->at(2) = _log_port;
- _min_port = new InputPort(this, "minimum", 3, 1, DataType::CONTROL, 0.0f, 1);
+ _min_port = new InputPort(bufs, this, "minimum", 3, 1, DataType::CONTROL, 0.0f, sizeof(Sample));
_ports->at(3) = _min_port;
- _max_port = new InputPort(this, "maximum", 4, 1, DataType::CONTROL, 1.0f, 1);
+ _max_port = new InputPort(bufs, this, "maximum", 4, 1, DataType::CONTROL, 1.0f, sizeof(Sample));
_ports->at(4) = _max_port;
- _audio_port = new OutputPort(this, "ar_output", 5, 1, DataType::AUDIO, 0.0f, _buffer_size);
+ _audio_port = new OutputPort(bufs, this, "ar_output", 5, 1, DataType::AUDIO, 0.0f, _buffer_size);
_ports->at(5) = _audio_port;
}
@@ -83,7 +84,7 @@ ControllerNode::process(ProcessContext& context)
uint16_t size = 0;
uint8_t* buf = NULL;
- EventBuffer* const midi_in = (EventBuffer*)_midi_in_port->buffer(0);
+ EventBuffer* const midi_in = (EventBuffer*)_midi_in_port->buffer(0).get();
midi_in->rewind();
@@ -110,15 +111,15 @@ ControllerNode::control(ProcessContext& context, uint8_t control_num, uint8_t va
if (_learning) {
_param_port->set_value(control_num);
- ((AudioBuffer*)_param_port->buffer(0))->set_value(
+ ((AudioBuffer*)_param_port->buffer(0).get())->set_value(
(float)control_num, context.start(), context.end());
_param_port->broadcast_value(context, true);
_learning = false;
}
- const Sample min_port_val = ((AudioBuffer*)_min_port->buffer(0))->value_at(0);
- const Sample max_port_val = ((AudioBuffer*)_max_port->buffer(0))->value_at(0);
- const Sample log_port_val = ((AudioBuffer*)_log_port->buffer(0))->value_at(0);
+ const Sample min_port_val = ((AudioBuffer*)_min_port->buffer(0).get())->value_at(0);
+ const Sample max_port_val = ((AudioBuffer*)_max_port->buffer(0).get())->value_at(0);
+ const Sample log_port_val = ((AudioBuffer*)_log_port->buffer(0).get())->value_at(0);
if (log_port_val > 0.0f) {
// haaaaack, stupid negatives and logarithms
@@ -132,8 +133,8 @@ ControllerNode::control(ProcessContext& context, uint8_t control_num, uint8_t va
scaled_value = ((nval) * (max_port_val - min_port_val)) + min_port_val;
}
- if (control_num == ((AudioBuffer*)_param_port->buffer(0))->value_at(0))
- ((AudioBuffer*)_audio_port->buffer(0))->set_value(scaled_value, context.start(), time);
+ if (control_num == ((AudioBuffer*)_param_port->buffer(0).get())->value_at(0))
+ ((AudioBuffer*)_audio_port->buffer(0).get())->set_value(scaled_value, context.start(), time);
}
diff --git a/src/engine/internals/Controller.hpp b/src/engine/internals/Controller.hpp
index 4f02a9ca..bca26ed5 100644
--- a/src/engine/internals/Controller.hpp
+++ b/src/engine/internals/Controller.hpp
@@ -39,7 +39,7 @@ namespace Internals {
class ControllerNode : public NodeBase
{
public:
- ControllerNode(const std::string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size);
+ ControllerNode(BufferFactory& bufs, const std::string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size);
void process(ProcessContext& context);
diff --git a/src/engine/internals/Note.cpp b/src/engine/internals/Note.cpp
index 4dc11891..ffe9ceca 100644
--- a/src/engine/internals/Note.cpp
+++ b/src/engine/internals/Note.cpp
@@ -40,7 +40,7 @@ using namespace Shared;
static InternalPlugin note_plugin(NS_INTERNALS "Note", "note");
-NoteNode::NoteNode(const string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size)
+NoteNode::NoteNode(BufferFactory& bufs, const string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size)
: NodeBase(&note_plugin, path, polyphonic, parent, srate, buffer_size)
, _voices(new Raul::Array<Voice>(_polyphony))
, _prepared_voices(NULL)
@@ -48,22 +48,22 @@ NoteNode::NoteNode(const string& path, bool polyphonic, PatchImpl* parent, Sampl
{
_ports = new Raul::Array<PortImpl*>(5);
- _midi_in_port = new InputPort(this, "input", 0, 1, DataType::EVENTS, Raul::Atom(), _buffer_size);
+ _midi_in_port = new InputPort(bufs, this, "input", 0, 1, DataType::EVENTS, Raul::Atom(), _buffer_size);
_ports->at(0) = _midi_in_port;
- _freq_port = new OutputPort(this, "frequency", 1, _polyphony, DataType::AUDIO, 440.0f, _buffer_size);
+ _freq_port = new OutputPort(bufs, this, "frequency", 1, _polyphony, DataType::AUDIO, 440.0f, _buffer_size);
_ports->at(1) = _freq_port;
- _vel_port = new OutputPort(this, "velocity", 2, _polyphony, DataType::AUDIO, 0.0f, _buffer_size);
+ _vel_port = new OutputPort(bufs, this, "velocity", 2, _polyphony, DataType::AUDIO, 0.0f, _buffer_size);
_vel_port->set_property("lv2:minimum", 0.0f);
_vel_port->set_property("lv2:maximum", 1.0f);
_ports->at(2) = _vel_port;
- _gate_port = new OutputPort(this, "gate", 3, _polyphony, DataType::AUDIO, 0.0f, _buffer_size);
+ _gate_port = new OutputPort(bufs, this, "gate", 3, _polyphony, DataType::AUDIO, 0.0f, _buffer_size);
_gate_port->set_property("lv2:toggled", true);
_ports->at(3) = _gate_port;
- _trig_port = new OutputPort(this, "trigger", 4, _polyphony, DataType::AUDIO, 0.0f, _buffer_size);
+ _trig_port = new OutputPort(bufs, this, "trigger", 4, _polyphony, DataType::AUDIO, 0.0f, _buffer_size);
_trig_port->set_property("lv2:toggled", true);
_ports->at(4) = _trig_port;
}
@@ -76,12 +76,12 @@ NoteNode::~NoteNode()
bool
-NoteNode::prepare_poly(uint32_t poly)
+NoteNode::prepare_poly(BufferFactory& bufs, uint32_t poly)
{
if (!_polyphonic)
return true;
- NodeBase::prepare_poly(poly);
+ NodeBase::prepare_poly(bufs, poly);
if (_prepared_voices && poly <= _prepared_voices->size())
return true;
@@ -117,7 +117,7 @@ NoteNode::apply_poly(Raul::Maid& maid, uint32_t poly)
void
NoteNode::process(ProcessContext& context)
{
- EventBuffer* const midi_in = (EventBuffer*)_midi_in_port->buffer(0);
+ EventBuffer* const midi_in = (EventBuffer*)_midi_in_port->buffer(0).get();
NodeBase::pre_process(context);
uint32_t frames = 0;
@@ -248,13 +248,18 @@ NoteNode::note_on(ProcessContext& context, uint8_t note_num, uint8_t velocity, F
assert(_keys[voice->note].state == Key::Key::ON_ASSIGNED);
assert(_keys[voice->note].voice == voice_num);
- ((AudioBuffer*)_freq_port->buffer(voice_num))->set_value(note_to_freq(note_num), context.start(), time);
- ((AudioBuffer*)_vel_port->buffer(voice_num))->set_value(velocity/127.0, context.start(), time);
- ((AudioBuffer*)_gate_port->buffer(voice_num))->set_value(1.0f, context.start(), time);
+ ((AudioBuffer*)_freq_port->buffer(voice_num).get())->set_value(
+ note_to_freq(note_num), context.start(), time);
+ ((AudioBuffer*)_vel_port->buffer(voice_num).get())->set_value(
+ velocity/127.0, context.start(), time);
+ ((AudioBuffer*)_gate_port->buffer(voice_num).get())->set_value(
+ 1.0f, context.start(), time);
// trigger (one sample)
- ((AudioBuffer*)_trig_port->buffer(voice_num))->set_value(1.0f, context.start(), time);
- ((AudioBuffer*)_trig_port->buffer(voice_num))->set_value(0.0f, context.start(), time + 1);
+ ((AudioBuffer*)_trig_port->buffer(voice_num).get())->set_value(
+ 1.0f, context.start(), time);
+ ((AudioBuffer*)_trig_port->buffer(voice_num).get())->set_value(
+ 0.0f, context.start(), time + 1);
assert(key->state == Key::Key::ON_ASSIGNED);
assert(voice->state == Voice::Voice::ACTIVE);
@@ -321,7 +326,7 @@ NoteNode::free_voice(ProcessContext& context, uint32_t voice, FrameTime time)
assert(replace_key->state == Key::ON_UNASSIGNED);
// Change the freq but leave the gate high and don't retrigger
- ((AudioBuffer*)_freq_port->buffer(voice))->set_value(note_to_freq(replace_key_num), context.start(), time);
+ ((AudioBuffer*)_freq_port->buffer(voice).get())->set_value(note_to_freq(replace_key_num), context.start(), time);
replace_key->state = Key::ON_ASSIGNED;
replace_key->voice = voice;
@@ -331,7 +336,7 @@ NoteNode::free_voice(ProcessContext& context, uint32_t voice, FrameTime time)
} else {
// No new note for voice, deactivate (set gate low)
//cerr << "[NoteNode] Note off. Key " << (int)note_num << ", Voice " << voice << " Killed" << endl;
- ((AudioBuffer*)_gate_port->buffer(voice))->set_value(0.0f, context.start(), time);
+ ((AudioBuffer*)_gate_port->buffer(voice).get())->set_value(0.0f, context.start(), time);
(*_voices)[voice].state = Voice::FREE;
}
}
@@ -348,7 +353,7 @@ NoteNode::all_notes_off(ProcessContext& context, FrameTime time)
// FIXME: set all keys to Key::OFF?
for (uint32_t i = 0; i < _polyphony; ++i) {
- ((AudioBuffer*)_gate_port->buffer(i))->set_value(0.0f, context.start(), time);
+ ((AudioBuffer*)_gate_port->buffer(i).get())->set_value(0.0f, context.start(), time);
(*_voices)[i].state = Voice::FREE;
}
}
diff --git a/src/engine/internals/Note.hpp b/src/engine/internals/Note.hpp
index d4c4c851..7f091231 100644
--- a/src/engine/internals/Note.hpp
+++ b/src/engine/internals/Note.hpp
@@ -39,10 +39,10 @@ namespace Internals {
class NoteNode : public NodeBase
{
public:
- NoteNode(const std::string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size);
+ NoteNode(BufferFactory& bufs, const std::string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size);
~NoteNode();
- bool prepare_poly(uint32_t poly);
+ bool prepare_poly(BufferFactory& bufs, uint32_t poly);
bool apply_poly(Raul::Maid& maid, uint32_t poly);
void process(ProcessContext& context);
diff --git a/src/engine/internals/Transport.cpp b/src/engine/internals/Transport.cpp
deleted file mode 100644
index 8fccc436..00000000
--- a/src/engine/internals/Transport.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-/* This file is part of Ingen.
- * Copyright (C) 2007-2009 Dave Robillard <http://drobilla.net>
- *
- * Ingen is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option) any later
- * version.
- *
- * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "internals/Transport.hpp"
-#include <jack/transport.h>
-#include "OutputPort.hpp"
-#include "InternalPlugin.hpp"
-#include "JackAudioDriver.hpp"
-#include "PortImpl.hpp"
-#include "util.hpp"
-//#include "Engine.hpp"
-
-using namespace std;
-
-namespace Ingen {
-namespace Internals {
-
-static InternalPlugin transport_plugin(NS_INTERNALS "Transport", "transport");
-
-TransportNode::TransportNode(const string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size)
- : NodeBase(&transport_plugin, path, false, parent, srate, buffer_size)
-{
-#if 0
- _num_ports = 10;
- _ports.alloc(_num_ports);
-
- OutputPort<Sample>* spb_port = new OutputPort<Sample>(this, "Seconds per Beat", 0, 1,
- // new PortInfo("Seconds per Beat", CONTROL, OUTPUT, 0, 0, 1), 1);
- _ports.at(0) = spb_port;
-
- OutputPort<Sample>* bpb_port = new OutputPort<Sample>(this, "Beats per Bar", 1, 1,
- // new PortInfo("Beats per Bar", CONTROL, OUTPUT, 0, 0, 1), 1);
- _ports.at(1) = bpb_port;
-
- OutputPort<Sample>* bar_port = new OutputPort<Sample>(this, "Bar", 3, 1,
-// new PortInfo("Bar", CONTROL, OUTPUT, 0, 0, 1), buffer_size);
- _ports.at(2) = bar_port;
-
- OutputPort<Sample>* beat_port = new OutputPort<Sample>(this, "Beat", 3, 1,
- // new PortInfo("Beat", CONTROL, OUTPUT, 0, 0, 1), buffer_size);
- _ports.at(3) = beat_port;
-
- OutputPort<Sample>* frame_port = new OutputPort<Sample>(this, "Frame", 3, 1,
- // new PortInfo("Frame", CONTROL, OUTPUT, 0, 0, 1), buffer_size);
- _ports.at(4) = frame_port;
-
- OutputPort<Sample>* hour_port = new OutputPort<Sample>(this, "Hour", 3, 1,
- // new PortInfo("Hour", CONTROL, OUTPUT, 0, 0, 1), buffer_size);
- _ports.at(5) = hour_port;
-
- OutputPort<Sample>* minute_port = new OutputPort<Sample>(this, "Minute", 3, 1,
- // new PortInfo("Minute", CONTROL, OUTPUT, 0, 0, 1), buffer_size);
- _ports.at(6) = minute_port;
-
- OutputPort<Sample>* second_port = new OutputPort<Sample>(this, "Second", 3, 1,
- // new PortInfo("Second", CONTROL, OUTPUT, 0, 0, 1), buffer_size);
- _ports.at(7) = second_port;
-
- OutputPort<Sample>* trg_port = new OutputPort<Sample>(this, "Beat Tick", 2, 1,
- // new PortInfo("Beat Tick", AUDIO, OUTPUT, 0, 0, 1), buffer_size);
- _ports.at(8) = trg_port;
-
- OutputPort<Sample>* bar_trig_port = new OutputPort<Sample>(this, "Bar Tick", 3, 1,
- // new PortInfo("Bar Tick", AUDIO, OUTPUT, 0, 0, 1), buffer_size);
- _ports.at(9) = bar_trig_port;
-#endif
-}
-
-
-void
-TransportNode::process(ProcessContext& context)
-{
- NodeBase::pre_process(context);
-#if 0
-
- // FIXME: this will die horribly with any driver other than jack (in theory)
- const jack_position_t* const position = ((JackAudioDriver*)Engine::instance().audio_driver())->position();
- jack_transport_state_t state = ((JackAudioDriver*)Engine::instance().audio_driver())->transport_state();
- double bpm = position->beats_per_minute;
- float bpb = position->beats_per_bar;
- float spb = 60.0 / bpm;
-
- //cerr << "bpm = " << bpm << endl;
- //cerr << "spb = " << spb << endl;
-
- if (position->valid & JackPositionBBT) {
- cerr << "bar: " << position->bar << endl;
- cerr << "beat: " << position->beat << endl;
- cerr << "tick: " << position->tick << endl;
- } else {
- cerr << "No BBT" << endl;
- }
-
- if (position->valid & JackBBTFrameOffset) {
- cerr << "bbt_offset: " << position->bbt_offset << endl;
- } else {
- cerr << "No BBT offset" << endl;
- }
-
- if (position->valid & JackPositionTimecode) {
- double time = position->frame_time;
- cerr << "Seconds: " << time << " : " << endl;
- /*time /= 60.0;
- cerr << "Minutes: " << time << " : ";
- time /= 60.0;
- cerr << "Hours: " << time << " : ";*/
- } else {
- cerr << "No timecode." << endl;
- }
-
-
- ((OutputPort<Sample>*)_ports.at(0))->buffer(0)->set(spb, 0, 0);
- ((OutputPort<Sample>*)_ports.at(1))->buffer(0)->set(bpb, 0, 0);
-
- // fill the trigger buffers with zeros
- ((OutputPort<Sample>*)_ports.at(2))->buffer(0)->set(0.0f, 0, nframes - 1);
- ((OutputPort<Sample>*)_ports.at(3))->buffer(0)->set(0.0f, 0, nframes - 1);
-
- // if the transport is rolling, add triggers at the right frame positions
- if ((position->valid & JackTransportBBT) && (state == JackTransportRolling)) {
- double frames_per_beat = position->frame_rate * spb;
- double first_beat = (1.0f - position->tick / position->ticks_per_beat) * frames_per_beat;
- int first_beat_no = position->beat;
- if (first_beat >= frames_per_beat) {
- first_beat -= frames_per_beat;
- --first_beat_no;
- }
- for ( ; first_beat < nframes; first_beat += frames_per_beat) {
- ((OutputPort<Sample>*)_ports.at(2))->buffer(0)->set(1.0f, size_t(first_beat));
- if (first_beat_no % int(bpb) == 0) {
- ((OutputPort<Sample>*)_ports.at(3))->buffer(0)->set(1.0f, size_t(first_beat));
- ++first_beat_no;
- }
- }
- }
- #endif
-
- NodeBase::post_process(context);
-}
-
-
-} // namespace Ingen
-} // namespace Internals
-
diff --git a/src/engine/internals/Transport.hpp b/src/engine/internals/Transport.hpp
deleted file mode 100644
index 78e12f4f..00000000
--- a/src/engine/internals/Transport.hpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/* This file is part of Ingen.
- * Copyright (C) 2007-2009 Dave Robillard <http://drobilla.net>
- *
- * Ingen is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option) any later
- * version.
- *
- * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef TRANSPORTNODE_H
-#define TRANSPORTNODE_H
-
-#include <string>
-#include <jack/transport.h>
-#include "NodeBase.hpp"
-
-namespace Ingen {
-namespace Internals {
-
-
-/** Transport Node, brings timing information into patches.
- *
- * This node uses the Jack transport API to get information about BPM, time
- * signature, etc.. all sample accurate. Using this you can do
- * tempo-synced effects or even synthesis, etc.
- */
-class TransportNode : public NodeBase
-{
-public:
- TransportNode(const std::string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size);
-
- virtual void process(ProcessContext& context);
-};
-
-
-} // namespace Ingen
-} // namespace Internals
-
-#endif // TRANSPORTNODE_H
diff --git a/src/engine/internals/Trigger.cpp b/src/engine/internals/Trigger.cpp
index 428a1b8f..15251f88 100644
--- a/src/engine/internals/Trigger.cpp
+++ b/src/engine/internals/Trigger.cpp
@@ -35,30 +35,30 @@ using namespace Shared;
static InternalPlugin trigger_plugin(NS_INTERNALS "Trigger", "trigger");
-TriggerNode::TriggerNode(const string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size)
+TriggerNode::TriggerNode(BufferFactory& bufs, const string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size)
: NodeBase(&trigger_plugin, path, false, parent, srate, buffer_size)
, _learning(false)
{
_ports = new Raul::Array<PortImpl*>(5);
- _midi_in_port = new InputPort(this, "input", 0, 1, DataType::EVENTS, Raul::Atom(), _buffer_size);
+ _midi_in_port = new InputPort(bufs, this, "input", 0, 1, DataType::EVENTS, Raul::Atom(), _buffer_size);
_ports->at(0) = _midi_in_port;
- _note_port = new InputPort(this, "note", 1, 1, DataType::CONTROL, 60.0f, 1);
+ _note_port = new InputPort(bufs, this, "note", 1, 1, DataType::CONTROL, 60.0f, sizeof(Sample));
_note_port->set_property("lv2:minimum", 0.0f);
_note_port->set_property("lv2:maximum", 127.0f);
_note_port->set_property("lv2:integer", true);
_ports->at(1) = _note_port;
- _gate_port = new OutputPort(this, "gate", 2, 1, DataType::AUDIO, 0.0f, _buffer_size);
+ _gate_port = new OutputPort(bufs, this, "gate", 2, 1, DataType::AUDIO, 0.0f, _buffer_size);
_gate_port->set_property("lv2:toggled", true);
_ports->at(2) = _gate_port;
- _trig_port = new OutputPort(this, "trigger", 3, 1, DataType::AUDIO, 0.0f, _buffer_size);
+ _trig_port = new OutputPort(bufs, this, "trigger", 3, 1, DataType::AUDIO, 0.0f, _buffer_size);
_trig_port->set_property("lv2:toggled", true);
_ports->at(3) = _trig_port;
- _vel_port = new OutputPort(this, "velocity", 4, 1, DataType::AUDIO, 0.0f, _buffer_size);
+ _vel_port = new OutputPort(bufs, this, "velocity", 4, 1, DataType::AUDIO, 0.0f, _buffer_size);
_vel_port->set_property("lv2:minimum", 0.0f);
_vel_port->set_property("lv2:maximum", 1.0f);
_ports->at(4) = _vel_port;
@@ -76,7 +76,7 @@ TriggerNode::process(ProcessContext& context)
uint16_t size = 0;
uint8_t* buf = NULL;
- EventBuffer* const midi_in = (EventBuffer*)_midi_in_port->buffer(0);
+ EventBuffer* const midi_in = (EventBuffer*)_midi_in_port->buffer(0).get();
midi_in->rewind();
@@ -97,7 +97,7 @@ TriggerNode::process(ProcessContext& context)
case MIDI_CMD_CONTROL:
if (buf[1] == MIDI_CTL_ALL_NOTES_OFF
|| buf[1] == MIDI_CTL_ALL_SOUNDS_OFF)
- ((AudioBuffer*)_gate_port->buffer(0))->set_value(0.0f, context.start(), time);
+ ((AudioBuffer*)_gate_port->buffer(0).get())->set_value(0.0f, context.start(), time);
default:
break;
}
@@ -118,7 +118,7 @@ TriggerNode::note_on(ProcessContext& context, uint8_t note_num, uint8_t velocity
if (_learning) {
_note_port->set_value(note_num);
- ((AudioBuffer*)_note_port->buffer(0))->set_value(
+ ((AudioBuffer*)_note_port->buffer(0).get())->set_value(
(float)note_num, context.start(), context.end());
_note_port->broadcast_value(context, true);
_learning = false;
@@ -126,13 +126,13 @@ TriggerNode::note_on(ProcessContext& context, uint8_t note_num, uint8_t velocity
/*cerr << "[TriggerNode] " << path() << " Note " << (int)note_num << " on @ " << time << endl;*/
- Sample filter_note = ((AudioBuffer*)_note_port->buffer(0))->value_at(0);
+ Sample filter_note = ((AudioBuffer*)_note_port->buffer(0).get())->value_at(0);
if (filter_note >= 0.0 && filter_note < 127.0 && (note_num == (uint8_t)filter_note)) {
- ((AudioBuffer*)_gate_port->buffer(0))->set_value(1.0f, context.start(), time);
- ((AudioBuffer*)_trig_port->buffer(0))->set_value(1.0f, context.start(), time);
- ((AudioBuffer*)_trig_port->buffer(0))->set_value(0.0f, context.start(), time + 1);
- ((AudioBuffer*)_vel_port->buffer(0))->set_value(velocity / 127.0f, context.start(), time);
- assert(((AudioBuffer*)_trig_port->buffer(0))->data()[time - context.start()] == 1.0f);
+ ((AudioBuffer*)_gate_port->buffer(0).get())->set_value(1.0f, context.start(), time);
+ ((AudioBuffer*)_trig_port->buffer(0).get())->set_value(1.0f, context.start(), time);
+ ((AudioBuffer*)_trig_port->buffer(0).get())->set_value(0.0f, context.start(), time + 1);
+ ((AudioBuffer*)_vel_port->buffer(0).get())->set_value(velocity / 127.0f, context.start(), time);
+ assert(((AudioBuffer*)_trig_port->buffer(0).get())->data()[time - context.start()] == 1.0f);
}
}
@@ -143,8 +143,8 @@ TriggerNode::note_off(ProcessContext& context, uint8_t note_num, FrameTime time)
assert(time >= context.start() && time <= context.end());
assert(time - context.start() < _buffer_size);
- if (note_num == lrintf(((AudioBuffer*)_note_port->buffer(0))->value_at(0)))
- ((AudioBuffer*)_gate_port->buffer(0))->set_value(0.0f, context.start(), time);
+ if (note_num == lrintf(((AudioBuffer*)_note_port->buffer(0).get())->value_at(0)))
+ ((AudioBuffer*)_gate_port->buffer(0).get())->set_value(0.0f, context.start(), time);
}
diff --git a/src/engine/internals/Trigger.hpp b/src/engine/internals/Trigger.hpp
index dfb4f899..84281ac7 100644
--- a/src/engine/internals/Trigger.hpp
+++ b/src/engine/internals/Trigger.hpp
@@ -42,7 +42,7 @@ namespace Internals {
class TriggerNode : public NodeBase
{
public:
- TriggerNode(const std::string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size);
+ TriggerNode(BufferFactory& bufs, const std::string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size);
void process(ProcessContext& context);
diff --git a/src/engine/wscript b/src/engine/wscript
index 232fb281..faee5517 100644
--- a/src/engine/wscript
+++ b/src/engine/wscript
@@ -4,7 +4,7 @@ import autowaf
def build(bld):
core_source = '''
AudioBuffer.cpp
- Buffer.cpp
+ BufferFactory.cpp
ClientBroadcaster.cpp
ConnectionImpl.cpp
DuplexPort.cpp
@@ -34,7 +34,6 @@ def build(bld):
ingen_engine.cpp
internals/Controller.cpp
internals/Note.cpp
- internals/Transport.cpp
internals/Trigger.cpp
'''
diff --git a/src/shared/LV2URIMap.cpp b/src/shared/LV2URIMap.cpp
index 65e3aa30..e401f6cb 100644
--- a/src/shared/LV2URIMap.cpp
+++ b/src/shared/LV2URIMap.cpp
@@ -35,6 +35,7 @@ LV2URIMap::LV2URIMap()
, object_class_string(uri_to_id(NULL, LV2_OBJECT_URI "#String"))
, object_class_int32(uri_to_id(NULL, LV2_OBJECT_URI "#Int32"))
, object_class_float32(uri_to_id(NULL, LV2_OBJECT_URI "#Float32"))
+ , object_class_vector(uri_to_id(NULL, LV2_OBJECT_URI "#Vector"))
, ui_format_events(uri_to_id(NULL, "http://lv2plug.in/ns/extensions/ui#Events"))
, midi_event(uri_to_id(NULL, "http://lv2plug.in/ns/ext/midi#MidiEvent"))
, string_transfer(uri_to_id(NULL, "http://lv2plug.in/ns/dev/string-port#StringTransfer"))
diff --git a/src/shared/LV2URIMap.hpp b/src/shared/LV2URIMap.hpp
index 0dd6b0cb..30823ef0 100644
--- a/src/shared/LV2URIMap.hpp
+++ b/src/shared/LV2URIMap.hpp
@@ -63,6 +63,7 @@ public:
const uint32_t object_class_string;
const uint32_t object_class_int32;
const uint32_t object_class_float32;
+ const uint32_t object_class_vector;
const uint32_t ui_format_events;
const uint32_t midi_event;
const uint32_t string_transfer;