summaryrefslogtreecommitdiffstats
path: root/src/engine/EventBuffer.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2010-01-04 20:59:01 +0000
committerDavid Robillard <d@drobilla.net>2010-01-04 20:59:01 +0000
commitbfca1f3a2739c1c0148b0641d3bdb8f4ea16b431 (patch)
tree39ca3cffc0e404fe33fac66663444d9e1a603b96 /src/engine/EventBuffer.cpp
parent29b77e922d7fd883795b04eadd528eca21a37a2f (diff)
downloadingen-bfca1f3a2739c1c0148b0641d3bdb8f4ea16b431.tar.gz
ingen-bfca1f3a2739c1c0148b0641d3bdb8f4ea16b431.tar.bz2
ingen-bfca1f3a2739c1c0148b0641d3bdb8f4ea16b431.zip
Remove redundant LV2EventBuffer class and merge with EventBuffer.
Refactor mixing from an in-place Buffer method (which doesn't work with EventBuffer) to a single function that takes an out of place destination and an array of sources. Fix audio buffer mixing for control<->audio. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@2333 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/engine/EventBuffer.cpp')
-rw-r--r--src/engine/EventBuffer.cpp224
1 files changed, 172 insertions, 52 deletions
diff --git a/src/engine/EventBuffer.cpp b/src/engine/EventBuffer.cpp
index 8d3769a6..24ed4be9 100644
--- a/src/engine/EventBuffer.cpp
+++ b/src/engine/EventBuffer.cpp
@@ -35,11 +35,40 @@ using namespace Shared;
*/
EventBuffer::EventBuffer(size_t capacity)
: Buffer(PortType(PortType::EVENTS), capacity)
- , _buf(new LV2EventBuffer(capacity))
+ , _latest_frames(0)
+ , _latest_subframes(0)
{
+ if (capacity > UINT32_MAX) {
+ cerr << "Event buffer size " << capacity << " too large, aborting." << endl;
+ throw std::bad_alloc();
+ }
+
+#ifdef HAVE_POSIX_MEMALIGN
+ int ret = posix_memalign((void**)&_data, 16, sizeof(LV2_Event_Buffer) + capacity);
+#else
+ _data = (LV2_Event_Buffer*)malloc(sizeof(LV2_Event_Buffer) + capacity);
+ int ret = (_data != NULL) ? 0 : -1;
+#endif
+
+ if (ret != 0) {
+ cerr << "Failed to allocate event buffer. Aborting." << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ _data->header_size = sizeof(LV2_Event_Buffer);
+ _data->data = reinterpret_cast<uint8_t*>(_data + _data->header_size);
+ _data->stamp_type = 0;
+ _data->event_count = 0;
+ _data->capacity = (uint32_t)capacity;
+ _data->size = 0;
+
clear();
+}
- //cerr << "Creating Event Buffer " << _buf << ", capacity = " << _buf->capacity << endl;
+
+EventBuffer::~EventBuffer()
+{
+ free(_data);
}
@@ -61,82 +90,173 @@ void
EventBuffer::copy(Context& context, const Buffer* src_buf)
{
const EventBuffer* src = dynamic_cast<const EventBuffer*>(src_buf);
- assert(src);
- assert(_buf->capacity() >= src->_buf->capacity());
- assert(src != this);
- assert(src->_buf != _buf);
+ if (src->_data == _data)
+ return;
+
+ assert(capacity() >= src->capacity());
+
+ rewind();
+
+ assert(src->_data->header_size == _data->header_size);
+ memcpy(_data, src->_data, _data->header_size + src->_data->size);
- src->rewind();
+ _iter = src->_iter;
+ _iter.buf = _data;
+
+ _latest_frames = src->_latest_frames;
+ _latest_subframes = src->_latest_subframes;
- _buf->copy(*src->_buf);
assert(event_count() == src->event_count());
}
-void
-EventBuffer::mix(Context& context, const Buffer* src)
+/** Increment the read position by one event.
+ *
+ * \return true if increment was successful, or false if end of buffer reached.
+ */
+bool
+EventBuffer::increment() const
+{
+ if (lv2_event_is_valid(&_iter)) {
+ lv2_event_increment(&_iter);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+/** \return true iff the cursor is valid (ie get_event is safe)
+ */
+bool
+EventBuffer::is_valid() const
+{
+ return lv2_event_is_valid(&_iter);
+}
+
+
+/** Read an event from the current position in the buffer
+ *
+ * \return true if read was successful, or false if end of buffer reached
+ */
+bool
+EventBuffer::get_event(uint32_t* frames,
+ uint32_t* subframes,
+ uint16_t* type,
+ uint16_t* size,
+ uint8_t** data) const
+{
+ if (lv2_event_is_valid(&_iter)) {
+ LV2_Event* ev = lv2_event_get(&_iter, data);
+ *frames = ev->frames;
+ *subframes = ev->subframes;
+ *type = ev->type;
+ *size = ev->size;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+/** Get the object currently pointed to, or NULL if invalid.
+ */
+LV2_Object*
+EventBuffer::get_object() const
{
+ if (lv2_event_is_valid(&_iter)) {
+ uint8_t* data;
+ LV2_Event* ev = lv2_event_get(&_iter, &data);
+ return LV2_OBJECT_FROM_EVENT(ev);
+ }
+ return NULL;
+}
+
+
+/** Get the event currently pointed to, or NULL if invalid.
+ */
+LV2_Event*
+EventBuffer::get_event() const
+{
+ if (lv2_event_is_valid(&_iter)) {
+ uint8_t* data;
+ return lv2_event_get(&_iter, &data);
+ }
+ return NULL;
}
-/** Clear, and merge \a a and \a b into this buffer.
+/** Append an event to the buffer.
*
- * FIXME: This is slow.
+ * \a timestamp must be >= the latest event in the buffer.
*
- * \return true if complete merge was successful
+ * \return true on success
*/
bool
-EventBuffer::merge(const EventBuffer& a, const EventBuffer& b)
+EventBuffer::append(uint32_t frames,
+ uint32_t subframes,
+ uint16_t type,
+ uint16_t size,
+ const uint8_t* data)
{
- // Die if a merge isn't necessary as it's expensive
- assert(a.size() > 0 && b.size() > 0);
+#ifndef NDEBUG
+ if (lv2_event_is_valid(&_iter)) {
+ LV2_Event* last_event = lv2_event_get(&_iter, NULL);
+ assert(last_event->frames < frames
+ || (last_event->frames == frames && last_event->subframes <= subframes));
+ }
+#endif
- clear();
+ /*cout << "Appending event type " << type << ", size " << size
+ << " @ " << frames << "." << subframes << endl;*/
+
+ if (!lv2_event_write(&_iter, frames, subframes, type, size, data)) {
+ cerr << "ERROR: Failed to write event." << endl;
+ return false;
+ } else {
+ _latest_frames = frames;
+ _latest_subframes = subframes;
+ return true;
+ }
+}
- a.rewind();
- b.rewind();
+/** Append a buffer of events to the buffer.
+ *
+ * \a timestamp must be >= the latest event in the buffer.
+ *
+ * \return true on success
+ */
+bool
+EventBuffer::append(const EventBuffer* buf)
+{
+ cerr << "FIXME: EventBuffer append" << endl;
#if 0
- uint32_t a_frames;
- uint32_t a_subframes;
- uint16_t a_type;
- uint16_t a_size;
- uint8_t* a_data;
-
- uint32_t b_frames;
- uint32_t b_subframes;
- uint16_t b_type;
- uint16_t b_size;
- uint8_t* b_data;
+ uint8_t** data = NULL;
+ bool ret = true;
+
+ LV2_Event_Iterator iter;
+ for (lv2_event_begin(&iter, _data); lv2_event_is_valid(&iter); lv2_event_increment(&iter)) {
+ LV2_Event* ev = lv2_event_get(&iter, data);
+
+#ifndef NDEBUG
+ assert((ev->frames > _latest_frames)
+ || (ev->frames == _latest_frames
+ && ev->subframes >= _latest_subframes));
#endif
- cout << "FIXME: merge" << endl;
-#if 0
- a.get_event(&a_frames, &a_subframes, &a_type, &a_size, &a_data);
- b.get_event(&b_frames, &b_subframes, &b_type, &b_size, &b_data);
-
- while (true) {
- if (a_data && (!b_data || (a_time < b_time))) {
- append(a_time, a_size, a_data);
- if (a.increment())
- a.get_event(&a_time, &a_size, &a_data);
- else
- a_data = NULL;
- } else if (b_data) {
- append(b_time, b_size, b_data);
- if (b.increment())
- b.get_event(&b_time, &b_size, &b_data);
- else
- b_data = NULL;
- } else {
+ if (!(ret = append(ev->frames, ev->subframes, ev->type, ev->size, *data))) {
+ cerr << "ERROR: Failed to write event." << endl;
break;
}
+
+ _latest_frames = ev->frames;
+ _latest_subframes = ev->subframes;
}
- _latest_stamp = max(a_time, b_time);
+ return ret;
#endif
-
- return true;
+ return false;
}