Update to latest LV2 atom extension.
authorDavid Robillard <d@drobilla.net>
Wed, 29 Feb 2012 03:21:37 +0000 (03:21 +0000)
committerDavid Robillard <d@drobilla.net>
Wed, 29 Feb 2012 03:21:37 +0000 (03:21 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@11548 d708f5d6-7413-0410-9779-e7cbd77b26cf

libs/ardour/ardour/buffer_set.h
libs/ardour/ardour/lv2_plugin.h
libs/ardour/buffer_set.cc
libs/ardour/lv2/lv2plug.in/ns/ext/atom/atom.h
libs/ardour/lv2/lv2plug.in/ns/ext/atom/forge.h
libs/ardour/lv2_evbuf.c
libs/ardour/lv2_evbuf.h
libs/ardour/lv2_plugin.cc

index 5049eda70a36f149f76d8394ad396b816cb1e38e..3cb6cbdbd9b3a3268edf2c847206cad6cb57d1b8 100644 (file)
@@ -112,13 +112,13 @@ public:
        }
 
 #ifdef LV2_SUPPORT
-       /** Get a MIDI buffer translated into an LV2 MIDI buffer for use with plugins.
-        * The index here corresponds directly to MIDI buffer numbers (i.e. the index
-        * passed to get_midi), translation back and forth will happen as needed.
-        * If atom_type is 0 the returned buffer will be in the old event API
-        * format.  Otherwise, atom_type must be the URID for atom:Sequence.
+       /** Get a MIDI buffer translated into an LV2 MIDI buffer for use with
+        * plugins.  The index here corresponds directly to MIDI buffer numbers
+        * (i.e. the index passed to get_midi), translation back and forth will
+        * happen as needed.  If old_api is true, the returned buffer will be in
+        * old event format.  Otherwise it will be in new atom sequence format.
         */
-       LV2_Evbuf* get_lv2_midi(bool input, size_t i, uint32_t atom_type);
+       LV2_Evbuf* get_lv2_midi(bool input, size_t i, bool old_api);
 
        /** Flush modified LV2 event output buffers back to Ardour buffers */
        void flush_lv2_midi(bool input, size_t i);
index 8ae9016bb23c0a7044025ba2f7c727cd9eaeddd7..0cd3bbd2de10e46bad6cc680aaac880e0de776a4 100644 (file)
@@ -130,6 +130,13 @@ class LV2Plugin : public ARDOUR::Plugin
 
        static URIMap _uri_map;
 
+       static uint32_t _midi_event_type_ev;
+       static uint32_t _midi_event_type;
+       static uint32_t _chunk_type;
+       static uint32_t _sequence_type;
+       static uint32_t _event_transfer_type;
+       static uint32_t _state_path_type;
+
   private:
        struct Impl;
        Impl*         _impl;
@@ -193,12 +200,6 @@ class LV2Plugin : public ARDOUR::Plugin
        bool _was_activated;
        bool _has_state_interface;
 
-       static uint32_t _midi_event_type_ev;
-       static uint32_t _midi_event_type;
-       static uint32_t _sequence_type;
-       static uint32_t _event_transfer_type;
-       static uint32_t _state_path_type;
-
        const std::string plugin_dir () const;
        const std::string scratch_dir () const;
        const std::string file_dir () const;
index bf114b95d5d9e0ce9d121670e1f1034355d6dc16..156cf4dd3fe583c68223ef5c9b6235d311c38c31 100644 (file)
@@ -190,8 +190,10 @@ BufferSet::ensure_buffers(DataType type, size_t num_buffers, size_t buffer_capac
        if (type == DataType::MIDI && _lv2_buffers.size() < _buffers[type].size() * 2 + 1) {
                while (_lv2_buffers.size() < _buffers[type].size() * 2) {
                        _lv2_buffers.push_back(
-                               std::make_pair(false,
-                                              lv2_evbuf_new(buffer_capacity, LV2_EVBUF_EVENT, 0)));
+                               std::make_pair(false, lv2_evbuf_new(buffer_capacity,
+                                                                   LV2_EVBUF_EVENT,
+                                                                   LV2Plugin::_chunk_type,
+                                                                   LV2Plugin::_sequence_type)));
                }
        }
 #endif
@@ -251,25 +253,23 @@ BufferSet::get(DataType type, size_t i) const
 #ifdef LV2_SUPPORT
 
 LV2_Evbuf*
-BufferSet::get_lv2_midi(bool input, size_t i, uint32_t atom_type)
+BufferSet::get_lv2_midi(bool input, size_t i, bool old_api)
 {
        assert(count().get(DataType::MIDI) > i);
 
        MidiBuffer&            mbuf  = get_midi(i);
        LV2Buffers::value_type b     = _lv2_buffers.at(i * 2 + (input ? 0 : 1));
        LV2_Evbuf*             evbuf = b.second;
-       lv2_evbuf_set_type(evbuf,
-                          atom_type ? LV2_EVBUF_ATOM : LV2_EVBUF_EVENT,
-                          atom_type);
+       lv2_evbuf_set_type(evbuf, old_api ? LV2_EVBUF_EVENT : LV2_EVBUF_ATOM);
 
-       lv2_evbuf_reset(evbuf);
+       lv2_evbuf_reset(evbuf, input);
        if (input) {
                DEBUG_TRACE(PBD::DEBUG::LV2,
                            string_compose("%1 bytes of MIDI waiting @ %2\n",
                                           mbuf.size(), (void*) mbuf.data()));
                
                LV2_Evbuf_Iterator i    = lv2_evbuf_begin(evbuf);
-               const uint32_t     type = LV2Plugin::midi_event_type(atom_type == 0);
+               const uint32_t     type = LV2Plugin::midi_event_type(old_api);
                for (MidiBuffer::iterator e = mbuf.begin(); e != mbuf.end(); ++e) {
                        const Evoral::MIDIEvent<framepos_t> ev(*e, false);
 #ifndef NDEBUG
index 9bce7ce7aac5904038e622094b4cfb6c6ff0baeb..6287830eed08c71f828a1dd3f5dd5140e090d02a 100644 (file)
@@ -33,6 +33,7 @@
 #define LV2_ATOM__Beats         LV2_ATOM_URI "#Beats"
 #define LV2_ATOM__Blank         LV2_ATOM_URI "#Blank"
 #define LV2_ATOM__Bool          LV2_ATOM_URI "#Bool"
+#define LV2_ATOM__Chunk         LV2_ATOM_URI "#Chunk"
 #define LV2_ATOM__Double        LV2_ATOM_URI "#Double"
 #define LV2_ATOM__Event         LV2_ATOM_URI "#Event"
 #define LV2_ATOM__Float         LV2_ATOM_URI "#Float"
@@ -55,6 +56,7 @@
 #define LV2_ATOM__Vector        LV2_ATOM_URI "#Vector"
 #define LV2_ATOM__beatTime      LV2_ATOM_URI "#beatTime"
 #define LV2_ATOM__bufferType    LV2_ATOM_URI "#bufferType"
+#define LV2_ATOM__childType     LV2_ATOM_URI "#childType"
 #define LV2_ATOM__eventTransfer LV2_ATOM_URI "#eventTransfer"
 #define LV2_ATOM__frameTime     LV2_ATOM_URI "#frameTime"
 #define LV2_ATOM__supports      LV2_ATOM_URI "#supports"
@@ -91,6 +93,12 @@ typedef struct {
        uint32_t type;  /**< Type of this atom (mapped URI). */
 } LV2_Atom;
 
+/** A chunk of memory that may be uninitialized or contain an Atom. */
+typedef struct {
+       LV2_Atom atom;  /**< Atom header. */
+       LV2_Atom body;  /**< Body atom header. */
+} LV2_Atom_Chunk;
+
 /** An atom:Int32 or atom:Bool.  May be cast to LV2_Atom. */
 typedef struct {
        LV2_Atom atom;  /**< Atom header. */
@@ -229,29 +237,6 @@ typedef struct {
        LV2_Atom_Literal_Body body;  /**< Body. */
 } LV2_Atom_Sequence;
 
-/**
-   The contents of an atom:AtomPort buffer.
-
-   This contains a pointer to an Atom, which is the data to be
-   processed/written, as well as additional metadata.  This struct may be
-   augmented in the future to add more metadata fields as they become
-   necessary.  The initial version of this struct contains data, size, and
-   capacity.  Implementations MUST check that any other fields they wish to use
-   are actually present by comparing the size with the offset of that field,
-   e.g.:
-
-   @code
-   if (offsetof(LV2_Atom_Port_Buffer, field) < buf->size) {
-       do_stuff_with(buf->field);
-   }
-   @endcode
-*/
-typedef struct {
-       LV2_Atom* data;      /** Pointer to data. */
-       uint32_t  size;      /** Total size of this struct. */
-       uint32_t  capacity;  /** Available space for data body. */
-} LV2_Atom_Port_Buffer;
-
 #ifdef __cplusplus
 }  /* extern "C" */
 #endif
index b9dd51ca2828f9cf4b6ed48e920f88eacc4768ff..f55cb0800c6a885c7ddc53f6b4ce4bc68ec379f8 100644 (file)
@@ -131,6 +131,7 @@ lv2_atom_forge_set_buffer(LV2_Atom_Forge* forge, uint8_t* buf, size_t size)
        forge->offset = 0;
        forge->sink   = NULL;
        forge->handle = NULL;
+       forge->stack  = NULL;
 }
 
 /**
@@ -154,6 +155,7 @@ lv2_atom_forge_set_sink(LV2_Atom_Forge*            forge,
        forge->size   = forge->offset = 0;
        forge->sink   = sink;
        forge->handle = handle;
+       forge->stack  = NULL;
 }
 
 /**
@@ -195,7 +197,7 @@ lv2_atom_forge_raw(LV2_Atom_Forge* forge, const void* data, uint32_t size)
 {
        uint8_t* out = NULL;
        if (forge->sink) {
-               out = forge->sink(forge->handle, data, size);
+               out = (uint8_t*)forge->sink(forge->handle, data, size);
        } else {
                out = forge->buf + forge->offset;
                if (forge->offset + size > forge->size) {
@@ -295,12 +297,12 @@ lv2_atom_forge_string_body(LV2_Atom_Forge* forge,
                            const uint8_t*  str,
                            uint32_t        len)
 {
-       uint8_t* out = NULL;
+       void* out = NULL;
        if (   (out = lv2_atom_forge_raw(forge, str, len))
            && (out = lv2_atom_forge_raw(forge, "", 1))) {
                lv2_atom_forge_pad(forge, len + 1);
        }
-       return out;
+       return (uint8_t*)out;
 }
 
 /** Write an atom compatible with atom:String.  Used internally. */
@@ -424,7 +426,7 @@ static inline LV2_Atom_Tuple*
 lv2_atom_forge_tuple(LV2_Atom_Forge* forge, LV2_Atom_Forge_Frame* frame)
 {
        const LV2_Atom_Tuple a    = { { 0, forge->Tuple } };
-       LV2_Atom*            atom = lv2_atom_forge_write(forge, &a, sizeof(a));
+       LV2_Atom*            atom = (LV2_Atom*)lv2_atom_forge_write(forge, &a, sizeof(a));
        return (LV2_Atom_Tuple*)lv2_atom_forge_push(forge, frame, atom);
 }
 
index 7877e07950844435f08b7a0e753b4b45f7a55d87..f3aea8d7993be516a7a4c49eaeb33e5c51b397fd 100644 (file)
@@ -14,8 +14,6 @@
   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
 
-#include <stdint.h>
-#include <stdbool.h>
 #include <string.h>
 #include <stdlib.h>
 
 struct LV2_Evbuf_Impl {
        LV2_Evbuf_Type type;
        uint32_t       capacity;
+       uint32_t       atom_Chunk;
+       uint32_t       atom_Sequence;
        union {
-               LV2_Event_Buffer     event;
-               LV2_Atom_Port_Buffer atom;
+               LV2_Event_Buffer  event;
+               LV2_Atom_Sequence atom;
        } buf;
 };
 
@@ -40,14 +40,19 @@ lv2_evbuf_pad_size(uint32_t size)
 }
 
 LV2_Evbuf*
-lv2_evbuf_new(uint32_t capacity, LV2_Evbuf_Type type, uint32_t atom_type)
+lv2_evbuf_new(uint32_t       capacity,
+              LV2_Evbuf_Type type,
+              uint32_t       atom_Chunk,
+              uint32_t       atom_Sequence)
 {
        // FIXME: memory must be 64-bit aligned
        LV2_Evbuf* evbuf = (LV2_Evbuf*)malloc(
                sizeof(LV2_Evbuf) + sizeof(LV2_Atom_Sequence) + capacity);
-       evbuf->capacity = capacity;
-       lv2_evbuf_set_type(evbuf, type, atom_type);
-       lv2_evbuf_reset(evbuf);
+       evbuf->capacity      = capacity;
+       evbuf->atom_Chunk    = atom_Chunk;
+       evbuf->atom_Sequence = atom_Sequence;
+       lv2_evbuf_set_type(evbuf, type);
+       lv2_evbuf_reset(evbuf, true);
        return evbuf;
 }
 
@@ -58,7 +63,7 @@ lv2_evbuf_free(LV2_Evbuf* evbuf)
 }
 
 void
-lv2_evbuf_set_type(LV2_Evbuf* evbuf, LV2_Evbuf_Type type, uint32_t atom_type)
+lv2_evbuf_set_type(LV2_Evbuf* evbuf, LV2_Evbuf_Type type)
 {
        evbuf->type = type;
        switch (type) {
@@ -67,18 +72,13 @@ lv2_evbuf_set_type(LV2_Evbuf* evbuf, LV2_Evbuf_Type type, uint32_t atom_type)
                evbuf->buf.event.capacity = evbuf->capacity;
                break;
        case LV2_EVBUF_ATOM:
-               evbuf->buf.atom.data       = (LV2_Atom*)(evbuf + 1);
-               evbuf->buf.atom.size       = sizeof(LV2_Atom_Port_Buffer);
-               evbuf->buf.atom.capacity   = evbuf->capacity;
-               evbuf->buf.atom.data->type = atom_type;
-               evbuf->buf.atom.data->size = 0;
                break;
        }
-       lv2_evbuf_reset(evbuf);
+       lv2_evbuf_reset(evbuf, true);
 }
 
 void
-lv2_evbuf_reset(LV2_Evbuf* evbuf)
+lv2_evbuf_reset(LV2_Evbuf* evbuf, bool input)
 {
        switch (evbuf->type) {
        case LV2_EVBUF_EVENT:
@@ -88,7 +88,13 @@ lv2_evbuf_reset(LV2_Evbuf* evbuf)
                evbuf->buf.event.size        = 0;
                break;
        case LV2_EVBUF_ATOM:
-               evbuf->buf.atom.data->size = 0;
+               if (input) {
+                       evbuf->buf.atom.atom.size = 0;
+                       evbuf->buf.atom.atom.type = evbuf->atom_Sequence;
+               } else {
+                       evbuf->buf.atom.atom.size = evbuf->capacity;
+                       evbuf->buf.atom.atom.type = evbuf->atom_Chunk;
+               }
        }
 }
 
@@ -99,7 +105,9 @@ lv2_evbuf_get_size(LV2_Evbuf* evbuf)
        case LV2_EVBUF_EVENT:
                return evbuf->buf.event.size;
        case LV2_EVBUF_ATOM:
-               return evbuf->buf.atom.data->size;
+               return evbuf->buf.atom.atom.type == evbuf->atom_Sequence
+                       ? evbuf->buf.atom.atom.size
+                       : 0;
        }
        return 0;
 }
@@ -154,7 +162,7 @@ lv2_evbuf_next(LV2_Evbuf_Iterator iter)
                break;
        case LV2_EVBUF_ATOM:
                size = ((LV2_Atom_Event*)
-                       ((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, evbuf->buf.atom.data)
+                       ((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, &evbuf->buf.atom)
                         + offset))->body.size;
                offset += lv2_evbuf_pad_size(sizeof(LV2_Atom_Event) + size);
                break;
@@ -179,10 +187,10 @@ lv2_evbuf_get(LV2_Evbuf_Iterator iter,
                return false;
        }
 
-       LV2_Event_Buffer*     ebuf;
-       LV2_Event*            ev;
-       LV2_Atom_Port_Buffer* abuf;
-       LV2_Atom_Event*       aev;
+       LV2_Event_Buffer*  ebuf;
+       LV2_Event*         ev;
+       LV2_Atom_Sequence* aseq;
+       LV2_Atom_Event*    aev;
        switch (iter.evbuf->type) {
        case LV2_EVBUF_EVENT:
                ebuf = &iter.evbuf->buf.event;
@@ -194,9 +202,9 @@ lv2_evbuf_get(LV2_Evbuf_Iterator iter,
                *data      = (uint8_t*)ev + sizeof(LV2_Event);
                break;
        case LV2_EVBUF_ATOM:
-               abuf = &iter.evbuf->buf.atom;
+               aseq = (LV2_Atom_Sequence*)&iter.evbuf->buf.atom;
                aev = (LV2_Atom_Event*)(
-                       (char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, abuf->data)
+                       (char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, aseq)
                        + iter.offset);
                *frames    = aev->time.frames;
                *subframes = 0;
@@ -217,10 +225,10 @@ lv2_evbuf_write(LV2_Evbuf_Iterator* iter,
                 uint32_t            size,
                 const uint8_t*      data)
 {
-       LV2_Event_Buffer*     ebuf;
-       LV2_Event*            ev;
-       LV2_Atom_Port_Buffer* abuf;
-       LV2_Atom_Event*       aev;
+       LV2_Event_Buffer*  ebuf;
+       LV2_Event*         ev;
+       LV2_Atom_Sequence* aseq;
+       LV2_Atom_Event*    aev;
        switch (iter->evbuf->type) {
        case LV2_EVBUF_EVENT:
                ebuf = &iter->evbuf->buf.event;
@@ -241,22 +249,23 @@ lv2_evbuf_write(LV2_Evbuf_Iterator* iter,
                iter->offset      += size;
                break;
        case LV2_EVBUF_ATOM:
-               abuf = &iter->evbuf->buf.atom;
-               if (abuf->capacity - abuf->data->size < sizeof(LV2_Atom_Event) + size) {
+               aseq = (LV2_Atom_Sequence*)&iter->evbuf->buf.atom;
+               if (iter->evbuf->capacity - sizeof(LV2_Atom) - aseq->atom.size
+                   < sizeof(LV2_Atom_Event) + size) {
                        return false;
                }
 
                aev = (LV2_Atom_Event*)(
-                       (char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, abuf->data)
+                       (char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, aseq)
                        + iter->offset);
                aev->time.frames = frames;
                aev->body.type   = type;
                aev->body.size   = size;
                memcpy(LV2_ATOM_BODY(&aev->body), data, size);
 
-               size              = lv2_evbuf_pad_size(sizeof(LV2_Atom_Event) + size);
-               abuf->data->size += size;
-               iter->offset     += size;
+               size             = lv2_evbuf_pad_size(sizeof(LV2_Atom_Event) + size);
+               aseq->atom.size += size;
+               iter->offset    += size;
                break;
        }
 
index b2caa12e280a5604cad3d91fcbff93ae18333499..fdb7766f96f7ac710c3db72d5e94f7ec39e55122 100644 (file)
 #define LV2_EVBUF_H
 
 #include <stdint.h>
-#include <stdbool.h>
 
 #ifdef __cplusplus
 extern "C" {
+#else
+#include <stdbool.h>
 #endif
 
 /**
@@ -54,11 +55,13 @@ typedef struct {
 
 /**
    Allocate a new, empty event buffer.
-   The URID for atom:Sequence must be passed for atom_Sequence if type is
-   LV2_EVBUF_ATOM.
+   URIDs for atom:Chunk and atom:Sequence must be passed for LV2_EVBUF_ATOM.
 */
 LV2_Evbuf*
-lv2_evbuf_new(uint32_t capacity, LV2_Evbuf_Type type, uint32_t atom_type);
+lv2_evbuf_new(uint32_t       capacity,
+              LV2_Evbuf_Type type,
+              uint32_t       atom_Chunk,
+              uint32_t       atom_Sequence);
 
 /**
    Free an event buffer allocated with lv2_evbuf_new.
@@ -67,21 +70,21 @@ void
 lv2_evbuf_free(LV2_Evbuf* evbuf);
 
 /**
-   Change the type of an existing event buffer.  This will clear and reset the
-   buffer, it is not possible to change the type and preserve the buffer
-   contents since the formats differ.  The URID for atom:Sequence must be
-   passed for atom_Sequence if type is LV2_EVBUF_ATOM.
+   Reset and change the type of an existing event buffer.
+   URIDs for atom:Chunk and atom:Sequence must be passed for LV2_EVBUF_ATOM.
 */
 void
-lv2_evbuf_set_type(LV2_Evbuf* evbuf, LV2_Evbuf_Type type, uint32_t atom_type);
+lv2_evbuf_set_type(LV2_Evbuf* evbuf, LV2_Evbuf_Type type);
 
 /**
    Clear and initialize an existing event buffer.
    The contents of buf are ignored entirely and overwritten, except capacity
    which is unmodified.
+   If input is false and this is an atom buffer, the buffer will be prepared
+   for writing by the plugin.  This MUST be called before every run cycle.
 */
 void
-lv2_evbuf_reset(LV2_Evbuf* evbuf);
+lv2_evbuf_reset(LV2_Evbuf* evbuf, bool input);
 
 /**
    Return the total padded size of the events stored in the buffer.
index 4a21e84628f1cee4e70a5fde28dc0760a5340e9c..259a81822dc102e308c47aef9a546c26c081160d 100644 (file)
@@ -74,6 +74,8 @@ uint32_t LV2Plugin::_midi_event_type_ev = _uri_map.uri_to_id(
 uint32_t LV2Plugin::_midi_event_type = _uri_map.uri_to_id(
        NULL,
        "http://lv2plug.in/ns/ext/midi#MidiEvent");
+uint32_t LV2Plugin::_chunk_type = _uri_map.uri_to_id(
+       NULL, LV2_ATOM__Chunk);
 uint32_t LV2Plugin::_sequence_type = _uri_map.uri_to_id(
        NULL, LV2_ATOM__Sequence);
 uint32_t LV2Plugin::_event_transfer_type = _uri_map.uri_to_id(
@@ -88,6 +90,7 @@ public:
 
        LilvWorld* world;
 
+       LilvNode* atom_Chunk;
        LilvNode* atom_MessagePort;
        LilvNode* atom_Sequence;
        LilvNode* atom_bufferType;
@@ -231,6 +234,18 @@ LV2Plugin::init(void* c_plugin, framecnt_t rate)
        for (uint32_t i = 0; i < num_ports; ++i) {
                const LilvPort* port  = lilv_plugin_get_port_by_index(_impl->plugin, i);
                PortFlags       flags = 0;
+
+               if (lilv_port_is_a(_impl->plugin, port, _world.lv2_OutputPort)) {
+                       flags |= PORT_OUTPUT;
+               } else if (lilv_port_is_a(_impl->plugin, port, _world.lv2_InputPort)) {
+                       flags |= PORT_INPUT;
+               } else {
+                       error << string_compose(
+                               "LV2: \"%1\" port %2 is neither input nor output",
+                               lilv_node_as_string(_impl->name), i) << endmsg;
+                       throw failed_constructor();
+               }
+
                if (lilv_port_is_a(_impl->plugin, port, _world.lv2_ControlPort)) {
                        flags |= PORT_CONTROL;
                } else if (lilv_port_is_a(_impl->plugin, port, _world.lv2_AudioPort)) {
@@ -240,9 +255,9 @@ LV2Plugin::init(void* c_plugin, framecnt_t rate)
                } else if (lilv_port_is_a(_impl->plugin, port, _world.atom_MessagePort)) {
                        LilvNodes* buffer_types = lilv_port_get_value(
                                _impl->plugin, port, _world.atom_bufferType);
-                       if (lilv_nodes_contains(buffer_types, _world.atom_Sequence)) {
-                               flags |= PORT_MESSAGE;
-                       }
+                               if (lilv_nodes_contains(buffer_types, _world.atom_Sequence)) {
+                                       flags |= PORT_MESSAGE;
+                               }
                        lilv_nodes_free(buffer_types);
                } else {
                        error << string_compose(
@@ -250,16 +265,7 @@ LV2Plugin::init(void* c_plugin, framecnt_t rate)
                                lilv_node_as_string(_impl->name), i) << endmsg;
                        throw failed_constructor();
                }
-               if (lilv_port_is_a(_impl->plugin, port, _world.lv2_OutputPort)) {
-                       flags |= PORT_OUTPUT;
-               } else if (lilv_port_is_a(_impl->plugin, port, _world.lv2_InputPort)) {
-                       flags |= PORT_INPUT;
-               } else {
-                       error << string_compose(
-                               "LV2: \"%1\" port %2 is neither input nor output",
-                               lilv_node_as_string(_impl->name), i) << endmsg;
-                       throw failed_constructor();
-               }
+
                _port_flags.push_back(flags);
        }
 
@@ -1097,18 +1103,17 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
                           be necessary, but the mapping is illegal in some cases.  Ideally
                           that should be fixed, but this is easier...
                        */
-                       const uint32_t atom_type = (flags & PORT_MESSAGE) ? _sequence_type : 0;
                        if (flags & PORT_INPUT) {
                                index = in_map.get(DataType::MIDI, midi_in_index++, &valid);
                                _ev_buffers[port_index] = (valid && bufs.count().n_midi() > index)
-                                       ? bufs.get_lv2_midi(true, index, atom_type)
-                                       : silent_bufs.get_lv2_midi(true, 0, atom_type);
+                                       ? bufs.get_lv2_midi(true, index, flags & PORT_EVENT)
+                                       : silent_bufs.get_lv2_midi(true, 0, flags & PORT_EVENT);
                                buf = lv2_evbuf_get_buffer(_ev_buffers[port_index]);
                        } else {
                                index = out_map.get(DataType::MIDI, midi_out_index++, &valid);
                                _ev_buffers[port_index] = (valid && bufs.count().n_midi() > index)
-                                       ? bufs.get_lv2_midi(false, index, atom_type)
-                                       : scratch_bufs.get_lv2_midi(false, 0, atom_type);
+                                       ? bufs.get_lv2_midi(false, index, flags & PORT_EVENT)
+                                       : scratch_bufs.get_lv2_midi(false, 0, flags & PORT_EVENT);
                                buf = lv2_evbuf_get_buffer(_ev_buffers[port_index]);
                        }
                } else {
@@ -1313,6 +1318,7 @@ LV2World::LV2World()
        : world(lilv_world_new())
 {
        lilv_world_load_all(world);
+       atom_Chunk         = lilv_new_uri(world, LV2_ATOM__Chunk);
        atom_MessagePort   = lilv_new_uri(world, LV2_ATOM__MessagePort);
        atom_Sequence      = lilv_new_uri(world, LV2_ATOM__Sequence);
        atom_bufferType    = lilv_new_uri(world, LV2_ATOM__bufferType);
@@ -1351,6 +1357,7 @@ LV2World::~LV2World()
        lilv_node_free(atom_bufferType);
        lilv_node_free(atom_Sequence);
        lilv_node_free(atom_MessagePort);
+       lilv_node_free(atom_Chunk);
 }
 
 LV2PluginInfo::LV2PluginInfo (void* c_plugin)