From 772bdee6ee56a2655a96429aec87589371ea263b Mon Sep 17 00:00:00 2001
From: David Robillard <d@drobilla.net>
Date: Mon, 7 Nov 2011 23:13:46 +0000
Subject: Implement atom buffer.

git-svn-id: http://svn.drobilla.net/lad/trunk/jalv@3606 a436a847-0d15-0410-975c-d299462d15a1
---
 src/jalv.c          |  35 +++++----
 src/jalv_internal.h |   2 +
 src/lv2_evbuf.c     | 201 +++++++++++++++++++++++++++++++++++++---------------
 src/lv2_evbuf.h     |  35 +++++----
 4 files changed, 185 insertions(+), 88 deletions(-)

(limited to 'src')

diff --git a/src/jalv.c b/src/jalv.c
index e927ee2..49fd8ba 100644
--- a/src/jalv.c
+++ b/src/jalv.c
@@ -42,6 +42,8 @@
 
 #include "lv2_evbuf.h"
 
+#define NS_ATOM "http://lv2plug.in/ns/ext/atom#"
+
 sem_t exit_sem;  /**< Exit semaphore */
 
 /**
@@ -101,12 +103,12 @@ lv2_ui_resize(LV2_UI_Resize_Feature_Data data, int width, int height)
 LV2_UI_Resize_Feature    ui_resize         = { NULL, &lv2_ui_resize };
 static const LV2_Feature ui_resize_feature = { NS_EXT "ui-resize#UIResize", &ui_resize };
 
-const LV2_Feature* features[4] = {
-	&uri_map_feature, &instance_feature, &ui_resize_feature
+const LV2_Feature* features[5] = {
+	&uri_map_feature, &mapper_feature, &instance_feature, &ui_resize_feature
 };
 #else
-const LV2_Feature* features[3] = {
-	&uri_map_feature, &instance_feature, NULL
+const LV2_Feature* features[4] = {
+	&uri_map_feature, &mapper_feature, &instance_feature, NULL
 };
 #endif
 
@@ -161,6 +163,10 @@ create_port(Jalv*    host,
 		port->type = TYPE_AUDIO;
 	} else if (lilv_port_is_a(host->plugin, port->lilv_port, host->event_class)) {
 		port->type = TYPE_EVENT;
+		port->old_api = true;
+	} else if (lilv_port_is_a(host->plugin, port->lilv_port, host->aevent_class)) {
+		port->type = TYPE_EVENT;
+		port->old_api = false;
 	} else if (!optional) {
 		die("Mandatory port has unknown type (neither control nor audio nor event)");
 	}
@@ -199,7 +205,9 @@ jalv_allocate_port_buffers(Jalv* jalv)
 		switch (port->type) {
 		case TYPE_EVENT:
 			lv2_evbuf_free(port->evbuf);
-			port->evbuf = lv2_evbuf_new(jalv->midi_buf_size);
+			port->evbuf = lv2_evbuf_new(
+				jalv->midi_buf_size,
+				port->old_api ? LV2_EVBUF_EVENT : LV2_EVBUF_ATOM);
 			lilv_instance_connect_port(
 				jalv->instance, i, lv2_evbuf_get_buffer(port->evbuf));
 		default: break;
@@ -207,7 +215,6 @@ jalv_allocate_port_buffers(Jalv* jalv)
 	}
 }
 
-
 /**
    Get a port structure by symbol.
 
@@ -311,9 +318,7 @@ jack_process_cb(jack_nframes_t nframes, void* data)
 				void* buf = jack_port_get_buffer(host->ports[p].jack_port,
 				                                 nframes);
 
-				LV2_Evbuf_Iterator iter;
-				lv2_evbuf_begin(&iter, host->ports[p].evbuf);
-
+				LV2_Evbuf_Iterator iter = lv2_evbuf_begin(host->ports[p].evbuf);
 				for (uint32_t i = 0; i < jack_midi_get_event_count(buf); ++i) {
 					jack_midi_event_t ev;
 					jack_midi_event_get(&ev, buf, i);
@@ -358,17 +363,15 @@ jack_process_cb(jack_nframes_t nframes, void* data)
 
 			jack_midi_clear_buffer(buf);
 
-			LV2_Evbuf_Iterator iter;
-			lv2_evbuf_begin(&iter, host->ports[p].evbuf);
-
-			const uint32_t event_count = lv2_evbuf_get_event_count(iter.evbuf);
+			LV2_Evbuf_Iterator iter        = lv2_evbuf_begin(host->ports[p].evbuf);
+			const uint32_t     event_count = lv2_evbuf_get_event_count(iter.evbuf);
 			for (uint32_t i = 0; i < event_count; ++i) {
 				uint32_t frames, subframes, type, size;
 				uint8_t* data;
-				lv2_evbuf_get(&iter, &frames, &subframes,
+				lv2_evbuf_get(iter, &frames, &subframes,
 				              &type, &size, &data);
 				jack_midi_event_write(buf, frames, data, size);
-				lv2_evbuf_increment(&iter);
+				iter = lv2_evbuf_next(iter);
 			}
 		} else if (send_ui_updates
 		           && !host->ports[p].flow == FLOW_INPUT
@@ -465,6 +468,7 @@ main(int argc, char** argv)
 
 	host.symap = symap_new();
 	uri_map.callback_data = &host;
+	mapper.handle = &host;
 	host.midi_event_id = uri_to_id(&host,
 	                               "http://lv2plug.in/ns/ext/event",
 	                               "http://lv2plug.in/ns/ext/midi#MidiEvent");
@@ -493,6 +497,7 @@ main(int argc, char** argv)
 	host.control_class = lilv_new_uri(world, LILV_URI_CONTROL_PORT);
 	host.audio_class   = lilv_new_uri(world, LILV_URI_AUDIO_PORT);
 	host.event_class   = lilv_new_uri(world, LILV_URI_EVENT_PORT);
+	host.aevent_class  = lilv_new_uri(world, NS_ATOM "EventPort");
 	host.midi_class    = lilv_new_uri(world, LILV_URI_MIDI_EVENT);
 	host.optional      = lilv_new_uri(world, LILV_NS_LV2
 	                                  "connectionOptional");
diff --git a/src/jalv_internal.h b/src/jalv_internal.h
index c171b72..e2f5dd5 100644
--- a/src/jalv_internal.h
+++ b/src/jalv_internal.h
@@ -57,6 +57,7 @@ struct Port {
 	jack_port_t*      jack_port;  /**< For audio/MIDI ports, otherwise NULL */
 	float             control;    /**< For control ports, otherwise 0.0f */
 	LV2_Evbuf*        evbuf;      /**< For MIDI ports, otherwise NULL */
+	bool              old_api;    /**< True for event, false for atom */
 };
 
 struct Property {
@@ -102,6 +103,7 @@ typedef struct {
 	LilvNode*          control_class; /**< Control port class (URI) */
 	LilvNode*          audio_class;   /**< Audio port class (URI) */
 	LilvNode*          event_class;   /**< Event port class (URI) */
+	LilvNode*          aevent_class;  /**< Atom event port class (URI) */
 	LilvNode*          midi_class;    /**< MIDI event class (URI) */
 	LilvNode*          optional;      /**< lv2:connectionOptional port property */
 	uint32_t           midi_event_id; /**< MIDI event class ID */
diff --git a/src/lv2_evbuf.c b/src/lv2_evbuf.c
index 8426297..8fab7f5 100644
--- a/src/lv2_evbuf.c
+++ b/src/lv2_evbuf.c
@@ -18,7 +18,6 @@
 #include <stdbool.h>
 #include <string.h>
 #include <stdlib.h>
-#include <assert.h>
 
 #include "lv2/lv2plug.in/ns/ext/atom/atom-buffer.h"
 #include "lv2/lv2plug.in/ns/ext/event/event.h"
@@ -28,7 +27,7 @@
 struct LV2_Evbuf_Impl {
 	union {
 		LV2_Event_Buffer event;
-		LV2_Atom_Buffer  atom_event;
+		LV2_Atom_Buffer  atom;
 	} buf;
 	LV2_Evbuf_Type type;
 };
@@ -40,11 +39,17 @@ lv2_evbuf_pad_size(uint32_t size)
 }
 
 LV2_Evbuf*
-lv2_evbuf_new(uint32_t capacity)
+lv2_evbuf_new(uint32_t capacity, LV2_Evbuf_Type type)
 {
 	LV2_Evbuf* evbuf = (LV2_Evbuf*)malloc(sizeof(LV2_Evbuf));
-	evbuf->type = LV2_EVBUF_EVENT_BUFFER;
-	evbuf->buf.event.capacity = capacity;
+	evbuf->type = type;
+	switch (type) {
+	case LV2_EVBUF_EVENT:
+		evbuf->buf.event.capacity = capacity;
+		break;
+	case LV2_EVBUF_ATOM:
+		evbuf->buf.atom.capacity = capacity;
+	}
 	lv2_evbuf_reset(evbuf);
 	return evbuf;
 }
@@ -58,73 +63,127 @@ lv2_evbuf_free(LV2_Evbuf* evbuf)
 void
 lv2_evbuf_reset(LV2_Evbuf* evbuf)
 {
-	LV2_Event_Buffer* buf = &evbuf->buf.event;
-	buf->header_size = sizeof(LV2_Event_Buffer);
-	buf->stamp_type  = LV2_EVENT_AUDIO_STAMP;
-	buf->event_count = 0;
-	buf->size        = 0;
+	switch (evbuf->type) {
+	case LV2_EVBUF_EVENT:
+		evbuf->buf.event.header_size = sizeof(LV2_Event_Buffer);
+		evbuf->buf.event.stamp_type  = LV2_EVENT_AUDIO_STAMP;
+		evbuf->buf.event.event_count = 0;
+		evbuf->buf.event.size        = 0;
+		break;
+	case LV2_EVBUF_ATOM:
+		evbuf->buf.atom.event_count = 0;
+		evbuf->buf.atom.size        = 0;
+	}
+}
+
+uint32_t
+lv2_evbuf_get_size(LV2_Evbuf* evbuf)
+{
+	switch (evbuf->type) {
+	case LV2_EVBUF_EVENT:
+		return evbuf->buf.event.size;
+	case LV2_EVBUF_ATOM:
+		return evbuf->buf.atom.size;
+	}
+	return 0;
 }
 
 uint32_t
 lv2_evbuf_get_event_count(LV2_Evbuf* evbuf)
 {
-	return evbuf->buf.event.event_count;
+	switch (evbuf->type) {
+	case LV2_EVBUF_EVENT:
+		return evbuf->buf.event.event_count;
+	case LV2_EVBUF_ATOM:
+		return evbuf->buf.atom.event_count;
+	}
+	return 0;
 }
 
 void*
 lv2_evbuf_get_buffer(LV2_Evbuf* evbuf)
 {
-	return &evbuf->buf.event;
+	switch (evbuf->type) {
+	case LV2_EVBUF_EVENT:
+		return &evbuf->buf.event;
+	case LV2_EVBUF_ATOM:
+		return &evbuf->buf.atom;
+	}
+	return NULL;
 }
 
-bool
-lv2_evbuf_begin(LV2_Evbuf_Iterator* iter,
-                LV2_Evbuf*          evbuf)
+LV2_Evbuf_Iterator
+lv2_evbuf_begin(LV2_Evbuf* evbuf)
 {
-	LV2_Event_Buffer* buf = &evbuf->buf.event;
-	iter->offset = 0;
-	return buf->size > 0;
+	LV2_Evbuf_Iterator iter = { evbuf, 0 };
+	return iter;
 }
 
 bool
-lv2_evbuf_is_valid(LV2_Evbuf_Iterator* iter)
+lv2_evbuf_is_valid(LV2_Evbuf_Iterator iter)
 {
-	return iter->offset < iter->evbuf->buf.event.size;
+	return iter.offset < lv2_evbuf_get_size(iter.evbuf);
 }
 
-bool
-lv2_evbuf_increment(LV2_Evbuf_Iterator* iter)
+LV2_Evbuf_Iterator
+lv2_evbuf_next(LV2_Evbuf_Iterator iter)
 {
-	assert(lv2_evbuf_is_valid(iter));
-
-	LV2_Event* const ev = (LV2_Event*)(
-		(uint8_t*)iter->evbuf->buf.event.data + iter->offset);
+	if (!lv2_evbuf_is_valid(iter)) {
+		return iter;
+	}
 
-	iter->offset += lv2_evbuf_pad_size(sizeof(LV2_Event) + ev->size);
+	LV2_Evbuf* evbuf = iter.evbuf;
+	uint32_t size;
+	uint32_t offset = iter.offset;
+	switch (evbuf->type) {
+	case LV2_EVBUF_EVENT:
+		size = ((LV2_Event*)(evbuf->buf.event.data + offset))->size;
+		break;
+	case LV2_EVBUF_ATOM:
+		size = ((LV2_Atom_Event*)(evbuf->buf.atom.data + offset))->body.size;
+		break;
+	}
 
-	return true;
+	offset += lv2_evbuf_pad_size(sizeof(LV2_Atom_Event) + size);
+	LV2_Evbuf_Iterator next = { evbuf, offset };
+	return next;
 }
 
 bool
-lv2_evbuf_get(LV2_Evbuf_Iterator* iter,
-              uint32_t*           frames,
-              uint32_t*           subframes,
-              uint32_t*           type,
-              uint32_t*           size,
-              uint8_t**           data)
+lv2_evbuf_get(LV2_Evbuf_Iterator iter,
+              uint32_t*          frames,
+              uint32_t*          subframes,
+              uint32_t*          type,
+              uint32_t*          size,
+              uint8_t**          data)
 {
 	*frames = *subframes = *type = *size = 0;
 	*data = NULL;
-	assert(lv2_evbuf_is_valid(iter));
 
-	LV2_Event* const ev = (LV2_Event*)(
-		(uint8_t*)iter->evbuf->buf.event.data + iter->offset);
+	if (!lv2_evbuf_is_valid(iter)) {
+		return false;
+	}
 
-	*frames    = ev->frames;
-	*subframes = ev->subframes;
-	*type      = ev->type;
-	*size      = ev->size;
-	*data      = (uint8_t*)ev + sizeof(LV2_Event);
+	LV2_Event*      ev;
+	LV2_Atom_Event* aev;
+	switch (iter.evbuf->type) {
+	case LV2_EVBUF_EVENT:
+		ev = (LV2_Event*)(iter.evbuf->buf.event.data + iter.offset);
+		*frames    = ev->frames;
+		*subframes = ev->subframes;
+		*type      = ev->type;
+		*size      = ev->size;
+		*data      = (uint8_t*)ev + sizeof(LV2_Event);
+		break;
+	case LV2_EVBUF_ATOM:
+		aev = (LV2_Atom_Event*)(iter.evbuf->buf.atom.data + iter.offset);
+		*frames    = aev->frames;
+		*subframes = aev->subframes;
+		*type      = aev->body.type;
+		*size      = aev->body.size;
+		*data      = aev->body.body;
+		break;
+	}
 
 	return true;
 }
@@ -137,23 +196,49 @@ lv2_evbuf_write(LV2_Evbuf_Iterator* iter,
                 uint32_t            size,
                 const uint8_t*      data)
 {
-	LV2_Event_Buffer* buf = &iter->evbuf->buf.event;
-	if (buf->capacity - buf->size < sizeof(LV2_Event) + size) {
-		return false;
+	LV2_Event_Buffer* ebuf;
+	LV2_Event*        ev;
+	LV2_Atom_Buffer*  abuf;
+	LV2_Atom_Event*   aev;
+	switch (iter->evbuf->type) {
+	case LV2_EVBUF_EVENT:
+		ebuf = &iter->evbuf->buf.event;
+		if (ebuf->capacity - ebuf->size < sizeof(LV2_Event) + size) {
+			return false;
+		}
+
+		ev = (LV2_Event*)(ebuf->data + iter->offset);
+		ev->frames    = frames;
+		ev->subframes = subframes;
+		ev->type      = type;
+		ev->size      = size;
+		memcpy((uint8_t*)ev + sizeof(LV2_Event), data, size);
+
+		size               = lv2_evbuf_pad_size(sizeof(LV2_Event) + size);
+		ebuf->size        += size;
+		ebuf->event_count += 1;
+		iter->offset      += size;
+		break;
+	case LV2_EVBUF_ATOM:
+		abuf = &iter->evbuf->buf.atom;
+		if (abuf->capacity - abuf->size < sizeof(LV2_Atom_Event) + size) {
+			return false;
+		}
+
+		aev = (LV2_Atom_Event*)(abuf->data + iter->offset);
+		aev->frames    = frames;
+		aev->subframes = subframes;
+		aev->body.type = type;
+		aev->body.size = size;
+		memcpy(aev->body.body, data, size);
+		++abuf->event_count;
+
+		size               = lv2_atom_pad_size(sizeof(LV2_Atom_Event) + size);
+		abuf->size        += size;
+		abuf->event_count += 1;
+		iter->offset      += size;
+		break;
 	}
 
-	LV2_Event* const ev = (LV2_Event*)((uint8_t*)buf->data + iter->offset);
-
-	ev->frames    = frames;
-	ev->subframes = subframes;
-	ev->type      = type;
-	ev->size      = size;
-	memcpy((uint8_t*)ev + sizeof(LV2_Event), data, size);
-	++buf->event_count;
-
-	size             = lv2_evbuf_pad_size(sizeof(LV2_Event) + size);
-	buf->size += size;
-	iter->offset    += size;
-
 	return true;
 }
diff --git a/src/lv2_evbuf.h b/src/lv2_evbuf.h
index 94aa1e0..7af161d 100644
--- a/src/lv2_evbuf.h
+++ b/src/lv2_evbuf.h
@@ -31,12 +31,12 @@ typedef enum {
 	/**
 	   An old ev:EventBuffer (LV2_Event_Buffer).
 	*/
-	LV2_EVBUF_EVENT_BUFFER,
+	LV2_EVBUF_EVENT,
 
 	/**
 	   A new atom:EventBuffer (LV2_Atom_Event_Buffer).
 	*/
-	LV2_EVBUF_ATOM_EVENT_BUFFER
+	LV2_EVBUF_ATOM
 } LV2_Evbuf_Type;
 
 /**
@@ -56,7 +56,7 @@ typedef struct {
    Allocate a new, empty event buffer.
 */
 LV2_Evbuf*
-lv2_evbuf_new(uint32_t capacity);
+lv2_evbuf_new(uint32_t capacity, LV2_Evbuf_Type type);
 
 /**
    Free an event buffer allocated with lv2_evbuf_new.
@@ -72,6 +72,12 @@ lv2_evbuf_free(LV2_Evbuf* evbuf);
 void
 lv2_evbuf_reset(LV2_Evbuf* evbuf);
 
+/**
+   Return the total padded size of the events stored in the buffer.
+*/
+uint32_t
+lv2_evbuf_get_size(LV2_Evbuf* evbuf);
+
 /**
    Return the number of events stored in the buffer.
 */
@@ -89,24 +95,23 @@ lv2_evbuf_get_buffer(LV2_Evbuf* evbuf);
    Reset an iterator to point to the start of @a buf.
    @return True if @a iter is valid, otherwise false (buffer is empty)
 */
-bool
-lv2_evbuf_begin(LV2_Evbuf_Iterator* iter,
-                LV2_Evbuf*          evbuf);
+LV2_Evbuf_Iterator
+lv2_evbuf_begin(LV2_Evbuf* evbuf);
 
 /**
    Check if @a iter is valid.
    @return True if @a iter is valid, otherwise false (past end of buffer)
 */
 bool
-lv2_evbuf_is_valid(LV2_Evbuf_Iterator* iter);
+lv2_evbuf_is_valid(LV2_Evbuf_Iterator iter);
 
 /**
    Advance @a iter forward one event.
    @a iter must be valid.
    @return True if @a iter is valid, otherwise false (reached end of buffer)
 */
-bool
-lv2_evbuf_increment(LV2_Evbuf_Iterator* iter);
+LV2_Evbuf_Iterator
+lv2_evbuf_next(LV2_Evbuf_Iterator iter);
 
 /**
    Dereference an event iterator (i.e. get the event currently pointed to).
@@ -117,12 +122,12 @@ lv2_evbuf_increment(LV2_Evbuf_Iterator* iter);
    @return True on success.
 */
 bool
-lv2_evbuf_get(LV2_Evbuf_Iterator* iter,
-              uint32_t*           frames,
-              uint32_t*           subframes,
-              uint32_t*           type,
-              uint32_t*           size,
-              uint8_t**           data);
+lv2_evbuf_get(LV2_Evbuf_Iterator iter,
+              uint32_t*          frames,
+              uint32_t*          subframes,
+              uint32_t*          type,
+              uint32_t*          size,
+              uint8_t**          data);
 
 /**
    Write an event at @a iter.
-- 
cgit v1.2.1