aboutsummaryrefslogtreecommitdiffstats
path: root/lv2/lv2plug.in/ns/ext/event
diff options
context:
space:
mode:
Diffstat (limited to 'lv2/lv2plug.in/ns/ext/event')
-rw-r--r--lv2/lv2plug.in/ns/ext/event/event-helpers.h246
-rw-r--r--lv2/lv2plug.in/ns/ext/event/event.h281
-rw-r--r--lv2/lv2plug.in/ns/ext/event/event.ttl224
l---------lv2/lv2plug.in/ns/ext/event/ext.pc.in1
-rw-r--r--lv2/lv2plug.in/ns/ext/event/manifest.ttl9
l---------lv2/lv2plug.in/ns/ext/event/waf1
l---------lv2/lv2plug.in/ns/ext/event/wscript1
7 files changed, 763 insertions, 0 deletions
diff --git a/lv2/lv2plug.in/ns/ext/event/event-helpers.h b/lv2/lv2plug.in/ns/ext/event/event-helpers.h
new file mode 100644
index 0000000..75ba14b
--- /dev/null
+++ b/lv2/lv2plug.in/ns/ext/event/event-helpers.h
@@ -0,0 +1,246 @@
+/* lv2_event_helpers.h - Helper functions for the LV2 events extension.
+ *
+ * Copyright (C) 2008-2009 David Robillard <http://drobilla.net>
+ *
+ * This header is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This header 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this header; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307 USA
+ */
+
+#ifndef LV2_EVENT_HELPERS_H
+#define LV2_EVENT_HELPERS_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "lv2/lv2plug.in/ns/ext/event/event.h"
+
+/** @file
+ * Helper functions for the LV2 Event extension
+ * <http://lv2plug.in/ns/ext/event>.
+ *
+ * These functions are provided for convenience only, use of them is not
+ * required for supporting lv2ev (i.e. the events extension is defined by the
+ * raw buffer format described in lv2_event.h and NOT by this API).
+ *
+ * Note that these functions are all static inline which basically means:
+ * do not take the address of these functions. */
+
+
+/** Pad a size to 64 bits (for event sizes) */
+static inline uint16_t
+lv2_event_pad_size(uint16_t size)
+{
+ return (size + 7) & (~7);
+}
+
+
+/** Initialize (empty, reset..) an existing event buffer.
+ * The contents of buf are ignored entirely and overwritten, except capacity
+ * which is unmodified. */
+static inline void
+lv2_event_buffer_reset(LV2_Event_Buffer* buf,
+ uint16_t stamp_type,
+ uint8_t *data)
+{
+ buf->data = data;
+ buf->header_size = sizeof(LV2_Event_Buffer);
+ buf->stamp_type = stamp_type;
+ buf->event_count = 0;
+ buf->size = 0;
+}
+
+
+/** Allocate a new, empty event buffer. */
+static inline LV2_Event_Buffer*
+lv2_event_buffer_new(uint32_t capacity, uint16_t stamp_type)
+{
+ const size_t size = sizeof(LV2_Event_Buffer) + capacity;
+ LV2_Event_Buffer* buf = (LV2_Event_Buffer*)malloc(size);
+ if (buf != NULL) {
+ buf->capacity = capacity;
+ lv2_event_buffer_reset(buf, stamp_type, (uint8_t *)(buf + 1));
+ return buf;
+ } else {
+ return NULL;
+ }
+}
+
+
+/** An iterator over an LV2_Event_Buffer.
+ *
+ * Multiple simultaneous read iterators over a single buffer is fine,
+ * but changing the buffer invalidates all iterators (e.g. RW Lock). */
+typedef struct {
+ LV2_Event_Buffer* buf;
+ uint32_t offset;
+} LV2_Event_Iterator;
+
+
+/** Reset an iterator to point to the start of @a buf.
+ * @return True if @a iter is valid, otherwise false (buffer is empty) */
+static inline bool
+lv2_event_begin(LV2_Event_Iterator* iter,
+ LV2_Event_Buffer* buf)
+{
+ iter->buf = buf;
+ iter->offset = 0;
+ return (buf->size > 0);
+}
+
+
+/** Check if @a iter is valid.
+ * @return True if @a iter is valid, otherwise false (past end of buffer) */
+static inline bool
+lv2_event_is_valid(LV2_Event_Iterator* iter)
+{
+ return (iter->offset < iter->buf->size);
+}
+
+
+/** Advance @a iter forward one event.
+ * @a iter must be valid.
+ * @return True if @a iter is valid, otherwise false (reached end of buffer) */
+static inline bool
+lv2_event_increment(LV2_Event_Iterator* iter)
+{
+ assert(lv2_event_is_valid(iter));
+
+ LV2_Event* const ev = (LV2_Event*)(
+ (uint8_t*)iter->buf->data + iter->offset);
+
+ iter->offset += lv2_event_pad_size(sizeof(LV2_Event) + ev->size);
+
+ return true;
+}
+
+
+/** Dereference an event iterator (get the event currently pointed at).
+ * @a iter must be valid.
+ * @a data if non-NULL, will be set to point to the contents of the event
+ * returned.
+ * @return A Pointer to the event @a iter is currently pointing at, or NULL
+ * if the end of the buffer is reached (in which case @a data is
+ * also set to NULL). */
+static inline LV2_Event*
+lv2_event_get(LV2_Event_Iterator* iter,
+ uint8_t** data)
+{
+ assert(lv2_event_is_valid(iter));
+
+ LV2_Event* const ev = (LV2_Event*)(
+ (uint8_t*)iter->buf->data + iter->offset);
+
+ if (data)
+ *data = (uint8_t*)ev + sizeof(LV2_Event);
+
+ return ev;
+}
+
+
+/** Write an event at @a iter.
+ * The event (if any) pointed to by @a iter will be overwritten, and @a iter
+ * incremented to point to the following event (i.e. several calls to this
+ * function can be done in sequence without twiddling iter in-between).
+ * @return True if event was written, otherwise false (buffer is full). */
+static inline bool
+lv2_event_write(LV2_Event_Iterator* iter,
+ uint32_t frames,
+ uint32_t subframes,
+ uint16_t type,
+ uint16_t size,
+ const uint8_t* data)
+{
+ if (iter->buf->capacity - iter->buf->size < sizeof(LV2_Event) + size)
+ return false;
+
+ LV2_Event* const ev = (LV2_Event*)(
+ (uint8_t*)iter->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);
+ ++iter->buf->event_count;
+
+ size = lv2_event_pad_size(sizeof(LV2_Event) + size);
+ iter->buf->size += size;
+ iter->offset += size;
+
+ return true;
+}
+
+
+/** Reserve space for an event in the buffer and return a pointer to
+ the memory where the caller can write the event data, or NULL if there
+ is not enough room in the buffer. */
+static inline uint8_t*
+lv2_event_reserve(LV2_Event_Iterator* iter,
+ uint32_t frames,
+ uint32_t subframes,
+ uint16_t type,
+ uint16_t size)
+{
+ size = lv2_event_pad_size(size);
+ if (iter->buf->capacity - iter->buf->size < sizeof(LV2_Event) + size)
+ return NULL;
+
+ LV2_Event* const ev = (LV2_Event*)((uint8_t*)iter->buf->data +
+ iter->offset);
+
+ ev->frames = frames;
+ ev->subframes = subframes;
+ ev->type = type;
+ ev->size = size;
+ ++iter->buf->event_count;
+
+ size = lv2_event_pad_size(sizeof(LV2_Event) + size);
+ iter->buf->size += size;
+ iter->offset += size;
+
+ return (uint8_t*)ev + sizeof(LV2_Event);
+}
+
+
+/** Write an event at @a iter.
+ * The event (if any) pointed to by @a iter will be overwritten, and @a iter
+ * incremented to point to the following event (i.e. several calls to this
+ * function can be done in sequence without twiddling iter in-between).
+ * @return True if event was written, otherwise false (buffer is full). */
+static inline bool
+lv2_event_write_event(LV2_Event_Iterator* iter,
+ const LV2_Event* ev,
+ const uint8_t* data)
+{
+ if (iter->buf->capacity - iter->buf->size < sizeof(LV2_Event) + ev->size)
+ return false;
+
+ LV2_Event* const write_ev = (LV2_Event*)(
+ (uint8_t*)iter->buf->data + iter->offset);
+
+ *write_ev = *ev;
+ memcpy((uint8_t*)write_ev + sizeof(LV2_Event), data, ev->size);
+ ++iter->buf->event_count;
+
+ const uint16_t size = lv2_event_pad_size(sizeof(LV2_Event) + ev->size);
+ iter->buf->size += size;
+ iter->offset += size;
+
+ return true;
+}
+
+#endif /* LV2_EVENT_HELPERS_H */
+
diff --git a/lv2/lv2plug.in/ns/ext/event/event.h b/lv2/lv2plug.in/ns/ext/event/event.h
new file mode 100644
index 0000000..2c340ba
--- /dev/null
+++ b/lv2/lv2plug.in/ns/ext/event/event.h
@@ -0,0 +1,281 @@
+/*
+ LV2 Event Extension
+ Copyright 2008-2011 David Robillard <http://drobilla.net>
+ Copyright 2006-2007 Lars Luthman <lars.luthman@gmail.com>
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#ifndef LV2_EVENT_H
+#define LV2_EVENT_H
+
+#define LV2_EVENT_URI "http://lv2plug.in/ns/ext/event"
+#define LV2_EVENT_AUDIO_STAMP 0
+
+#include <stdint.h>
+
+/**
+ @file event.h
+ C API for the LV2 Event extension <http://lv2plug.in/ns/ext/event>.
+
+ This extension is a generic transport mechanism for time stamped events
+ of any type (e.g. MIDI, OSC, ramps, etc). Each port can transport mixed
+ events of any type; the type of events and timestamps are defined by a URI
+ which is mapped to an integer by the host for performance reasons.
+
+ This extension requires the host to support the LV2 URI Map extension.
+ Any host which supports this extension MUST guarantee that any call to
+ the LV2 URI Map uri_to_id function with the URI of this extension as the
+ 'map' argument returns a value within the range of uint16_t.
+*/
+
+/**
+ The best Pulses Per Quarter Note for tempo-based uint32_t timestamps.
+ Equal to 2^12 * 5 * 7 * 9 * 11 * 13 * 17, which is evenly divisble
+ by all integers from 1 through 18 inclusive, and powers of 2 up to 2^12.
+*/
+static const uint32_t LV2_EVENT_PPQN = 3136573440U;
+
+/**
+ An LV2 event (header only).
+
+ LV2 events are generic time-stamped containers for any type of event.
+ The type field defines the format of a given event's contents.
+
+ This struct defines the header of an LV2 event. An LV2 event is a single
+ chunk of POD (plain old data), usually contained in a flat buffer (see
+ LV2_EventBuffer below). Unless a required feature says otherwise, hosts may
+ assume a deep copy of an LV2 event can be created safely using a simple:
+
+ memcpy(ev_copy, ev, sizeof(LV2_Event) + ev->size); (or equivalent)
+*/
+typedef struct {
+
+ /**
+ The frames portion of timestamp. The units used here can optionally be
+ set for a port (with the lv2ev:timeUnits property), otherwise this is
+ audio frames, corresponding to the sample_count parameter of the LV2 run
+ method (e.g. frame 0 is the first frame for that call to run).
+ */
+ uint32_t frames;
+
+ /**
+ The sub-frames portion of timestamp. The units used here can optionally
+ be set for a port (with the lv2ev:timeUnits property), otherwise this is
+ 1/(2^32) of an audio frame.
+ */
+ uint32_t subframes;
+
+ /**
+ The type of this event, as a number which represents some URI
+ defining an event type. This value MUST be some value previously
+ returned from a call to the uri_to_id function defined in the LV2
+ URI map extension (see lv2_uri_map.h).
+ There are special rules which must be followed depending on the type
+ of an event. If the plugin recognizes an event type, the definition
+ of that event type will describe how to interpret the event, and
+ any required behaviour. Otherwise, if the type is 0, this event is a
+ non-POD event and lv2_event_unref MUST be called if the event is
+ 'dropped' (see above). Even if the plugin does not understand an event,
+ it may pass the event through to an output by simply copying (and NOT
+ calling lv2_event_unref). These rules are designed to allow for generic
+ event handling plugins and large non-POD events, but with minimal hassle
+ on simple plugins that "don't care" about these more advanced features.
+ */
+ uint16_t type;
+
+ /**
+ The size of the data portion of this event in bytes, which immediately
+ follows. The header size (12 bytes) is not included in this value.
+ */
+ uint16_t size;
+
+ /* size bytes of data follow here */
+
+} LV2_Event;
+
+
+/**
+ A buffer of LV2 events (header only).
+
+ Like events (which this contains) an event buffer is a single chunk of POD:
+ the entire buffer (including contents) can be copied with a single memcpy.
+ The first contained event begins sizeof(LV2_EventBuffer) bytes after the
+ start of this struct.
+
+ After this header, the buffer contains an event header (defined by struct
+ LV2_Event), followed by that event's contents (padded to 64 bits), followed
+ by another header, etc:
+
+ | | | | | | |
+ | | | | | | | | | | | | | | | | | | | | | | | | |
+ |FRAMES |SUBFRMS|TYP|LEN|DATA..DATA..PAD|FRAMES | ...
+*/
+typedef struct {
+
+ /**
+ The contents of the event buffer. This may or may not reside in the
+ same block of memory as this header, plugins must not assume either.
+ The host guarantees this points to at least capacity bytes of allocated
+ memory (though only size bytes of that are valid events).
+ */
+ uint8_t* data;
+
+ /**
+ The size of this event header in bytes (including everything).
+
+ This is to allow for extending this header in the future without
+ breaking binary compatibility. Whenever this header is copied,
+ it MUST be done using this field (and NOT the sizeof this struct).
+ */
+ uint16_t header_size;
+
+ /**
+ The type of the time stamps for events in this buffer.
+ As a special exception, '0' always means audio frames and subframes
+ (1/UINT32_MAX'th of a frame) in the sample rate passed to instantiate.
+
+ INPUTS: The host must set this field to the numeric ID of some URI
+ defining the meaning of the frames/subframes fields of contained events
+ (obtained by the LV2 URI Map uri_to_id function with the URI of this
+ extension as the 'map' argument, see lv2_uri_map.h). The host must
+ never pass a plugin a buffer which uses a stamp type the plugin does not
+ 'understand'. The value of this field must never change, except when
+ connect_port is called on the input port, at which time the host MUST
+ have set the stamp_type field to the value that will be used for all
+ subsequent run calls.
+
+ OUTPUTS: The plugin may set this to any value that has been returned
+ from uri_to_id with the URI of this extension for a 'map' argument.
+ When connected to a buffer with connect_port, output ports MUST set this
+ field to the type of time stamp they will be writing. On any call to
+ connect_port on an event input port, the plugin may change this field on
+ any output port, it is the responsibility of the host to check if any of
+ these values have changed and act accordingly.
+ */
+ uint16_t stamp_type;
+
+ /**
+ The number of events in this buffer.
+
+ INPUTS: The host must set this field to the number of events contained
+ in the data buffer before calling run(). The plugin must not change
+ this field.
+
+ OUTPUTS: The plugin must set this field to the number of events it has
+ written to the buffer before returning from run(). Any initial value
+ should be ignored by the plugin.
+ */
+ uint32_t event_count;
+
+ /**
+ The size of the data buffer in bytes.
+ This is set by the host and must not be changed by the plugin.
+ The host is allowed to change this between run() calls.
+ */
+ uint32_t capacity;
+
+ /**
+ The size of the initial portion of the data buffer containing data.
+
+ INPUTS: The host must set this field to the number of bytes used
+ by all events it has written to the buffer (including headers)
+ before calling the plugin's run().
+ The plugin must not change this field.
+
+ OUTPUTS: The plugin must set this field to the number of bytes
+ used by all events it has written to the buffer (including headers)
+ before returning from run().
+ Any initial value should be ignored by the plugin.
+ */
+ uint32_t size;
+
+} LV2_Event_Buffer;
+
+
+/**
+ Opaque pointer to host data.
+*/
+typedef void* LV2_Event_Callback_Data;
+
+
+/**
+ Non-POD events feature.
+
+ To support this feature the host must pass an LV2_Feature struct to the
+ plugin's instantiate method with URI "http://lv2plug.in/ns/ext/event"
+ and data pointed to an instance of this struct. Note this feature
+ is not mandatory to support the event extension.
+*/
+typedef struct {
+
+ /**
+ Opaque pointer to host data.
+
+ The plugin MUST pass this to any call to functions in this struct.
+ Otherwise, it must not be interpreted in any way.
+ */
+ LV2_Event_Callback_Data callback_data;
+
+ /**
+ Take a reference to a non-POD event.
+
+ If a plugin receives an event with type 0, it means the event is a
+ pointer to some object in memory and not a flat sequence of bytes
+ in the buffer. When receiving a non-POD event, the plugin already
+ has an implicit reference to the event. If the event is stored AND
+ passed to an output, lv2_event_ref MUST be called on that event.
+ If the event is only stored OR passed through, this is not necessary
+ (as the plugin already has 1 implicit reference).
+
+ @param event An event received at an input that will not be copied to
+ an output or stored in any way.
+
+ @param context The calling context. Like event types, this is a mapped
+ URI, see lv2_context.h. Simple plugin with just a run() method should
+ pass 0 here (the ID of the 'standard' LV2 run context). The host
+ guarantees that this function is realtime safe iff @a context is
+ realtime safe.
+
+ PLUGINS THAT VIOLATE THESE RULES MAY CAUSE CRASHES AND MEMORY LEAKS.
+ */
+ uint32_t (*lv2_event_ref)(LV2_Event_Callback_Data callback_data,
+ LV2_Event* event);
+
+ /**
+ Drop a reference to a non-POD event.
+
+ If a plugin receives an event with type 0, it means the event is a
+ pointer to some object in memory and not a flat sequence of bytes
+ in the buffer. If the plugin does not pass the event through to
+ an output or store it internally somehow, it MUST call this function
+ on the event (more information on using non-POD events below).
+
+ @param event An event received at an input that will not be copied to an
+ output or stored in any way.
+
+ @param context The calling context. Like event types, this is a mapped
+ URI, see lv2_context.h. Simple plugin with just a run() method should
+ pass 0 here (the ID of the 'standard' LV2 run context). The host
+ guarantees that this function is realtime safe iff @a context is
+ realtime safe.
+
+ PLUGINS THAT VIOLATE THESE RULES MAY CAUSE CRASHES AND MEMORY LEAKS.
+ */
+ uint32_t (*lv2_event_unref)(LV2_Event_Callback_Data callback_data,
+ LV2_Event* event);
+
+} LV2_Event_Feature;
+
+
+#endif /* LV2_EVENT_H */
diff --git a/lv2/lv2plug.in/ns/ext/event/event.ttl b/lv2/lv2plug.in/ns/ext/event/event.ttl
new file mode 100644
index 0000000..67285aa
--- /dev/null
+++ b/lv2/lv2plug.in/ns/ext/event/event.ttl
@@ -0,0 +1,224 @@
+# LV2 Event Extension
+# Copyright 2008-2011 David Robillard <http://drobilla.net>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+@prefix dcs: <http://ontologi.es/doap-changeset#> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix ev: <http://lv2plug.in/ns/ext/event#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://drobilla.net/drobilla#me>
+ a foaf:Person ;
+ foaf:name "David Robillard" ;
+ foaf:homepage <http://drobilla.net/> ;
+ foaf:mbox <mailto:d@drobilla.net> ;
+ rdfs:seeAlso <http://drobilla.net/drobilla> .
+
+_:larsl
+ a foaf:Person ;
+ foaf:name "Lars Luthman" .
+
+<http://lv2plug.in/ns/ext/event>
+ a lv2:Specification ;
+ doap:license <http://opensource.org/licenses/isc> ;
+ doap:name "LV2 Event" ;
+ doap:shortdesc "A port-based real-time generic event interface." ;
+ rdfs:seeAlso <event-helpers.h> ;
+ doap:release [
+ doap:revision "1.4" ;
+ doap:created "2011-11-21" ;
+ doap:file-release <http://lv2plug.in/spec/lv2-event-1.4.tar.bz2> ;
+ dcs:blame <http://drobilla.net/drobilla#me> ;
+ dcs:changeset [
+ dcs:item [
+ rdfs:label "Update packaging."
+ ]
+ ]
+ ] , [
+ doap:revision "1.2" ;
+ doap:created "2011-05-26" ;
+ doap:file-release <http://lv2plug.in/spec/lv2-event-1.2.tar.bz2> ;
+ dcs:blame <http://drobilla.net/drobilla#me> ;
+ dcs:changeset [
+ dcs:item [
+ rdfs:label "Add build system (for installation)."
+ ] , [
+ rdfs:label "Convert documentation to HTML and use lv2:documentation."
+ ] , [
+ rdfs:label "Use lv2:Specification to be discovered as an extension."
+ ]
+ ]
+ ] , [
+ doap:revision "1.0" ;
+ doap:created "2010-11-24" ;
+ doap:file-release <http://lv2plug.in/spec/lv2-event-1.0.tar.gz> ;
+ dcs:blame <http://drobilla.net/drobilla#me> ;
+ dcs:changeset [
+ dcs:item [
+ rdfs:label "Initial release."
+ ]
+ ]
+ ] ;
+ doap:developer <http://drobilla.net/drobilla#me> ,
+ _:larsl ;
+ lv2:documentation """
+<p>This extension defines a generic time-stamped event port type, which can be
+used to create plugins that read and write real-time events, such as MIDI,
+OSC, or any other type of event payload. The type(s) of event supported by
+a port is defined in the data file for a plugin, for example:</p>
+<pre class="turtle-code">
+&lt;http://example.org/some-plugin&gt;
+ lv2:port [
+ a ev:EventPort, lv2:InputPort ;
+ lv2:index 0 ;
+ ev:supportsEvent &lt;http://lv2plug.in/ns/ext/midi#MidiEvent&gt; ;
+ lv2:symbol "midi_input" ;
+ lv2:name "MIDI input" ;
+ ] .
+</pre>
+""" .
+
+ev:EventPort
+ a rdfs:Class ;
+ rdfs:label "Event port" ;
+ rdfs:subClassOf lv2:Port ;
+ rdfs:comment """
+Ports of this type will be connected to a struct of type LV2_Event_Buffer,
+defined in event.h. These ports contain a sequence of generic events
+(possibly several types mixed in a single stream), the specific types of
+which are defined by some URI in another LV2 extension.
+""" .
+
+ev:Event
+ a rdfs:Class ;
+ rdfs:label "LV2 event" ;
+ rdfs:comment """
+A single generic time-stamped event.
+
+An ev:EventPort contains an LV2_Event_Buffer which contains a sequence
+of these events. The binary format of LV2 events is defined by the
+LV2_Event struct in event.h.
+
+Specific event types (e.g. MIDI, OSC) are defined by extensions, and should
+be rdfs:subClassOf this class.
+""" .
+
+ev:TimeStamp
+ a rdfs:Class ;
+ rdfs:label "LV2 event time stamp" ;
+ rdfs:comment """
+The time stamp of an Event.
+
+This defines the meaning of the 'frames' and 'subframes' fields of an
+LV2_Event (both unsigned 32-bit integers).
+""" .
+
+ev:FrameStamp
+ a rdfs:Class ;
+ rdfs:subClassOf ev:TimeStamp ;
+ rdfs:label "Audio frame time stamp" ;
+ rdfs:comment """
+The default time stamp unit for an LV2 event: the frames field represents
+audio frames (in the sample rate passed to intantiate), and the subframes
+field is 1/UINT32_MAX of a frame.
+""" .
+
+ev:generic
+ a lv2:PortProperty ;
+ rdfs:label "Generic event port" ;
+ rdfs:comment """
+Indicates that this port does something meaningful for any event type
+(e.g. event mixers, delays, serialisers, etc). If this property is set, hosts
+should consider the port suitable for any type of event. Otherwise, hosts
+should consider the port 'appropriate' only for the specific event types
+listed with :supportsEvent. Note that plugins must gracefully handle unknown
+event types whether or not this property is present.
+""" .
+
+ev:supportsEvent
+ a rdf:Property ;
+ rdfs:domain lv2:Port ;
+ rdfs:range ev:Event ;
+ rdfs:label "Supports event type" ;
+ rdfs:comment """
+Indicates that this port supports or "understands" a certain event type.
+For input ports, this means the plugin understands and does something useful
+with events of this type. For output ports, this means the plugin may generate
+events of this type. If the plugin never actually generates events of this type,
+but might pass them through from an input, this property should not be set (use
+ev:inheritsEvent for that).
+Plugins with event input ports must always gracefully handle any type of event,
+even if it does not 'support' it. This property should always be set for
+event types the plugin understands/generates so hosts can discover plugins
+appropriate for a given scenario (e.g. plugins with a MIDI input).
+Hosts are not expected to consider event ports suitable for some type of
+event if the relevant :supportsEvent property is not set, unless the
+ev:generic property for that port is also set.
+""" .
+
+ev:inheritsEvent
+ a rdf:Property ;
+ rdfs:domain lv2:Port ;
+ rdfs:range lv2:Port ;
+ rdfs:label "Inherits event type" ;
+ rdfs:comment """
+Indicates that this output port might pass through events that arrived at some
+other input port (or generate an event of the same type as events arriving at
+that input). The host must always check the stamp type of all outputs when
+connecting an input, but this property should be set whenever it applies.
+""" .
+
+ev:supportsTimeStamp
+ a rdf:Property ;
+ rdfs:domain lv2:Port ;
+ rdfs:range ev:TimeStamp ;
+ rdfs:label "Supports time stamp type" ;
+ rdfs:comment """
+Indicates that this port supports or "understands" a certain time stamp type.
+Meaningful only for input ports, the host must never connect a port to an
+event buffer with a time stamp type that isn't supported by the port.
+""" .
+
+ev:generatesTimeStamp
+ a rdf:Property ;
+ rdfs:domain lv2:Port ;
+ rdfs:range ev:TimeStamp ;
+ rdfs:label "Outputs time stamp type" ;
+ rdfs:comment """
+Indicates that this port may output a certain time stamp type, regardless of
+the time stamp type of any input ports. If the port outputs stamps based on
+what type inputs are connected to, this property should not be set (use the
+ev:inheritsTimeStamp property for that). Hosts MUST check the time_stamp value
+of any output port buffers after a call to connect_port on ANY event input
+port on the plugin. If the plugin changes the stamp_type field of an output
+event buffer during a call to run(), the plugin must call the
+stamp_type_changed function provided by the host in the LV2_Event_Feature
+struct, if it is non-NULL.
+""" .
+
+ev:inheritsTimeStamp
+ a rdf:Property ;
+ rdfs:domain lv2:Port ;
+ rdfs:range lv2:Port ;
+ rdfs:label "Inherits time stamp type" ;
+ rdfs:comment """
+Indicates that this port follows the time stamp type of an input port.
+This property is not necessary, but it should be set for outputs that
+base their output type on an input port so the host can make more sense
+of the plugin and provide a more sensible interface.
+""" .
diff --git a/lv2/lv2plug.in/ns/ext/event/ext.pc.in b/lv2/lv2plug.in/ns/ext/event/ext.pc.in
new file mode 120000
index 0000000..03dd044
--- /dev/null
+++ b/lv2/lv2plug.in/ns/ext/event/ext.pc.in
@@ -0,0 +1 @@
+../../../../../ext.pc.in \ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/event/manifest.ttl b/lv2/lv2plug.in/ns/ext/event/manifest.ttl
new file mode 100644
index 0000000..fa12f94
--- /dev/null
+++ b/lv2/lv2plug.in/ns/ext/event/manifest.ttl
@@ -0,0 +1,9 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/event>
+ a lv2:Specification ;
+ lv2:minorVersion 1 ;
+ lv2:microVersion 4 ;
+ rdfs:seeAlso <event.ttl> .
+
diff --git a/lv2/lv2plug.in/ns/ext/event/waf b/lv2/lv2plug.in/ns/ext/event/waf
new file mode 120000
index 0000000..5235032
--- /dev/null
+++ b/lv2/lv2plug.in/ns/ext/event/waf
@@ -0,0 +1 @@
+../../../../../waf \ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/event/wscript b/lv2/lv2plug.in/ns/ext/event/wscript
new file mode 120000
index 0000000..7e2c01b
--- /dev/null
+++ b/lv2/lv2plug.in/ns/ext/event/wscript
@@ -0,0 +1 @@
+../../../../../ext.wscript \ No newline at end of file