aboutsummaryrefslogtreecommitdiffstats
path: root/ext
diff options
context:
space:
mode:
Diffstat (limited to 'ext')
-rw-r--r--ext/atom-port.lv2/atom-port.ttl127
-rw-r--r--ext/atom-port.lv2/manifest.ttl7
-rw-r--r--ext/atom.lv2/atom.h232
-rw-r--r--ext/atom.lv2/atom.ttl272
-rw-r--r--ext/atom.lv2/manifest.ttl7
-rw-r--r--ext/command.lv2/command.ttl73
-rw-r--r--ext/command.lv2/manifest.ttl7
-rw-r--r--ext/contexts.lv2/contexts.h72
-rw-r--r--ext/contexts.lv2/contexts.ttl202
-rw-r--r--ext/contexts.lv2/manifest.ttl7
-rw-r--r--ext/contexts.lv2/test.c65
-rw-r--r--ext/data-access.lv2/data-access.h57
-rw-r--r--ext/data-access.lv2/data-access.ttl46
-rw-r--r--ext/data-access.lv2/manifest.ttl7
-rw-r--r--ext/dyn-manifest.lv2/Makefile20
-rw-r--r--ext/dyn-manifest.lv2/dyn-manifest.h245
-rw-r--r--ext/dyn-manifest.lv2/dyn-manifest.ttl109
-rw-r--r--ext/dyn-manifest.lv2/manifest.ttl7
-rw-r--r--ext/event.lv2/event-helpers.h243
-rw-r--r--ext/event.lv2/event.h259
-rw-r--r--ext/event.lv2/event.ttl192
-rw-r--r--ext/event.lv2/lv2_event.pc.in10
-rw-r--r--ext/event.lv2/manifest.ttl7
-rw-r--r--ext/files.lv2/files.h61
-rw-r--r--ext/files.lv2/files.ttl94
-rw-r--r--ext/files.lv2/manifest.ttl7
-rw-r--r--ext/host-info.lv2/host-info.ttl116
-rw-r--r--ext/host-info.lv2/manifest.ttl7
-rw-r--r--ext/instance-access.lv2/instance-access.h39
-rw-r--r--ext/instance-access.lv2/instance-access.ttl46
-rw-r--r--ext/instance-access.lv2/manifest.ttl7
-rw-r--r--ext/midi.lv2/manifest.ttl7
-rw-r--r--ext/midi.lv2/midi.ttl87
-rw-r--r--ext/osc.lv2/lv2_osc.c314
-rw-r--r--ext/osc.lv2/lv2_osc.pc.in10
-rw-r--r--ext/osc.lv2/lv2_osc_print.c66
-rw-r--r--ext/osc.lv2/lv2_osc_test.c55
-rw-r--r--ext/osc.lv2/manifest.ttl7
-rw-r--r--ext/osc.lv2/osc-print.h42
-rw-r--r--ext/osc.lv2/osc.h123
-rw-r--r--ext/osc.lv2/osc.ttl56
-rw-r--r--ext/parameter.lv2/manifest.ttl7
-rw-r--r--ext/parameter.lv2/parameter.ttl110
-rw-r--r--ext/persist.lv2/manifest.ttl7
-rw-r--r--ext/persist.lv2/persist.h177
-rw-r--r--ext/persist.lv2/persist.ttl116
-rw-r--r--ext/polymorphic-port.lv2/manifest.ttl7
-rw-r--r--ext/polymorphic-port.lv2/polymorphic-port.h63
-rw-r--r--ext/polymorphic-port.lv2/polymorphic-port.ttl71
-rw-r--r--ext/port-groups.lv2/manifest.ttl7
-rw-r--r--ext/port-groups.lv2/port-groups.ttl489
-rw-r--r--ext/presets.lv2/manifest.ttl7
-rw-r--r--ext/presets.lv2/presets.ttl88
-rw-r--r--ext/resize-port.lv2/manifest.ttl7
-rw-r--r--ext/resize-port.lv2/resize-port.h46
-rw-r--r--ext/resize-port.lv2/resize-port.ttl85
-rw-r--r--ext/string-port.lv2/manifest.ttl6
-rw-r--r--ext/string-port.lv2/string-port.h58
-rw-r--r--ext/string-port.lv2/string-port.ttl105
-rw-r--r--ext/uri-map.lv2/manifest.ttl6
-rw-r--r--ext/uri-map.lv2/uri-map.h87
-rw-r--r--ext/uri-map.lv2/uri-map.ttl54
-rw-r--r--ext/variables.lv2/manifest.ttl7
-rw-r--r--ext/variables.lv2/variables-private.h48
-rw-r--r--ext/variables.lv2/variables.h144
-rw-r--r--ext/variables.lv2/variables.ttl118
66 files changed, 5337 insertions, 0 deletions
diff --git a/ext/atom-port.lv2/atom-port.ttl b/ext/atom-port.lv2/atom-port.ttl
new file mode 100644
index 0000000..7533606
--- /dev/null
+++ b/ext/atom-port.lv2/atom-port.ttl
@@ -0,0 +1,127 @@
+# LV2 Atom Port Extension
+# Copyright (C) 2010 David Robillard <d@drobilla.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix aport: <http://lv2plug.in/ns/ext/atom-port#> .
+@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema> .
+
+<http://lv2plug.in/ns/ext/atom-port>
+ a lv2:Specification ;
+ doap:name "LV2 Atom Port" ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "David Robillard" ;
+ foaf:homepage <http://drobilla.net/> ;
+ rdfs:seeAlso <http://drobilla.net/drobilla.rdf>
+ ] ;
+ rdfs:comment """
+This extension describes port types that hold polymorphic values
+(<a href="http://lv2plug.in/ns/ext/atom#Atom">atom:Atom</a>). There are
+two such port types with equivalent buffer formats but different semantics:
+value ports (aport:ValuePort) and message ports (aport:MessagePort).
+""" .
+
+
+aport:AtomPort a rdfs:Class ;
+ rdfs:label "Atom Port" ;
+ rdfs:subClassOf lv2:Port ;
+ rdfs:comment """
+A port which contains a polymorphic value, or "atom".
+Ports of this type will be connected to a 32-bit aligned <a
+href="http://lv2plug.in/ns/ext/atom#Atom">atom:Atom</a> (i.e. a uint32_t type,
+immediately followed by a uint32_t size, immediately followed by that many
+bytes of data).
+
+This is an abstract port type. A port that is a aport:AtomPort MUST also
+have a more descriptive type that is a subClassOf aport:AtomPort which
+defines the port's semantics (typically aport:ValuePort or aport:MessagePort).
+
+Before calling a method on the plugin that writes to an AtomPort output,
+the host MUST set the size of the Atom in that output to the amount of
+available memory immediately following the Atom header. The plugin MUST
+write a valid Atom to that port (leaving it untouched is illegal). If there
+is no reasonable value to write to the port, the plugin MUST write null
+(the atom with both type and size equal to zero).
+""" .
+
+
+#aport:respondsWith a rdf:Property ;
+# rdfs:domain aport:MessagePort ;
+# rdfs:range lv2:Symbol ;
+# rdfs:label "responds with" ;
+# rdfs:comment """
+#Indicates that a message port responds to messages via the port with the
+#given symbol on the same plugin instance. If
+#<pre>input aport:respondsWith output</pre> then after running the plugin with
+#a message <em>m</em> in <code>input</code> the host SHOULD interpret the aport:
+#in <code>output</code> as the response to <em>m</em>.
+#""" .
+
+
+aport:ValuePort a rdfs:Class ;
+ rdfs:label "Value Port" ;
+ rdfs:subClassOf aport:AtomPort ;
+ rdfs:comment """
+An AtomPort that interprets its data as a persistent and time-independent
+"value".
+<ul>
+<li>If a plugin has fixed input values for all ports, all ValuePort outputs
+are also fixed regardless of the number of times the plugin is run.</li>
+<li>If a plugin has fixed input values for all ports except a ValuePort,
+each value V of that ValuePort corresponds to a single set of outputs
+for all ports.</li>
+<li>If an aport:ValuePort contains a reference then the blob it refers to is
+constant; plugin MUST NOT modify the blob in any way.</li>
+</ul>
+Value ports can be thought of as purely functional ports: if a plugin
+callback has only value ports, then the plugin callback is a pure function.
+""" .
+
+
+aport:MessagePort a rdfs:Class ;
+ rdfs:label "Message Port" ;
+ rdfs:subClassOf aport:AtomPort ;
+ rdfs:comment """
+An AtomPort that consumes or executes its value as a "message". The contents
+of a MessagePort are considered transient and/or time-dependent, and only
+apply for a single run invocation. Unlike a ValuePort, a MessagePort may
+be used to manipulate and access internal plugin state.
+
+Intuitively, a MessagePort contains a "command" or "event" (which is reacted
+to), NOT a "value" or "signal" (which is computed with).
+""" .
+
+aport:supports a rdf:Property ;
+ rdfs:domain lv2:Port ;
+ rdfs:range atom:AtomType ;
+ rdfs:label "supports" ;
+ rdfs:comment """
+Indicates that an atom port supports a certain value type. This is distinct
+from the port type - e.g. the port type ValuePort can hold atoms with many
+different types. This property is used to describe which atom types
+a port ``understands''.
+""" .
+
diff --git a/ext/atom-port.lv2/manifest.ttl b/ext/atom-port.lv2/manifest.ttl
new file mode 100644
index 0000000..e681793
--- /dev/null
+++ b/ext/atom-port.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/atom-port>
+ a lv2:Specification ;
+ rdfs:seeAlso <atom-port.ttl> .
+
diff --git a/ext/atom.lv2/atom.h b/ext/atom.lv2/atom.h
new file mode 100644
index 0000000..fe7a373
--- /dev/null
+++ b/ext/atom.lv2/atom.h
@@ -0,0 +1,232 @@
+/* lv2_atom.h - C header file for the LV2 Atom 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
+ */
+
+/** @file
+ * C header for the LV2 Atom extension <http://lv2plug.in/ns/ext/atom>.
+ * This extension defines convenience structs that
+ * should match the definition of the built-in types of the atom extension.
+ * The layout of atoms in this header must match the description in RDF.
+ * The RDF description of an atom type should be considered normative.
+ * This header is a non-normative (but hopefully accurate) implementation
+ * of that specification.
+ */
+
+#ifndef LV2_ATOM_H
+#define LV2_ATOM_H
+
+#define LV2_ATOM_URI "http://lv2plug.in/ns/ext/atom"
+#define LV2_BLOB_SUPPORT_URI "http://lv2plug.in/ns/ext/atom#blobSupport"
+
+#define LV2_ATOM_REFERENCE_TYPE 0
+
+#include <stdint.h>
+#include <stddef.h>
+
+#define LV2_ATOM_FROM_EVENT(ev) ((LV2_Atom*)&((LV2_Event*)ev)->type)
+
+/** An LV2 Atom.
+ *
+ * An "Atom" is a generic chunk of memory with a given type and size.
+ * The type field defines how to interpret an atom.
+ *
+ * All atoms are by definition Plain Old Data (POD) and may be safely
+ * copied (e.g. with memcpy) using the size field, except atoms with type 0.
+ * An atom with type 0 is a reference, and may only be used via the functions
+ * provided in LV2_Blob_Support (e.g. it MUST NOT be manually copied).
+ *
+ * Note that an LV2_Atom is the latter two fields of an LV2_Event as defined
+ * by the <a href="http://lv2plug.in/ns/ext/event">LV2 events extension</a>.
+ * The host MAY marshal an Event to an Atom simply by pointing to the offset
+ * of the 'type' field of the LV2_Event, which is also the type field (i.e. start)
+ * of a valid LV2_Atom. The macro LV2_ATOM_FROM_EVENT is provided in this
+ * header for this purpose.
+ */
+typedef struct _LV2_Atom {
+
+ /** The type of this atom. This number represents a URI, mapped to an
+ * integer using the extension <http://lv2plug.in/ns/ext/uri-map>
+ * with "http://lv2plug.in/ns/ext/atom" as the 'map' argument.
+ * Type 0 is a special case which indicates this atom
+ * is a reference and MUST NOT be copied manually.
+ */
+ uint16_t type;
+
+ /** The size of this atom, not including this header, in bytes. */
+ uint16_t size;
+
+ /** Size bytes of data follow here */
+ uint8_t body[];
+
+} LV2_Atom;
+
+/** Reference, an LV2_Atom with type 0 */
+typedef LV2_Atom LV2_Reference;
+
+/** The body of an LV2_Atom with type atom:Vector
+ */
+typedef struct _LV2_Vector_Body {
+
+ /** The size of each element in the vector */
+ uint16_t elem_count;
+
+ /** The type of each element in the vector */
+ uint16_t elem_type;
+
+ /** Elements follow here */
+ uint8_t elems[];
+
+} LV2_Vector_Body;
+
+
+/** The body of an LV2_Atom with type atom:Triple
+ */
+typedef struct _LV2_Triple_Body {
+ uint32_t subject;
+ uint32_t predicate;
+ LV2_Atom object;
+} LV2_Triple_Body;
+
+
+/** The body of an LV2_Atom with type atom:Message
+ */
+typedef struct _LV2_Message_Body {
+ uint32_t selector; /***< Selector URI mapped to integer */
+ LV2_Atom triples; /***< Always an atom:Triples */
+} LV2_Message_Body;
+
+
+/* Everything below here is related to blobs, which are dynamically allocated
+ * atoms that are not necessarily POD. This functionality is optional,
+ * hosts may support atoms without implementing blob support.
+ * Blob support is an LV2 Feature.
+ */
+
+
+typedef void* LV2_Blob_Data;
+
+/** Dynamically Allocated LV2 Blob.
+ *
+ * This is a blob of data of any type, dynamically allocated in memory.
+ * Unlike an LV2_Atom, a blob is not necessarily POD. Plugins may only
+ * refer to blobs via a Reference (an LV2_Atom with type 0), there is no
+ * way for a plugin to directly create, copy, or destroy a Blob.
+ */
+typedef struct _LV2_Blob {
+
+ /** Pointer to opaque data.
+ *
+ * Plugins MUST NOT interpret this data in any way. Hosts may store
+ * whatever information they need to associate with references here.
+ */
+ LV2_Blob_Data data;
+
+ /** Get blob's type as a URI mapped to an integer.
+ *
+ * The return value may be any type URI, mapped to an integer with the
+ * URI Map extension. If this type is an LV2_Atom type, get returns
+ * a pointer to the LV2_Atom header (e.g. a blob with type atom:Int32
+ * does NOT return a pointer to a int32_t).
+ */
+ uint32_t (*type)(struct _LV2_Blob* blob);
+
+ /** Get blob's body.
+ *
+ * Returns a pointer to the start of the blob data. The format of this
+ * data is defined by the return value of the type method. It MUST NOT
+ * be used in any way by code which does not understand that type.
+ */
+ void* (*get)(struct _LV2_Blob* blob);
+
+} LV2_Blob;
+
+
+typedef void* LV2_Blob_Support_Data;
+
+typedef void (*LV2_Blob_Destroy)(LV2_Blob* blob);
+
+/** The data field of the LV2_Feature for the LV2 Atom extension.
+ *
+ * A host which supports this extension must pass an LV2_Feature struct to the
+ * plugin's instantiate method with 'URI' "http://lv2plug.in/ns/ext/atom" and
+ * 'data' pointing to an instance of this struct. All fields of this struct,
+ * MUST be set to non-NULL values by the host (except possibly data).
+ */
+typedef struct {
+
+ /** Pointer to opaque data.
+ *
+ * The plugin MUST pass this to any call to functions in this struct.
+ * Otherwise, it must not be interpreted in any way.
+ */
+ LV2_Blob_Support_Data data;
+
+ /** The size of a reference, in bytes.
+ *
+ * This value is provided by the host so plugins can allocate large
+ * enough chunks of memory to store references.
+ */
+ size_t reference_size;
+
+ /** Initialize a reference to point to a newly allocated Blob.
+ *
+ * @param data Must be the data member of this struct.
+ * @param reference Pointer to an area of memory at least as large as
+ * the reference_size field of this struct. On return, this will
+ * be the unique reference to the new blob which is owned by the
+ * caller. Caller MUST NOT pass a valid reference.
+ * @param destroy Function to destroy a blob of this type. This function
+ * MUST clean up any resources contained in the blob, but MUST NOT
+ * attempt to free the memory pointed to by its LV2_Blob* parameter.
+ * @param type Type of blob to allocate (URI mapped integer).
+ * @param size Size of blob to allocate in bytes.
+ */
+ void (*lv2_blob_new)(LV2_Blob_Support_Data data,
+ LV2_Reference* reference,
+ LV2_Blob_Destroy destroy_func,
+ uint32_t type,
+ size_t size);
+
+ /** Return a pointer to the Blob referred to by @a ref.
+ *
+ * The returned value MUST NOT be used in any way other than by calling
+ * methods defined in LV2_Blob (e.g. it MUST NOT be copied or destroyed).
+ */
+ LV2_Blob* (*lv2_reference_get)(LV2_Blob_Support_Data data,
+ LV2_Reference* ref);
+
+ /** Copy a reference.
+ * This copies a reference but not the blob it refers to,
+ * i.e. after this call @a dst and @a src refer to the same LV2_Blob.
+ */
+ void (*lv2_reference_copy)(LV2_Blob_Support_Data data,
+ LV2_Reference* dst,
+ LV2_Reference* src);
+
+ /** Reset (release) a reference.
+ * After this call, @a ref is invalid. Use of this function is only
+ * necessary if a plugin makes a copy of a reference it does not later
+ * send to an output (which transfers ownership to the host).
+ */
+ void (*lv2_reference_reset)(LV2_Blob_Support_Data data,
+ LV2_Reference* ref);
+
+} LV2_Blob_Support;
+
+
+#endif /* LV2_ATOM_H */
+
diff --git a/ext/atom.lv2/atom.ttl b/ext/atom.lv2/atom.ttl
new file mode 100644
index 0000000..ad957f3
--- /dev/null
+++ b/ext/atom.lv2/atom.ttl
@@ -0,0 +1,272 @@
+# LV2 Atom Extension
+# Copyright (C) 2007-2010 David Robillard <d@drobilla.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema> .
+
+<http://lv2plug.in/ns/ext/atom>
+ a lv2:Specification ;
+ doap:name "LV2 Atom" ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "David Robillard" ;
+ foaf:homepage <http://drobilla.net/> ;
+ rdfs:seeAlso <http://drobilla.net/drobilla.rdf>
+ ] ;
+ rdfs:comment """
+This extension defines a generic format for a typed piece of data, called an
+"atom" (e.g. integers, strings, buffers, data structures, etc). Atoms allow
+LV2 plugins and host to communicate and store values of any type and size via
+a generic mechanism (e.g. port buffers, event payloads, shared data, etc.).
+Atoms are simple a chunk of memory with a type and a size, and are (with
+one exception) Plain Old Data (POD) and may be safely copied (e.g. with a
+simple call to <code>memcpy</code>). Because they are POD, hosts and plugins
+can communicate atoms of any type, even if they do not understand that type.
+This allows two plugins that both understand some type to be used together in
+a host that does not itself understand that type, or allows a host to send
+atoms "through" a plugin that does not understand them (for e.g. routing,
+delaying, or buffering plugins).
+
+Atoms as defined by this extension can be trivially constructed in-place
+from events as defined by the <a href="http://lv2plug.in/ns/ext/event">LV2
+Event</a> extension. A valid LV2_Atom (see atom.h) is contained within
+any valid LV2_Event (see event.h). An LV2_Event is simply an LV2_Atom
+with a time stamp header prepended. Atoms should be used anywhere a "value"
+needs to be stored or communicated, which allows implementations to be
+polymorphic and extensible.
+
+Optionally, the host MAY support "Blobs", which are dynamically allocated
+chunks of memory that (unlike Atoms) are not necessarily POD. Blobs are
+accessed via references, which are a special case of Atom that always have
+type 0, are not POD, and can only be copied using host provided functions.
+This allows plugins and hosts to work with data of any type at all.
+Blob data MUST NOT be used in any way by an implementation that does not
+understand that blob type (meaningful type-oblivious use is impossible,
+e.g. the blob pointer may not point to actual memory).
+
+This extension requires the host to support the <a
+href="http://lv2plug.in/ns/ext/uri-map">LV2 URI Map</a> extension.
+""" .
+
+
+atom:AtomType a rdfs:Class ;
+ rdfs:label "LV2 Atom Type" ;
+ rdfs:comment """
+Base class for all types of LV2 Atom.
+
+All Atom types (instances of this class, which are themselves classes)
+must define a precise binary layout for that type of atom, which dictates
+the format of the data following the LV2_Atom header. Pedantically, this
+class refers to the type of memory starting where the LV2_Atom header starts,
+i.e. a chunk of memory with any type that is a subClassOf atom:AtomType by
+definition starts with an LV2_Atom. The area after the header is referred
+to as the atom's "body".
+
+The URIs of subclasses of atom:AtomType are mapped to integers and used as
+the type field of an LV2_Atom. If a plugin or host does not understand
+the type of an LV2_Atom, that atom SHOULD simply be ignored (though it
+MAY be simply copied if it is not a reference).
+
+All atoms are POD by definition, except references, which have type 0.
+An atom MUST NOT contain a reference. It is safe to copy any type of
+atom except type 0 with a simple memcpy using the size field, even if the
+implementation does not understand the actual type of that atom.
+""" .
+
+
+atom:Reference a atom:AtomType ;
+ rdfs:label "Reference" ;
+ rdfs:comment """
+Reference to a blob. The actual contents of a reference are opaque and host
+specific, and must not be copied, serialized, or otherwise interpreted by
+a plugin, except by using functions provided by the host.
+
+References are a special case: a reference atom always has type 0.
+The NULL reference is the unique atom with type 0 and size 0.
+""" .
+
+
+atom:String a atom:AtomType ;
+ rdfs:label "String" ;
+ rdfs:comment """
+A UTF-8 encoded string, where LV2_Atom.size refers to the length of the
+string in bytes (not characters).
+""" .
+
+
+atom:URIInt a atom:AtomType ;
+ rdfs:label "URI mapped to an integer" ;
+ rdfs:comment """
+A uint32_t interpreted as a URI mapped to an integer using the LV2
+URI map extension &lt;http://lv2plug.in/ns/ext/uri-map&gt;. Size is
+always 4.
+""" .
+
+
+atom:Message a atom:AtomType ;
+ rdfs:label "Message" ;
+ rdfs:comment """
+A message is a communication from one component to another. Messages
+consist of a selector URI, and a set of RDF triples. The selector URI
+dictates how the triples are to be interpreted (e.g. the selector can
+be used as a "verb" to build commands).
+
+The payload of a message is always an atom:Triples so hosts and plugins can
+always work with message data (e.g. to serialise for saved state or an undo
+stack), even if they do not specifically understand a particular message.
+
+In memory, a Message is simply a uint32_t selector (a URI mapped integer)
+followed by an atom:Triples.
+""" .
+
+
+atom:Vector a atom:AtomType ;
+ rdfs:label "Vector" ;
+ rdfs:comment """
+A POD homogeneous sequence of atoms with equivalent type and size.
+
+The body of a vector begins with
+<pre>
+uint16_t elem_count; // The number of elements in the vector
+uint16_t elem_type; // The type of each element
+</pre>
+followed by <code>elem_count</code> bodies of atoms of type
+<code>elem_type</code>, each with equivalent size. For variably sized
+content types, this size can be calculated using the total byte size of the
+vector, e.g.
+<pre>
+uint16_t elem_size = (vector.size - (2 * sizeof(uint16_t))) / vector.count);
+</pre>
+Note that it is possible to construct a valid Atom for each element of the
+vector, even by an implementation which does not understand <code>type</code>.
+
+For example, an atom:Vector containing 42 elements of type atom:Int32 looks
+like this in memory:
+<pre>
+uint16_t atom_type = uri_map(atom:Vector)
+uint16_t atom_size = (2 * sizeof(uint16_t)) + (42 * sizeof(int32_t))
+uint16_t elem_count = 42
+uint16_t elem_type = uri_map(atom:Int32)
+int32_t contents[42] = ...
+</pre>
+""" .
+
+
+atom:Triple a atom:AtomType ;
+ rdfs:label "RDF triple" ;
+ rdfs:comment """
+A single RDF triple.
+
+The subject and predicate of an RDF triple are implicitly URIs, this in an
+atom:Triple they are stored as URI mapped integers with type tags and sizes
+omitted.
+
+An atom:Triple in memory is two uint32_t's followed by an LV2_Atom:
+<pre>
+uint32_t subject;
+uint32_t predicate;
+LV2_Atom object;
+</pre>
+""" .
+
+
+atom:Triples a atom:AtomType ;
+ rdfs:label "RDF triple set" ;
+ rdfs:comment """
+A description in RDF (i.e. a set of triples).
+
+An atom:Triples contains any number of RDF triples, describing one or
+several resources. The subject and predicate of all triples are implicitly
+URI mapped integers, type tags are omitted. The object of triples may be
+any atom.
+
+An atom:Triples in memory is a sequence of atom:Triple where each atom:Triple
+is immediately followed by the next (without time stamps or sizes), with
+padding to ensure each subject is 32-bit aligned, e.g.:
+<pre>
+uint32_t subject1;
+uint32_t predicate1;
+LV2_Atom object1;
+uint8_t pad[1]; /* e.g. if object1.size == 3 */
+uint32_t subject2;
+uint32_t predicate2;
+LV2_Atom object2;
+...
+</pre>
+""" .
+
+
+atom:Blank a atom:AtomType ;
+ rdfs:label "Blank (anonymous resource)" ;
+ rdfs:comment """
+A description of an RDF resource with no URI (a resource with blank node
+ID), e.g. the resource of type ex:Foo in the following Turtle description:
+<code>&lt;&gt; ex:hasThing [ a ex:Thing ]</code>
+
+An atom:Blank is conceptually a dictionary where keys (RDF predicates) are
+URI mapped integers, and values (RDF objects) are any atom.
+
+An atom:Blank in memory is like an atom:Triples, but with subjects omitted:
+<pre>
+uint32_t predicate1;
+LV2_Atom object1;
+uint32_t predicate2;
+LV2_Atom object2;
+...
+</pre>
+""" .
+
+
+atom:Bang a atom:AtomType ; rdfs:label "Bang (generic activity), size=0" .
+atom:Byte a atom:AtomType ; rdfs:label "A byte" .
+atom:Int32 a atom:AtomType ; rdfs:label "Signed 32-bit Integer" .
+atom:Bool a atom:AtomType ; rdfs:label "atom:Int32 where 0=false, 1=true" .
+atom:Float32 a atom:AtomType ; rdfs:label "32-bit Floating Point Number" .
+atom:Float64 a atom:AtomType ; rdfs:label "64-bit Floating Point Number" .
+
+
+atom:blobSupport a lv2:Feature ;
+ rdfs:label "Blob support" ;
+ rdfs:comment """
+Support for dynamically allocated blobs. If a host supports this feature, it
+MUST pass an LV2_Feature with URI http://lv2plug.in/ns/ext/atom#blobSupport
+and a pointer to LV2_Blob_Support as data to the plugin's instantiate method.
+See atom.h for details.
+""" .
+
+
+atom:BlobType a rdfs:Class ;
+ rdfs:label "Blob Type" ;
+ rdfs:comment """
+Base class for all types of dynamically allocated LV2 blobs. Blobs can be of
+any type at all, there are no restrictions on the binary format or contents
+of a blob. Blobs are dynamically allocated by the host (or a plugin via
+the host), and unlike Atoms are not necessarily POD.
+
+The type of a blob MAY be a atom:AtomType, in which case the start of the
+blob data is the start of the Atom header (LV2_Atom).
+""" .
+
diff --git a/ext/atom.lv2/manifest.ttl b/ext/atom.lv2/manifest.ttl
new file mode 100644
index 0000000..65a4e6e
--- /dev/null
+++ b/ext/atom.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/atom>
+ a lv2:Specification ;
+ rdfs:seeAlso <atom.ttl> .
+
diff --git a/ext/command.lv2/command.ttl b/ext/command.lv2/command.ttl
new file mode 100644
index 0000000..ab8b82b
--- /dev/null
+++ b/ext/command.lv2/command.ttl
@@ -0,0 +1,73 @@
+# LV2 Command Extension
+# Copyright (C) 2010 David Robillard <d@drobilla.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix cmd: <http://lv2plug.in/ns/ext/command#> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+
+<http://lv2plug.in/ns/ext/command>
+ a lv2:Specification ;
+ doap:name "LV2 Command" ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "David Robillard" ;
+ foaf:homepage <http://drobilla.net/> ;
+ rdfs:seeAlso <http://drobilla.net/drobilla.rdf>
+ ] ;
+ rdfs:comment """
+This extension defines special port types used for controlling and inspecting a
+plugin instance by sending messages/commands and receiving responses to them.
+It also allows plugins to send status updates to the host. The port types in
+this extension only define an abstract notion of plugin control, not actual
+data types and/or message semantics. They must be used with some other port
+data type (e.g. event) to define the actual data format of port buffers.
+As a result, this extension can be used in conjunction with any extension
+that defines a port type suitable for controlling plugins.
+""" .
+
+cmd:CommandPort a rdfs:Class ;
+ rdfs:label "Command Port" ;
+ rdfs:subClassOf lv2:Port ;
+ rdfs:comment """
+An input port used to control a plugin instance. A plugin has
+at most 1 CommandPort. A CommandPort is always an lv2:InputPort. Hosts or
+UIs send messages to the command port in order to control a plugin instance
+in any way. This is an abstract port class, the actual format and semantics
+of the port buffer (and messages) are defined by some other port type.
+""" .
+
+cmd:StatusPort a rdfs:Class ;
+ rdfs:label "Command Port" ;
+ rdfs:subClassOf lv2:Port ;
+ rdfs:comment """
+An output port used to notify the host about changes to a plugin instance and
+responses to commands. A plugin has at most 1 StatusPort. A StatusPort is
+always an lv2:OutputPort. Any response to a command sent to the CommandPort
+of the plugin will appear in the StatusPort output. The plugin may also emit
+other messages (i.e. the contents of a StatusPort are not necessarily responses
+to commands). This is an abstract port class, the actual format and semantics
+of the port buffer (and messages) are defined by some other port type.
+""" .
+
diff --git a/ext/command.lv2/manifest.ttl b/ext/command.lv2/manifest.ttl
new file mode 100644
index 0000000..0590b62
--- /dev/null
+++ b/ext/command.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/command>
+ a lv2:Specification ;
+ rdfs:seeAlso <command.ttl> .
+
diff --git a/ext/contexts.lv2/contexts.h b/ext/contexts.lv2/contexts.h
new file mode 100644
index 0000000..c6e8ef2
--- /dev/null
+++ b/ext/contexts.lv2/contexts.h
@@ -0,0 +1,72 @@
+/* LV2 Contexts Extension
+ * Copyright (C) 2007-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 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 General Public License
+ * for more 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.
+ */
+
+/** @file
+ * C header for the LV2 Contexts extension
+ * <http://lv2plug.in/ns/ext/contexts>.
+ */
+
+#ifndef LV2_CONTEXTS_H
+#define LV2_CONTEXTS_H
+
+#include <stdint.h>
+
+#define LV2_CONTEXTS_URI "http://lv2plug.in/ns/ext/contexts"
+
+#define LV2_CONTEXT_MESSAGE "http://lv2plug.in/ns/ext/contexts#MessageContext"
+
+static inline void
+lv2_contexts_set_port_valid(void* flags, uint32_t index) {
+ ((uint8_t*)flags)[index / 8] |= 1 << (index % 8);
+}
+
+static inline void
+lv2_contexts_unset_port_valid(void* flags, uint32_t index) {
+ ((uint8_t*)flags)[index / 8] &= ~(1 << (index % 8));
+}
+
+static inline int
+lv2_contexts_port_is_valid(const void* flags, uint32_t index) {
+ return (((uint8_t*)flags)[index / 8] & (1 << (index % 8))) != 0;
+}
+
+#include "lv2.h"
+
+
+typedef struct {
+
+ /** The message run function. This is called once to process a set of
+ * inputs and produce a set of outputs.
+ *
+ * Before calling the host MUST set valid_inputs such that the bit
+ * corresponding to each input port is 1 iff data is present. The plugin
+ * MUST only inspect bits corresponding to ports in the message thread.
+ *
+ * Similarly, before returning the plugin MUST set valid_outputs such that
+ * the bit corresponding to each output port of the message context is 1
+ * iff the value at that port has changed.
+ * The plugin must return 1 if outputs have been written, 0 otherwise.
+ */
+ uint32_t (*message_run)(LV2_Handle instance,
+ const void* valid_inputs,
+ void* valid_outputs);
+
+} LV2_Contexts_MessageContext;
+
+#endif /* LV2_CONTEXTS_H */
+
diff --git a/ext/contexts.lv2/contexts.ttl b/ext/contexts.lv2/contexts.ttl
new file mode 100644
index 0000000..59c4cb1
--- /dev/null
+++ b/ext/contexts.lv2/contexts.ttl
@@ -0,0 +1,202 @@
+# LV2 Contexts Extension
+#
+# Allows for an LV2 plugin to have several independent contexts, each with its
+# own run callback and associated ports.
+#
+# Copyright (C) 2007 David Robillard
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix ctx: <http://lv2plug.in/ns/ext/contexts#> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+
+<http://lv2plug.in/ns/ext/contexts>
+ a lv2:Specification ;
+ a lv2:Feature ;
+ doap:name "LV2 Contexts" ;
+ rdfs:comment """
+An extension for LV2 plugins which have several execution contexts.
+
+Any host which supports this extension must pass an LV2_Feature to
+the plugin's instantiate method with URI http://lv2plug.in/ns/ext/contexts
+and a pointer to a
+<pre>
+struct {
+ void* host_handle;
+ void (*request_run)(void* host_handle, const char* context_uri);
+}
+</pre>
+where the plugin may call request_run with the given host_handle (from any
+context) to demand immediate execution of the context specified.
+
+If the host does not support blocking contexts, request_run may be set to NULL,
+but plugins which have a :BlockingContext which is :mandatory MUST NOT be
+instantiated. If the plugin has ANY context which is :hardRTCapable,
+request_run must be realtime safe (as defined by lv2:hardRTCapable).
+
+Unless otherwise stated, each context (defined by some URI) adds a new
+threading class similar to the Audio class defined by LV2. Each context has a
+run callback and a connect_port callback both in the same class (i.e. can't be
+called concurrently), but may be called concurrently with functions for other
+contexts (excluding the Instantiation class). Context properties such as
+ctx:hardRTCapable apply to both functions.
+The host MUST only call the correct connect_port function associated with the
+context for that port, i.e. it is an error to use the main LV2 connect_port
+function on a port with a context other than the main LV2 run function.
+"""^^lv2:basicXHTML .
+
+
+##########################
+## Context Base Classes ##
+##########################
+
+ctx:Context a rdfs:Class ;
+ rdfs:label "LV2 Context" ;
+ rdfs:comment """
+A potentially concurrent context (callback) on a plugin.
+
+If a plugin supports a context (specified with the :optionalContext or
+ctx:requiredContext plugin properties) its extension_data function, called with
+the URI for that context, should return a context descriptor as defined by the
+specification of the context URI. If a plugin has any contexts, it MUST specify
+the associated context of ALL ports, with the :context port property.""" .
+
+
+ctx:RollingContext a rdfs:Class ;
+ rdfs:subClassOf ctx:Context ;
+ rdfs:comment """
+A context which is is continually executed in blocks (like the standard LV2
+run callback). Extension data is a pointer to a
+
+struct {
+ void (*run)(LV2Handle instance, uint32_t sample_count);
+ void (*connect_port)(LV2_Handle instance, uint32_t port, void* data);
+}
+
+When run is called, sample_count frames worth of input/output should be
+read from/written to all ports associated with this context.
+""" .
+
+
+ctx:BlockingContext a rdfs:Class ;
+ rdfs:subClassOf ctx:Context ;
+ rdfs:comment """
+A context which is executed only when there is work to be done
+(e.g. a message is received). Extension data is a pointer to a
+
+struct LV2BlockingContext {
+ bool (*run)(LV2Handle instance, uint8_t* valid_inputs, uint8_t* valid_outputs)
+ void (*connect_port)(LV2_Handle instance, uint32_t port, void* data);
+}
+
+When run is called, any pending input in ports associated with this context
+should be read, and true returned iff output was written (meaning plugins
+connected to ports where output has been written should be executed).
+
+Before calling run, the host MUST set the nth bit of valid_inputs to 1 if the
+input port with index n has valid input that should be processed, otherwise 0.
+Before returning from run, the plugin MUST set the nth bit of valid_outputs
+to 1 if the port with index n was written to, otherwise 0.
+The header lv2_contexts.h provides utility functions for these purposes.
+The plugin MUST NOT touch any bits corresponding to ports on another context.
+""" .
+
+
+#######################
+## Plugin Properties ##
+#######################
+
+ctx:optionalContext a rdf:Property ;
+ rdfs:domain lv2:Plugin ;
+ rdfs:range ctx:Context ;
+ rdfs:label "Has an optional context" ;
+ rdfs:comment """
+Signifies a Plugin supports a certain context, defined by a URI, which may
+be ignored by the host.""" .
+
+ctx:requiredContext a rdf:Property ;
+ rdfs:domain lv2:Plugin ;
+ rdfs:range ctx:Context ;
+ rdfs:label "Has a required context" ;
+ rdfs:comment """
+Signifies a Plugin supports a certain context, defined by a URI, which must be
+supported by the host for the plugin to function.""" .
+
+
+#####################
+## Port Properties ##
+#####################
+
+ctx:context a rdf:Property ;
+ rdfs:domain lv2:Port ;
+ rdfs:range ctx:Context ;
+ rdfs:label "Is used by context" ;
+ rdfs:comment """
+The context a particular port is associated with; the port will only be
+connected/read/written by that context.
+
+If no context is specified, the port is considered part of the default LV2
+audio context.""" .
+
+
+##################################
+## Specific context definitions ##
+##################################
+
+
+ctx:AudioContext a rdfs:Class ;
+ rdfs:subClassOf ctx:Context ;
+ rdfs:comment """
+The context of the core LV2 run method (LV2_Descriptor::run).
+""" .
+
+
+ctx:StatelessAudioContext a rdfs:Class ;
+ rdfs:subClassOf ctx:Context ;
+ rdfs:comment """
+The usual LV2 run context (ctx:AudioContext), with the additional property
+that the plugin has no internal state whatsoever (other than the sample rate
+and the locations ports are currently connected to). On a plugin with a
+ctx:StatelessAudioContext, the nframes parameter to run is meaningless and
+ignored by the plugin, and the host may assume that any call to run with
+a given set of inputs will produce the exact same set of outputs (i.e.
+the plugin's run method is purely functional). This context inherently
+conflicts with lv2:isLive, a plugin MUST NOT have both a
+ctx:StatelessAudioContext and the lv2:isLive feature.
+
+For easy compatibility with hosts that don't care whether the audio context
+is stateless or not, this context should be listed as a ctx:optionalContext
+(since the default LV2 context is implicitly present).
+""" .
+
+
+ctx:MessageContext a rdfs:Class ;
+ rdfs:subClassOf ctx:BlockingContext ;
+ rdfs:comment """
+A blocking context for on-demand message-like processing. The plugin's
+lv2:hardRTCapable property does not apply to the message context, there are
+no realtime restrictions on the plugin's message context, and no
+syncronisation guarantees between the message context and any other context.
+""" .
+
diff --git a/ext/contexts.lv2/manifest.ttl b/ext/contexts.lv2/manifest.ttl
new file mode 100644
index 0000000..373b8f6
--- /dev/null
+++ b/ext/contexts.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/contexts>
+ a lv2:Specification ;
+ rdfs:seeAlso <contexts.ttl> .
+
diff --git a/ext/contexts.lv2/test.c b/ext/contexts.lv2/test.c
new file mode 100644
index 0000000..f55cdd6
--- /dev/null
+++ b/ext/contexts.lv2/test.c
@@ -0,0 +1,65 @@
+#include <stdio.h>
+#include <limits.h>
+#include <assert.h>
+#include <unistd.h>
+#include "lv2_contexts.h"
+
+#define TEST_ASSERT(check) do {\
+ if (!(check)) {\
+ fprintf(stderr, "Failure at line %d: %s\n", __LINE__, #check);\
+ assert(false);\
+ _exit(1);\
+ }\
+} while (0)
+
+#define NUM_PORTS 64
+
+void
+print_flags(void* flags)
+{
+ for (int i = NUM_PORTS; i >= 0; --i)
+ printf((lv2_contexts_port_is_valid(flags, i)) ? "1" : "0");
+ printf("\n");
+}
+
+
+int
+main()
+{
+ uint64_t flags = 0;
+ print_flags(&flags);
+
+ lv2_contexts_set_port_valid(&flags, 16);
+ print_flags(&flags);
+ for (int i = 0; i < NUM_PORTS; ++i) {
+ if (i == 16) {
+ TEST_ASSERT(lv2_contexts_port_is_valid(&flags, i));
+ } else {
+ TEST_ASSERT(!lv2_contexts_port_is_valid(&flags, i));
+ }
+ }
+
+ lv2_contexts_set_port_valid(&flags, 46);
+ lv2_contexts_set_port_valid(&flags, 0);
+ print_flags(&flags);
+ for (int i = 0; i < NUM_PORTS; ++i) {
+ if (i == 0 || i == 16 || i == 46) {
+ TEST_ASSERT(lv2_contexts_port_is_valid(&flags, i));
+ } else {
+ TEST_ASSERT(!lv2_contexts_port_is_valid(&flags, i));
+ }
+ }
+
+ lv2_contexts_unset_port_valid(&flags, 16);
+ print_flags(&flags);
+ for (int i = 0; i < NUM_PORTS; ++i) {
+ if (i == 0 || i == 46) {
+ TEST_ASSERT(lv2_contexts_port_is_valid(&flags, i));
+ } else {
+ TEST_ASSERT(!lv2_contexts_port_is_valid(&flags, i));
+ }
+ }
+
+ return 0;
+}
+
diff --git a/ext/data-access.lv2/data-access.h b/ext/data-access.lv2/data-access.h
new file mode 100644
index 0000000..aa87723
--- /dev/null
+++ b/ext/data-access.lv2/data-access.h
@@ -0,0 +1,57 @@
+/* lv2_data_access.h - C header file for the LV2 Data Access 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
+ */
+
+/** @file
+ * C header for the LV2 Extension Data extension
+ * <http://lv2plug.in/ns/ext/data-access>.
+ *
+ * This extension defines a method for (e.g.) plugin UIs to have (possibly
+ * marshalled) access to the extension_data function on a plugin instance.
+ */
+
+#ifndef LV2_DATA_ACCESS_H
+#define LV2_DATA_ACCESS_H
+
+#define LV2_DATA_ACCESS_URI "http://lv2plug.in/ns/ext/data-access"
+
+/** The data field of the LV2_Feature for this extension.
+ *
+ * To support this feature the host must pass an LV2_Feature struct to the
+ * instantiate method with URI "http://lv2plug.in/ns/ext/data-access"
+ * and data pointed to an instance of this struct.
+ */
+typedef struct {
+
+ /** A pointer to a method the UI can call to get data (of a type specified
+ * by some other extension) from the plugin.
+ *
+ * This call never is never guaranteed to return anything, UIs should
+ * degrade gracefully if direct access to the plugin data is not possible
+ * (in which case this function will return NULL).
+ *
+ * This is for access to large data that can only possibly work if the UI
+ * and plugin are running in the same process. For all other things, use
+ * the normal LV2 UI communication system.
+ */
+ const void* (*data_access)(const char* uri);
+
+} LV2_Extension_Data_Feature;
+
+
+#endif /* LV2_DATA_ACCESS_H */
+
diff --git a/ext/data-access.lv2/data-access.ttl b/ext/data-access.lv2/data-access.ttl
new file mode 100644
index 0000000..ce5c849
--- /dev/null
+++ b/ext/data-access.lv2/data-access.ttl
@@ -0,0 +1,46 @@
+# LV2 Data Access Extension
+# Copyright (C) 2008 David Robillard <d@drobilla.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix da: <http://lv2plug.in/ns/ext/data-access#> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix lv2ev: <http://lv2plug.in/ns/ext/event#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+
+<http://lv2plug.in/ns/ext/data-access> a lv2:Specification ;
+ doap:license <http://usefulinc.com/doap/licenses/mit> ;
+ doap:name "LV2 Data Access" ;
+ doap:release [
+ doap:revision "1" ;
+ doap:created "2008-08-11" ;
+ ] ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "David Robillard" ;
+ foaf:homepage <http://drobilla.net/> ;
+ rdfs:seeAlso <http://drobilla.net/drobilla.xrdf>
+ ] ;
+ rdfs:comment """
+This extension defines a method for (e.g.) plugin UIs to have (possibly
+marshalled) access to the extension_data function on a plugin instance.
+""" .
diff --git a/ext/data-access.lv2/manifest.ttl b/ext/data-access.lv2/manifest.ttl
new file mode 100644
index 0000000..11b6e52
--- /dev/null
+++ b/ext/data-access.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/data-access>
+ a lv2:Specification ;
+ rdfs:seeAlso <data-access.ttl> .
+
diff --git a/ext/dyn-manifest.lv2/Makefile b/ext/dyn-manifest.lv2/Makefile
new file mode 100644
index 0000000..c575035
--- /dev/null
+++ b/ext/dyn-manifest.lv2/Makefile
@@ -0,0 +1,20 @@
+PREFIX = /usr/local
+LV2_DIR = $(PREFIX)/lib/lv2
+INCLUDE_DIR = $(PREFIX)/include
+
+all:
+ @echo "There's nothing to build here, just 'make install'"
+ @echo
+ @echo "The variables PREFIX, LV2_DIR, and INCLUDE_DIR are used, e.g.:"
+ @echo "make PREFIX=/usr LV2_DIR=/usr/lib/lv2 INCLUDE_DIR=/usr/include"
+ @echo
+ @echo "Defaults:"
+ @echo " PREFIX = /usr/local"
+ @echo " LV2_DIR = PREFIX/lib/lv2"
+ @echo " INCLUDE_DIR = PREFIX/include"
+
+install:
+ install -d $(LV2_DIR)/lv2_dyn_manifest.lv2
+ install -m 0644 lv2_dyn_manifest.ttl $(LV2_DIR)/lv2_dyn_manifest.lv2/
+ install -d $(INCLUDE_DIR)/
+ install -m 0644 lv2_dyn_manifest.h $(INCLUDE_DIR)/
diff --git a/ext/dyn-manifest.lv2/dyn-manifest.h b/ext/dyn-manifest.lv2/dyn-manifest.h
new file mode 100644
index 0000000..00e46fd
--- /dev/null
+++ b/ext/dyn-manifest.lv2/dyn-manifest.h
@@ -0,0 +1,245 @@
+/* Dynamic manifest specification for LV2
+ * Revision 1
+ *
+ * Copyright (C) 2008, 2009 Stefano D'Angelo <zanga.mail@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LV2_DYN_MANIFEST_H_INCLUDED
+#define LV2_DYN_MANIFEST_H_INCLUDED
+
+#include <stdio.h>
+#include "lv2.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* ************************************************************************* */
+
+
+/** @file
+ * C header for the LV2 Dynamic Manifest extension
+ * <http://lv2plug.in/ns/ext/dyn-manifest>.
+ * Revision: 1
+ *
+ * == Overview ==
+ *
+ * The LV2 API, on its own, cannot be used to write plugin libraries where
+ * data is dynamically generated at runtime (e.g. API wrappers), since LV2
+ * requires needed information to be provided in one or more static data (RDF)
+ * files. This API addresses this limitation by extending the LV2 API.
+ *
+ * A host implementing support for this API should first detect that the plugin
+ * library implements a dynamic manifest generator by examining its static
+ * manifest file, then fetch data from the shared object file by accessing it as
+ * usual (dlopen() and family) and using this API.
+ *
+ * The host is allowed to request regeneration of the dynamic manifest multiple
+ * times, and the plugin library is expected to provide updated data if/when
+ * possible. All data and references provided via this API before the last
+ * regeneration of the dynamic manifest is to be considered invalid by the
+ * host, including plugin descriptors whose URIs were discovered using this API.
+ *
+ * This API is extensible in a similar fashion as the LV2 plugin API.
+ *
+ * == Threading rules ==
+ *
+ * This specification defines threading rule classes, similarly to the LV2
+ * specification.
+ *
+ * The functions defined by this API belong to:
+ *
+ * - Dynamic manifest open class: lv2_dyn_manifest_open()
+ * - Dynamic manifest close class: lv2_dyn_manifest_close()
+ * - Dynamic manifest file class: lv2_dyn_manifest_get_subjects(),
+ * lv2_dyn_manifest_get_data()
+ *
+ * The rules that hosts must follow are these:
+ *
+ * - When a function from the Dynamic manifest open or the Dynamic manifest
+ * close class is running, no other functions in the same shared object file
+ * may run.
+ * - When a function from the Dynamic manifest file class is called, no other
+ * functions from the same class may run if they are given at least one
+ * FILE * argument with the same value.
+ * - A function from the Dynamic manifest open class may not run after a
+ * successful call to a function from the same class, in case a function from
+ * the Dynamic manifest close class was not successfully called in the
+ * meanwhile.
+ * - A function from the Dynamic manifest close class may only run after a
+ * successful call to a function from the Dynamic manifest open class.
+ * - A function from the Dynamic manifest file class may only run beetween a
+ * successful call to a function from the Dynamic manifest open class and the
+ * following successful call to a function from the Dynamic manifest close
+ * class.
+ *
+ * Extensions to this specification which add new functions MUST declare in
+ * which of these classes the functions belong, or define new classes for them;
+ * furthermore, classes defined by such extensions MUST only allow calls after
+ * a successful call to a function from the Dynamic manifest open class and
+ * before the following successful call to a function from the Dynamic manifest
+ * close class.
+ *
+ * Any simultaneous calls that are not explicitly forbidden by these rules are
+ * allowed.
+ */
+
+
+/* ************************************************************************* */
+
+
+/** Dynamic manifest generator handle.
+ *
+ * This handle indicates a particular status of a dynamic manifest generator.
+ * The host MUST NOT attempt to interpret it and, unlikely LV2_Handle, it is NOT
+ * even valid to compare this to NULL. The dynamic manifest generator may use it
+ * to reference internal data. */
+typedef void * LV2_Dyn_Manifest_Handle;
+
+
+/* ************************************************************************* */
+
+
+/** Accessing data.
+ *
+ * Whenever a host wants to access data using this API, it could:
+ *
+ * 1. Call lv2_dyn_manifest_open();
+ * 2. Create an empty resource identified by a FILE *;
+ * 3. Get a "list" of exposed subject URIs using
+ * lv2_dyn_manifest_get_subjects();
+ * 4. Call lv2_dyn_manifest_get_data() for each URI of interest, in order to
+ * get data related to that URI (either by calling the function subsequently
+ * with the same FILE * resource, or by creating more FILE * resources to
+ * perform parallel calls);
+ * 5. Call lv2_dyn_manifest_close();
+ * 6. Parse the content of the FILE * resource(s).
+ * 7. Free/delete/unlink the FILE * resource(s).
+ *
+ * The content of the FILE * resources has to be interpreted by the host as a
+ * regular file in Turtle syntax. This also means that each FILE * resource
+ * should also contain needed prefix definitions, in case any are used.
+ *
+ * Each call to lv2_dyn_manifest_open() automatically implies the (re)generation
+ * of the dynamic manifest on the library side.
+ *
+ * When such calls are made, data fetched from the involved library using this
+ * API before such call is to be considered no more valid.
+ *
+ * In case the library uses this same API to access other dynamic manifests, it
+ * MUST implement some mechanism to avoid potentially endless loops (such as A
+ * loads B, B loads A, etc.) in functions from the Dynamic manifest open class
+ * (the open-like operation MUST fail). For this purpose, use of a static
+ * boolean flag is suggested.
+ */
+
+/** Function that (re)generates the dynamic manifest.
+ *
+ * handle is a pointer to an uninitialized dynamic manifest generator handle.
+ *
+ * features is a NULL terminated array of LV2_Feature structs which
+ * represent the features the host supports. The dynamic manifest geenrator may
+ * refuse to (re)generate the dynamic manifest if required features are not
+ * found here (however hosts SHOULD NOT use this as a discovery mechanism,
+ * instead of reading the static manifest file). This array must always exist;
+ * if a host has no features, it MUST pass a single element array containing
+ * NULL.
+ *
+ * This function MUST return 0 on success, otherwise a non-zero error code, and
+ * the host SHOULD evaluate the result of the operation by examining the
+ * returned value, rather than try to interpret the value of handle.
+ */
+int lv2_dyn_manifest_open(LV2_Dyn_Manifest_Handle * handle,
+ const LV2_Feature *const * features);
+
+/** Function that fetches a "list" of subject URIs exposed by the dynamic
+ * manifest generator.
+ *
+ * handle is the dynamic manifest generator handle.
+ *
+ * fp is the FILE * identifying the resource the host has to set up for the
+ * dynamic manifest generator. The host MUST pass a writable, empty resource to
+ * this function, and the dynamic manifest generator MUST ONLY perform write
+ * operations on it at the end of the stream (e.g. use only fprintf(), fwrite()
+ * and similar).
+ *
+ * The dynamic manifest generator has to fill the resource only with the needed
+ * triples to make the host aware of the "objects" it wants to expose. For
+ * example, if the library exposes a regular LV2 plugin, it should output only a
+ * triple like the following:
+ *
+ * <http://www.example.com/plugin/uri> a lv2:Plugin;
+ *
+ * This function MUST return 0 on success, otherwise a non-zero error code.
+ */
+int lv2_dyn_manifest_get_subjects(LV2_Dyn_Manifest_Handle handle,
+ FILE * fp);
+
+/** Function that fetches data related to a specific URI.
+ *
+ * handle is the dynamic manifest generator handle.
+ *
+ * fp is the FILE * identifying the resource the host has to set up for the
+ * dynamic manifest generator. The host MUST pass a writable resource to this
+ * function, and the dynamic manifest generator MUST ONLY perform write
+ * operations on it at the current position of the stream (e.g. use only
+ * fprintf(), fwrite() and similar).
+ *
+ * uri is the URI to get data about (in the "plain" form, a.k.a. without RDF
+ * prefixes).
+ *
+ * The dynamic manifest generator has to fill the resource with data related to
+ * the URI. For example, if the library exposes a regular LV2 plugin whose URI,
+ * as retrieved by the host using lv2_dyn_manifest_get_subjects() is
+ * http://www.example.com/plugin/uri, it should output something like:
+ *
+ * <http://www.example.com/plugin/uri> a lv2:Plugin;
+ * lv2:binary <mylib.so>;
+ * doap:name "My Plugin";
+ * ... etc...
+ *
+ * This function MUST return 0 on success, otherwise a non-zero error code.
+ */
+int lv2_dyn_manifest_get_data(LV2_Dyn_Manifest_Handle handle,
+ FILE * fp,
+ const char * uri);
+
+/** Function that ends the operations on the dynamic manifest generator.
+ *
+ * handle is the dynamic manifest generator handle.
+ *
+ * This function should be used by the dynamic manifest generator to perform
+ * cleanup operations, etc.
+ */
+void lv2_dyn_manifest_close(LV2_Dyn_Manifest_Handle handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LV2_DYN_MANIFEST_H_INCLUDED */
+
diff --git a/ext/dyn-manifest.lv2/dyn-manifest.ttl b/ext/dyn-manifest.lv2/dyn-manifest.ttl
new file mode 100644
index 0000000..84e8f5a
--- /dev/null
+++ b/ext/dyn-manifest.lv2/dyn-manifest.ttl
@@ -0,0 +1,109 @@
+# Dynamic manifest specification for LV2
+# Revision 1
+#
+# Copyright (C) 2008, 2009 Stefano D'Angelo <zanga.mail@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+@prefix dman: <http://lv2plug.in/ns/ext/dyn-manifest#> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+
+<http://lv2plug.in/ns/ext/dyn-manifest>
+ a doap:Project ;
+ a lv2:Specification ;
+ doap:license <http://usefulinc.com/doap/licenses/bsd> ;
+ doap:name "LV2 Dynamic Manifest" ;
+ doap:homepage <http://naspro.atheme.org> ;
+ doap:created "2009-06-13" ;
+ doap:shortdesc "An LV2-based specification for dynamic data generation." ;
+ doap:programming-language "C" ;
+ doap:release [
+ doap:revision "1" ;
+ doap:created "2009-06-13"
+ ] ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "Stefano D'Angelo" ;
+ ] .
+
+######################################
+## Dynamic manifest generator class ##
+######################################
+
+dman:DynManifest a rdfs:Class ;
+ rdfs:label "Dynamic manifest generator" ;
+ rdfs:subClassOf [ a owl:Restriction ;
+ owl:onProperty rdf:type ;
+ owl:hasValue dman:DynManifest ;
+ rdfs:comment "A DynManifest has rdf:type dman:DynManifest."
+ ] , [ a owl:Restriction ;
+ owl:onProperty lv2:binary ;
+ owl:minCardinality 1 ;
+ rdfs:comment """A DynManifest has at least 1 lv2:binary.
+The binary must be a library with at least the functions described in
+lv2_dyn_manifest.h implemented.
+""" ] ;
+ rdfs:comment """
+The class which represents a dynamic manifest generator.
+
+There MUST NOT be any instances of :DynManifest in the generated manifest.
+
+All relative URIs in the generated data MUST be relative to the base path
+that would be used to parse a normal LV2 manifest (the bundle path).
+""" .
+
+##############
+## Features ##
+##############
+
+dman:optionalFeature a rdf:Property ;
+ rdfs:domain dman:DynManifest ;
+ rdfs:range lv2:Feature ;
+ rdfs:label "Optional feature" ;
+ rdfs:comment """
+Signifies that a dynamic manifest generator is able to make use of or provide a
+certain feature. If the host supports this feature, it MUST pass its URI and any
+additional data to the dynamic manifest generator in the lv2_dyn_manifest_open()
+function. The dynamic manifest generator MUST NOT fail because an optional
+feature is possibly not supported by the host.""" .
+
+dman:requiredFeature a rdf:Property ;
+ rdfs:domain dman:DynManifest ;
+ rdfs:range lv2:Feature ;
+ rdfs:label "Required feature" ;
+ rdfs:comment """
+Signifies that a dynamic manifest generator requires a certain feature in order
+to function. If the host supports this feature, it MUST pass its URI and any
+additional data to the dynamic manifest generator in the lv2_dyn_manifest_open()
+function. The dynamic manifest generator MUST fail if a required feature is not
+present; hosts SHOULD always check this before attempting to perform futher
+operations on the dynamic manifest generator.
+""" .
+
diff --git a/ext/dyn-manifest.lv2/manifest.ttl b/ext/dyn-manifest.lv2/manifest.ttl
new file mode 100644
index 0000000..e5d09b4
--- /dev/null
+++ b/ext/dyn-manifest.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/dyn-manifest>
+ a lv2:Specification ;
+ rdfs:seeAlso <dyn-manifest.ttl> .
+
diff --git a/ext/event.lv2/event-helpers.h b/ext/event.lv2/event-helpers.h
new file mode 100644
index 0000000..14500b8
--- /dev/null
+++ b/ext/event.lv2/event-helpers.h
@@ -0,0 +1,243 @@
+/* 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 "event.lv2/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)
+{
+ LV2_Event_Buffer* buf = (LV2_Event_Buffer*)malloc(sizeof(LV2_Event_Buffer) + capacity);
+ 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 @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 @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/ext/event.lv2/event.h b/ext/event.lv2/event.h
new file mode 100644
index 0000000..7fb189c
--- /dev/null
+++ b/ext/event.lv2/event.h
@@ -0,0 +1,259 @@
+/* lv2_event.h - C header file for the LV2 events extension.
+ *
+ * Copyright (C) 2006-2007 Lars Luthman <lars.luthman@gmail.com>
+ * 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_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
+ * C header 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 timestmaps.
+ * 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;
+
+
+/** The data field of the LV2_Feature for this extension.
+ *
+ * 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.
+ */
+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/ext/event.lv2/event.ttl b/ext/event.lv2/event.ttl
new file mode 100644
index 0000000..4f939a4
--- /dev/null
+++ b/ext/event.lv2/event.ttl
@@ -0,0 +1,192 @@
+# LV2 Events Extension
+# Copyright (C) 2008 David Robillard <d@drobilla.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix ev: <http://lv2plug.in/ns/ext/event#> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix lv2ev: <http://lv2plug.in/ns/ext/event#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+
+<http://lv2plug.in/ns/ext/event> a lv2:Specification ;
+ doap:license <http://usefulinc.com/doap/licenses/mit> ;
+ doap:name "LV2 Events" ;
+ rdfs:seeAlso "event-helpers.h" ;
+ doap:release [
+ doap:revision "1" ;
+ doap:created "2008-04-04" ;
+ ] ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "David Robillard" ;
+ foaf:homepage <http://drobilla.net/> ;
+ rdfs:seeAlso <http://drobilla.net/drobilla.xrdf>
+ ] , [
+ a foaf:Person ;
+ foaf:name "Lars Luthman" ;
+ ] ;
+ rdfs:comment """
+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:
+<pre>
+&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 lv2ev: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
+lv2ev: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/ext/event.lv2/lv2_event.pc.in b/ext/event.lv2/lv2_event.pc.in
new file mode 100644
index 0000000..6d556ef
--- /dev/null
+++ b/ext/event.lv2/lv2_event.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: lv2_event
+Version: @LV2_EVENT_VERSION@
+Description: LV2 events extension
+Libs:
+Cflags: -I${includedir}
diff --git a/ext/event.lv2/manifest.ttl b/ext/event.lv2/manifest.ttl
new file mode 100644
index 0000000..8f17311
--- /dev/null
+++ b/ext/event.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@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 ;
+ rdfs:seeAlso <event.ttl> .
+
diff --git a/ext/files.lv2/files.h b/ext/files.lv2/files.h
new file mode 100644
index 0000000..4f0564f
--- /dev/null
+++ b/ext/files.lv2/files.h
@@ -0,0 +1,61 @@
+/* lv2_files.h - C header file for the LV2 Files extension.
+ * Copyright (C) 2010 Leonard Ritter <paniq@paniq.org>
+ *
+ * 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
+ */
+
+/** @file
+ * C header for the LV2 Files extension <http://lv2plug.in/ns/ext/files>.
+ */
+
+#ifndef LV2_FILES_H
+#define LV2_FILES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LV2_FILES_URI "http://lv2plug.in/ns/ext/files"
+
+typedef void* LV2_Files_FileSupport_Data;
+
+/** Feature structure passed by host to instantiate with feature URI
+ * <http://lv2plug.in/ns/ext/files#fileSupport>.
+ */
+typedef struct {
+
+ LV2_Files_FileSupport_Data data;
+
+ /** Return the full path that should be used for a file owned by this
+ * plugin called @a name. The plugin can assume @a name belongs to a
+ * namespace dedicated to that plugin instance (i.e. hosts MUST ensure
+ * this, e.g. by giving each plugin its own directory for files, or
+ * mangling filenames somehow).
+ *
+ * @param data MUST be the @a data member of this struct.
+ * @param name The name of the file.
+ * @return A newly allocated path which the plugin may use to create a new
+ * file. The plugin is responsible for freeing the returned string.
+ */
+ char* new_file_path(LV2_Files_FileSupport_Data data,
+ const char* name);
+
+} LV2_Files_FileSupport;
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* LV2_FILES_H */
diff --git a/ext/files.lv2/files.ttl b/ext/files.lv2/files.ttl
new file mode 100644
index 0000000..a83889d
--- /dev/null
+++ b/ext/files.lv2/files.ttl
@@ -0,0 +1,94 @@
+# LV2 Files Extension
+# Copyright (C) 2010 Leonard Ritter <paniq@paniq.org>
+# Copyright (C) 2010 David Robillard <d@drobilla.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix files: <http://lv2plug.in/ns/ext/files#> .
+@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema> .
+
+<http://lv2plug.in/ns/ext/files>
+ a lv2:Specification ;
+ doap:name "LV2 Files" ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "David Robillard" ;
+ foaf:homepage <http://drobilla.net/> ;
+ rdfs:seeAlso <http://drobilla.net/drobilla.rdf>
+ ] ;
+ rdfs:comment """
+This extension provides a mechanism for plugins to create new files for
+storing arbitrary data (e.g. waveforms), which can be persisted using
+the <a href="http://lv2plug.in/ns/ext/persist">LV2 Persist</a> extension.
+This allows plugins to work with potentially very large data via files,
+and save/restore these files.
+
+The motivating idea behind this extension is that all details of file
+management must be handled by the host in whatever way is most appropriate for
+that host. Plugins MUST NOT make any assumption about filesystem locations
+beyond what is explicitly guaranteed by this extension.
+
+To create a new file, plugins request a filename from the host. This way,
+the host is aware of files used by the plugin and can use an appropriate
+location for them that the plugin alone could not know (e.g. using an
+appropriate disk volume for recording).
+
+Plugins may also use pre-existing files from elsewhere on the filesystem.
+Using the LV2 Persist extension, the host can save both these types of files
+in an appropriate way (by e.g. storing a link, or copying the file to export
+or archive a project).
+
+""" .
+
+files:fileSupport a lv2:Feature ;
+ rdfs:label "Support for plugin-created files" ;
+ rdfs:comment """
+This feature allows plugins to use pre-existing or newly created files,
+and files them (e.g. across project saves and restores). If a host supports
+this feature it passes a LV2_Files_FileSupport structure to the plugins
+instantiate method as a feature (with URI
+http://lv2plug.in/ns/ext/files#FileSupport). This structure provides
+a function the plugin can use to create new file names. If and only if the
+host supports this feature, the plugin MAY files and restore values of
+type LV2_FILES_FILENAME.
+
+A plugin SHOULD use this facility to create any new files it may need
+(e.g. samples, waveforms for recording). Plugins MUST NOT expect their
+state to be correctly restored if they do not use this mechanism to
+create new files.
+""" .
+
+files:FilePath a atom:AtomType ;
+ rdfs:label "File Path" ;
+ rdfs:comment """
+The full path to a file on the local filesystem. The format of a
+files:filePath is a C string (escaped or otherwise restricted in whatever way
+necessary for the system). This URI (http://lv2plug.in/ns/ext/files#FilePath),
+mapped to an integer, should be used as the <code>type</code> parameter with
+the LV2 Persist extension to persist a file. When persisting a files:FilePath,
+the plugin MUST NOT assume that the same path will be restored (i.e. the
+host MAY choose to store the file elsewhere). The plugin may, of course,
+assume that the actual contents of the file are equivalent when restored.
+""" .
diff --git a/ext/files.lv2/manifest.ttl b/ext/files.lv2/manifest.ttl
new file mode 100644
index 0000000..7f572d9
--- /dev/null
+++ b/ext/files.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/files>
+ a lv2:Specification ;
+ rdfs:seeAlso <files.ttl> .
+
diff --git a/ext/host-info.lv2/host-info.ttl b/ext/host-info.lv2/host-info.ttl
new file mode 100644
index 0000000..2aac2fc
--- /dev/null
+++ b/ext/host-info.lv2/host-info.ttl
@@ -0,0 +1,116 @@
+# LV2 Host Info Extension
+# PROVISIONAL
+# Copyright (C) 2009 David Robillard <d@drobilla.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix hi: <http://lv2plug.in/ns/ext/host-info#> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix amb: <http://ambisonics.ch/standards/channels/> .
+
+<http://lv2plug.in/ns/ext/host-info> a lv2:Specification ;
+ doap:license <http://usefulinc.com/doap/licenses/mit> ;
+ doap:name "LV2 Host Info" ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "David Robillard" ;
+ foaf:homepage <http://drobilla.net/> ;
+ rdfs:seeAlso <http://drobilla.net/drobilla.rdf>
+ ] ;
+ rdfs:comment """
+This specification defines various properties to represent useful information
+about LV2 hosts. Currently, the primary use of this specification is to describe which
+extensions are supported by a given host.
+
+The extensions supported by a host can be described like this:
+<pre>
+@prefix hi: &lt;http://lv2plug.in/ns/ext/host-info#&gt; .
+
+&lt;http://example.org/some-host&gt; a hi:Host ;
+ doap:name "Foo Rack" ;
+ hi:supportsExtension [
+ hi:extension &lt;http://example.org/some-extension&gt; ;
+ hi:sinceVersion "1.2.0"
+ ] .
+</pre>
+"""^^lv2:basicXHTML .
+
+
+## Core Classes / Properties
+
+hi:Host a rdfs:Class ;
+ rdfs:label "LV2 Host" ;
+ rdfs:subClassOf [ a owl:Restriction ;
+ owl:onProperty doap:name ;
+ owl:someValuesFrom xsd:string ;
+ owl:minCardinality 1 ;
+ rdfs:comment "A hi:Host MUST have at least one string doap:name"
+ ] ;
+ rdfs:comment """
+An application that supports loading LV2 plugins, or performs other
+LV2 related functionality.
+""" .
+
+hi:supportsExtension a rdf:Property ;
+ rdfs:domain hi:Host ;
+ rdfs:range hi:ExtensionSupport ;
+ rdfs:label "supports extension" ;
+ rdfs:comment "Relates a Host to its ExtensionSupport" .
+
+hi:ExtensionSupport a rdfs:Class ;
+ rdfs:label "Extension Support" ;
+ rdfs:subClassOf [ a owl:Restriction ;
+ owl:onProperty hi:sinceVersion ;
+ owl:someValuesFrom xsd:string ;
+ owl:minCardinality 1 ;
+ rdfs:comment """
+A hi:ExtensionSupport MUST have at least one string hi:sinceVersion
+""" ] ;
+ rdfs:comment "A description of the support for an extension by a Host" .
+
+hi:extension a rdf:Property ;
+ rdfs:domain hi:ExtensionSupport ;
+ rdfs:range lv2:Specification ;
+ rdfs:label "extension" ;
+ rdfs:comment "Indicates the extension supported by a host." .
+
+hi:sinceVersion a rdf:Property ;
+ rdfs:domain hi:ExtensionSupport ;
+ rdfs:range xsd:string ;
+ rdfs:label "since version" ;
+ rdfs:comment """
+The initial version of a host which supported an extension.
+This property MUST always be given
+""" .
+
+hi:untilVersion a rdf:Property ;
+ rdfs:domain hi:ExtensionSupport ;
+ rdfs:range xsd:string ;
+ rdfs:label "until version" ;
+ rdfs:comment """
+The final version of a host which supported an extension. This property can
+be used if support for an extension was discontinued in a host for some reason.
+""" .
+
diff --git a/ext/host-info.lv2/manifest.ttl b/ext/host-info.lv2/manifest.ttl
new file mode 100644
index 0000000..a431711
--- /dev/null
+++ b/ext/host-info.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/host-info>
+ a lv2:Specification ;
+ rdfs:seeAlso <host-info.ttl> .
+
diff --git a/ext/instance-access.lv2/instance-access.h b/ext/instance-access.lv2/instance-access.h
new file mode 100644
index 0000000..e8b833f
--- /dev/null
+++ b/ext/instance-access.lv2/instance-access.h
@@ -0,0 +1,39 @@
+/* lv2_extension_data.h - C header file for the LV2 Instance Access 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_INSTANCE_ACCESS_H
+#define LV2_INSTANCE_ACCESS_H
+
+#define LV2_INSTANCE_ACCESS_URI "http://lv2plug.in/ns/ext/instance-access"
+
+
+/** @file
+ * C header for the LV2 Instance Access extension
+ * <http://lv2plug.in/ns/ext/instance-access>.
+ *
+ * This extension defines a method for (e.g.) plugin UIs to get a direct
+ * handle to an LV2 plugin instance (LV2_Handle), if possible.
+ *
+ * To support this feature the host must pass an LV2_Feature struct to the
+ * UI instantiate method with URI "http://lv2plug.in/ns/ext/instance-access"
+ * and data pointed directly to the LV2_Handle of the plugin instance.
+ */
+
+
+#endif /* LV2_INSTANCE_ACCESS_H */
+
diff --git a/ext/instance-access.lv2/instance-access.ttl b/ext/instance-access.lv2/instance-access.ttl
new file mode 100644
index 0000000..0646478
--- /dev/null
+++ b/ext/instance-access.lv2/instance-access.ttl
@@ -0,0 +1,46 @@
+# LV2 Data Access Extension
+# Copyright (C) 2008 David Robillard <d@drobilla.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix ia: <http://lv2plug.in/ns/ext/instance-access#> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix lv2ev: <http://lv2plug.in/ns/ext/event#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+
+<http://lv2plug.in/ns/ext/instance-access> a lv2:Specification ;
+ doap:license <http://usefulinc.com/doap/licenses/mit> ;
+ doap:name "LV2 Instance Access" ;
+ doap:release [
+ doap:revision "1" ;
+ doap:created "2008-08-11" ;
+ ] ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "David Robillard" ;
+ foaf:homepage <http://drobilla.net/> ;
+ rdfs:seeAlso <http://drobilla.net/drobilla.xrdf>
+ ] ;
+ rdfs:comment """
+This extension defines a method for (e.g.) plugin UIs to get a direct
+handle to an LV2 plugin instance (LV2_Handle), if possible.
+""" .
diff --git a/ext/instance-access.lv2/manifest.ttl b/ext/instance-access.lv2/manifest.ttl
new file mode 100644
index 0000000..e1f154b
--- /dev/null
+++ b/ext/instance-access.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/instance-access>
+ a lv2:Specification ;
+ rdfs:seeAlso <instance-access.ttl> .
+
diff --git a/ext/midi.lv2/manifest.ttl b/ext/midi.lv2/manifest.ttl
new file mode 100644
index 0000000..f243e8a
--- /dev/null
+++ b/ext/midi.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/midi>
+ a lv2:Specification ;
+ rdfs:seeAlso <midi.ttl> .
+
diff --git a/ext/midi.lv2/midi.ttl b/ext/midi.lv2/midi.ttl
new file mode 100644
index 0000000..12725ad
--- /dev/null
+++ b/ext/midi.lv2/midi.ttl
@@ -0,0 +1,87 @@
+# LV2 MIDI Extension
+# Copyright (C) 2008 David Robillard <d@drobilla.net>
+#
+# Based on lv2-midiport.h:
+# Copyright (C) 2006 Lars Luthman <lars.luthman@gmail.com>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix midi: <http://lv2plug.in/ns/ext/midi#> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix lv2ev: <http://lv2plug.in/ns/ext/events#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+
+<http://lv2plug.in/ns/ext/midi> a lv2:Specification ;
+ doap:license <http://usefulinc.com/doap/licenses/mit> ;
+ doap:name "LV2 MIDI Events" ;
+ rdfs:comment "Defines an LV2 event type for standard raw MIDI" ;
+ doap:release [
+ doap:revision "1" ;
+ doap:created "2008-08-11" ;
+ ] ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "David Robillard" ;
+ foaf:homepage <http://drobilla.net/> ;
+ rdfs:seeAlso <http://drobilla.net/drobilla.xrdf>
+ ] , [
+ a foaf:Person ;
+ foaf:name "Lars Luthman" ;
+ ] .
+
+
+midi:MidiEvent a rdfs:Class ;
+ rdfs:label "LV2 MIDI event" ;
+ rdfs:subClassOf lv2ev:Event ;
+ rdfs:comment """
+A single raw (sequence of bytes) MIDI event.
+
+These events are equivalent to standard MIDI events, with the following
+restrictions to ease the burden on plugin authors:
+<ul>
+ <li>Running status is not allowed. Every event must have its own status
+ byte.</li>
+
+ <li>Note On events with velocity 0 are not allowed. These events are
+ equivalent to Note Off in standard MIDI streams, but in order to make
+ plugins and hosts easier to write, as well as more efficient, only proper
+ Note Off events are allowed as Note Off.</li>
+
+ <li>"Realtime events" (status bytes 0xF8 to 0xFF) are allowed, but may
+ not occur inside other events like they are allowed to in hardware MIDI
+ streams.</li>
+
+ <li>All events must be fully contained in a single data buffer, i.e. events
+ may not "wrap around" by storing the first few bytes in one buffer and
+ then wait for the next run() call to store the rest of the event. If
+ there isn't enough space in the current data buffer to store an event,
+ the event will either have to wait until next run() call, be ignored,
+ or compensated for in some more clever way.</li>
+
+ <li>All events must be valid MIDI events. This means for example that
+ only the first byte in each event (the status byte) may have the eighth
+ bit set, that Note On and Note Off events are always 3 bytes long etc.
+ The MIDI writer (host or plugin) is responsible for writing valid MIDI
+ events to the buffer, and the MIDI reader (plugin or host) can assume that
+ all events are valid.</li>
+</ul>
+"""^^lv2:basicXHTML .
+
diff --git a/ext/osc.lv2/lv2_osc.c b/ext/osc.lv2/lv2_osc.c
new file mode 100644
index 0000000..0c1d1e0
--- /dev/null
+++ b/ext/osc.lv2/lv2_osc.c
@@ -0,0 +1,314 @@
+/* LV2 OSC Messages Extension
+ * Copyright (C) 2007-2009 David Robillard
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "lv2_osc.h"
+#include "lv2_osc_print.h"
+
+/*#ifndef BIG_ENDIAN
+ #ifndef LITTLE_ENDIAN
+ #warning This code requires BIG_ENDIAN or LITTLE_ENDIAN to be defined
+ #warning Assuming little endian. THIS MAY BREAK HORRIBLY!
+ #endif
+#endif*/
+
+#define lv2_osc_swap32(x) \
+({ \
+ uint32_t __x = (x); \
+ ((uint32_t)( \
+ (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
+ (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
+ (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
+ (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
+})
+
+#define lv2_osc_swap64(x) \
+({ \
+ uint64_t __x = (x); \
+ ((uint64_t)( \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \
+})
+
+
+/** Pad a size to a multiple of 32 bits */
+inline static uint32_t
+lv2_osc_pad_size(uint32_t size)
+{
+ return size + 3 - ((size-1) % 4);
+}
+
+
+inline static uint32_t
+lv2_osc_string_size(const char *s)
+{
+ return lv2_osc_pad_size((uint32_t)strlen(s) + 1);
+}
+
+
+static inline uint32_t
+lv2_osc_blob_size(const void* blob)
+{
+ return sizeof(uint32_t) + lv2_osc_pad_size(*((uint32_t*)blob));
+}
+
+
+uint32_t
+lv2_osc_arg_size(char type, const LV2_OSC_Argument* arg)
+{
+ switch (type) {
+ case 'c':
+ case 'i':
+ case 'f':
+ return 4;
+
+ case 'h':
+ case 'd':
+ return 8;
+
+ case 's':
+ return lv2_osc_string_size(&arg->s);
+
+ /*case 'S':
+ return lv2_osc_string_size(&arg->S);*/
+
+ case 'b':
+ return lv2_osc_blob_size(&arg->b);
+
+ default:
+ fprintf(stderr, "Warning: unknown OSC type '%c'.", type);
+ return 0;
+ }
+}
+
+
+void
+lv2_osc_argument_swap_byte_order(char type, LV2_OSC_Argument* arg)
+{
+ switch (type) {
+ case 'i':
+ case 'f':
+ case 'b':
+ case 'c':
+ *(int32_t*)arg = lv2_osc_swap32(*(int32_t*)arg);
+ break;
+
+ case 'h':
+ case 'd':
+ *(int64_t*)arg = lv2_osc_swap64(*(int64_t*)arg);
+ break;
+ }
+}
+
+
+/** Convert a message from network byte order to host byte order. */
+void
+lv2_osc_message_swap_byte_order(LV2_OSC_Event* msg)
+{
+ const char* const types = lv2_osc_get_types(msg);
+
+ for (uint32_t i=0; i < msg->argument_count; ++i)
+ lv2_osc_argument_swap_byte_order(types[i], lv2_osc_get_argument(msg, i));
+}
+
+
+/** Not realtime safe, returned value must be free()'d by caller. */
+LV2_OSC_Event*
+lv2_osc_message_new(const char* path, const char* types, ...)
+{
+ /* FIXME: path only */
+
+ LV2_OSC_Event* result = malloc(sizeof(LV2_OSC_Event)
+ + 4 + lv2_osc_string_size(path));
+
+ const uint32_t path_size = lv2_osc_string_size(path);
+ result->data_size = path_size + 4; // 4 for types
+ result->argument_count = 0;
+ result->types_offset = lv2_osc_string_size(path) + 1;
+ (&result->data)[result->types_offset - 1] = ',';
+ (&result->data)[result->types_offset] = '\0';
+
+ memcpy(&result->data, path, strlen(path) + 1);
+
+ return result;
+}
+
+
+/** Create a new LV2_OSC_Event from a raw OSC message.
+ *
+ * If \a out_buf is NULL, new memory will be allocated. Otherwise the returned
+ * value will be equal to buf, unless there is insufficient space in which
+ * case NULL is returned.
+ */
+LV2_OSC_Event*
+lv2_osc_message_from_raw(uint32_t out_buf_size,
+ void* out_buf,
+ uint32_t raw_msg_size,
+ void* raw_msg)
+{
+ const uint32_t message_header_size = (sizeof(uint32_t) * 4);
+
+ const uint32_t path_size = lv2_osc_string_size((char*)raw_msg);
+ const uint32_t types_len = strlen((char*)(raw_msg + path_size + 1));
+ uint32_t index_size = types_len * sizeof(uint32_t);
+
+ if (out_buf == NULL) {
+ out_buf_size = message_header_size + index_size + raw_msg_size;
+ out_buf = malloc((size_t)out_buf_size);
+ } else if (out_buf && out_buf_size < message_header_size + raw_msg_size) {
+ return NULL;
+ }
+
+ LV2_OSC_Event* write_loc = (LV2_OSC_Event*)(out_buf);
+ write_loc->argument_count = types_len;
+ write_loc->data_size = index_size + raw_msg_size;
+
+ // Copy raw message
+ memcpy(&write_loc->data + index_size, raw_msg, raw_msg_size);
+
+ write_loc->types_offset = index_size + path_size + 1;
+ const char* const types = lv2_osc_get_types(write_loc);
+
+ // Calculate/Write index
+ uint32_t args_base_offset = write_loc->types_offset + lv2_osc_string_size(types) - 1;
+ uint32_t arg_offset = 0;
+
+ for (uint32_t i=0; i < write_loc->argument_count; ++i) {
+ ((uint32_t*)&write_loc->data)[i] = args_base_offset + arg_offset;
+ const LV2_OSC_Argument* const arg = (LV2_OSC_Argument*)(&write_loc->data + args_base_offset + arg_offset);
+ // Special case because size is still big-endian
+#ifndef BIG_ENDIAN
+ if (types[i] == 'b') // special case because size is still big-endian
+ arg_offset += lv2_osc_swap32(*((int32_t*)arg));
+ else
+#endif
+ arg_offset += lv2_osc_arg_size(types[i], arg);
+ }
+
+ /*printf("Index:\n");
+ for (uint32_t i=0; i < write_loc->argument_count; ++i) {
+ printf("%u ", ((uint32_t*)&write_loc->data)[i]);
+ }
+ printf("\n");
+
+ printf("Data:\n");
+ for (uint32_t i=0; i < (write_loc->argument_count * 4) + size; ++i) {
+ printf("%3u", i % 10);
+ }
+ printf("\n");
+ for (uint32_t i=0; i < (write_loc->argument_count * 4) + size; ++i) {
+ char c = *(((char*)&write_loc->data) + i);
+ if (c >= 32 && c <= 126)
+ printf("%3c", c);
+ else
+ printf("%3d", (int)c);
+ }
+ printf("\n");*/
+
+ // Swap to host byte order if necessary
+#ifndef BIG_ENDIAN
+ lv2_osc_message_swap_byte_order(write_loc);
+#endif
+
+ printf("Created message:\n");
+ lv2_osc_message_print(write_loc);
+
+ return write_loc;
+}
+
+
+#if 0
+/** Allocate a new LV2OSCBuffer.
+ *
+ * This function is NOT realtime safe.
+ */
+LV2_OSCBuffer*
+lv2_osc_buffer_new(uint32_t capacity)
+{
+ LV2OSCBuffer* buf = (LV2OSCBuffer*)malloc((sizeof(uint32_t) * 3) + capacity);
+ buf->capacity = capacity;
+ buf->size = 0;
+ buf->message_count = 0;
+ memset(&buf->data, 0, capacity);
+ return buf;
+}
+
+
+void
+lv2_osc_buffer_clear(LV2OSCBuffer* buf)
+{
+ buf->size = 0;
+ buf->message_count = 0;
+}
+
+int
+lv2_osc_buffer_append_message(LV2OSCBuffer* buf, LV2_OSC_Event* msg)
+{
+ const uint32_t msg_size = lv2_message_get_size(msg);
+
+ if (buf->capacity - buf->size - ((buf->message_count + 1) * sizeof(uint32_t)) < msg_size)
+ return ENOBUFS;
+
+ char* write_loc = &buf->data + buf->size;
+
+ memcpy(write_loc, msg, msg_size);
+
+ // Index is written backwards, starting at end of data
+ uint32_t* index_end = (uint32_t*)(&buf->data + buf->capacity - sizeof(uint32_t));
+ *(index_end - buf->message_count) = buf->size;
+
+ ++buf->message_count;
+
+ buf->size += msg_size;
+
+ return 0;
+}
+
+int
+lv2_osc_buffer_append(LV2OSCBuffer* buf, double time, const char* path, const char* types, ...)
+{
+ // FIXME: crazy unsafe
+ LV2_OSC_Event* write_msg = (LV2_OSC_Event*)(&buf->data + buf->size);
+
+ write_msg->time = time;
+ write_msg->data_size = 0;
+ write_msg->argument_count = 0;
+ write_msg->types_offset = strlen(path) + 1;
+
+ memcpy(&write_msg->data, path, write_msg->types_offset);
+
+ /*fprintf(stderr, "Append message:\n");
+ lv2_osc_message_print(write_msg);
+ fprintf(stderr, "\n");*/
+
+ uint32_t msg_size = lv2_message_get_size(write_msg);
+ buf->size += msg_size;
+ buf->message_count++;
+
+ return 0;
+}
+#endif
+
diff --git a/ext/osc.lv2/lv2_osc.pc.in b/ext/osc.lv2/lv2_osc.pc.in
new file mode 100644
index 0000000..0424836
--- /dev/null
+++ b/ext/osc.lv2/lv2_osc.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: lv2_osc
+Version: @LV2_OSC_VERSION@
+Description: LV2 OSC message events extension
+Libs:
+Cflags: -I${includedir}
diff --git a/ext/osc.lv2/lv2_osc_print.c b/ext/osc.lv2/lv2_osc_print.c
new file mode 100644
index 0000000..5282d46
--- /dev/null
+++ b/ext/osc.lv2/lv2_osc_print.c
@@ -0,0 +1,66 @@
+/* LV2 OSC Messages Extension - Pretty printing methods
+ * Copyright (C) 2007-2009 David Robillard
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include "lv2_osc_print.h"
+
+void
+lv2_osc_argument_print(char type, const LV2_OSC_Argument* arg)
+{
+ int32_t blob_size;
+
+ switch (type) {
+ case 'c':
+ printf("%c", arg->c); break;
+ case 'i':
+ printf("%d", arg->i); break;
+ case 'f':
+ printf("%f", arg->f); break;
+ case 'h':
+ printf("%ld", arg->h); break;
+ case 'd':
+ printf("%f", arg->d); break;
+ case 's':
+ printf("\"%s\"", &arg->s); break;
+ /*case 'S':
+ printf("\"%s\"", &arg->S); break;*/
+ case 'b':
+ blob_size = *((int32_t*)arg);
+ printf("{ ");
+ for (int32_t i=0; i < blob_size; ++i)
+ printf("%X, ", (&arg->b)[i+4]);
+ printf(" }");
+ break;
+ default:
+ printf("?");
+ }
+}
+
+
+void
+lv2_osc_print(const LV2_OSC_Event* msg)
+{
+ const char* const types = lv2_osc_get_types(msg);
+
+ printf("%s (%s) ", lv2_osc_get_path(msg), types);
+ for (uint32_t i=0; i < msg->argument_count; ++i) {
+ lv2_osc_argument_print(types[i], lv2_osc_get_argument(msg, i));
+ printf(" ");
+ }
+ printf("\n");
+}
+
diff --git a/ext/osc.lv2/lv2_osc_test.c b/ext/osc.lv2/lv2_osc_test.c
new file mode 100644
index 0000000..3f76d41
--- /dev/null
+++ b/ext/osc.lv2/lv2_osc_test.c
@@ -0,0 +1,55 @@
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <lo/lo.h>
+#include "lv2_osc.h"
+#include "lv2_osc_print.h"
+
+int
+main()
+{
+ lo_message lo_msg = lo_message_new();
+ //lo_message_add_symbol(lo_msg, "a_sym");
+ lo_message_add_string(lo_msg, "Hello World");
+ lo_message_add_char(lo_msg, 'a');
+ lo_message_add_int32(lo_msg, 1234);
+ lo_message_add_float(lo_msg, 0.1234);
+ lo_message_add_int64(lo_msg, 5678);
+ lo_message_add_double(lo_msg, 0.5678);
+
+
+ /*unsigned char blob_data[] = { 0,1,2,3,4,5,6,7,8,9 };
+ lo_blob blob = lo_blob_new(10, blob_data);
+ lo_message_add_blob(lo_msg, blob);*/
+
+ /* Leaks like a sieve */
+
+ size_t raw_msg_size = 0;
+ void* raw_msg = lo_message_serialise(lo_msg, "/foo/bar", NULL, &raw_msg_size);
+
+ LV2Message* msg = lv2_osc_message_from_raw(0.0, 0, NULL, raw_msg_size, raw_msg);
+ assert(msg);
+
+ LV2OSCBuffer* buf = lv2_osc_buffer_new(1024);
+
+ int ret = lv2_osc_buffer_append_message(buf, msg);
+ if (ret)
+ fprintf(stderr, "Message append failed: %s", strerror(ret));
+
+ lo_message lo_msg_2 = lo_message_new();
+ lo_message_add_string(lo_msg_2, "Another message");
+
+ raw_msg = lo_message_serialise(lo_msg_2, "/baz", NULL, &raw_msg_size);
+
+ msg = lv2_osc_message_from_raw(0.0, 0, NULL, raw_msg_size, raw_msg);
+ assert(msg);
+
+ ret = lv2_osc_buffer_append_message(buf, msg);
+ if (ret)
+ fprintf(stderr, "Message append failed: %s", strerror(ret));
+
+ printf("\nBuffer contents:\n\n");
+ lv2_osc_buffer_print(buf);
+
+ return 0;
+}
diff --git a/ext/osc.lv2/manifest.ttl b/ext/osc.lv2/manifest.ttl
new file mode 100644
index 0000000..dc7c310
--- /dev/null
+++ b/ext/osc.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/osc>
+ a lv2:Specification ;
+ rdfs:seeAlso <osc.ttl> .
+
diff --git a/ext/osc.lv2/osc-print.h b/ext/osc.lv2/osc-print.h
new file mode 100644
index 0000000..7d590f3
--- /dev/null
+++ b/ext/osc.lv2/osc-print.h
@@ -0,0 +1,42 @@
+/* LV2 OSC Messages Extension - Pretty printing methods
+ * Copyright (C) 2007-2009 David Robillard
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ * Helper functions for printing LV2 OSC messages as defined by the
+ * LV2 OSC extension <http://lv2plug.in/ns/ext/osc>.
+ */
+
+#ifndef LV2_OSC_PRINT_H
+#define LV2_OSC_PRINT_H
+
+#include "ext/osc.lv2/osc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+lv2_osc_argument_print(char type, const LV2_OSC_Argument* arg);
+
+void
+lv2_osc_message_print(const LV2_OSC_Event* msg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LV2_OSC_PRINT_H */
diff --git a/ext/osc.lv2/osc.h b/ext/osc.lv2/osc.h
new file mode 100644
index 0000000..23e49a9
--- /dev/null
+++ b/ext/osc.lv2/osc.h
@@ -0,0 +1,123 @@
+/* LV2 OSC Messages Extension
+ * Copyright (C) 2007-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 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 General Public License
+ * for more 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 LV2_OSC_H
+#define LV2_OSC_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @file
+ * C header for the LV2 OSC extension <http://lv2plug.in/ns/ext/osc>.
+ * This extension uses (raw) OSC messages
+ * and a buffer format which contains a sequence of timestamped messages.
+ * Additional (ie beyond raw OSC) indexing information is stored in the buffer
+ * for performance, so that accessors for messages and arguments are very fast:
+ * O(1) and realtime safe, unless otherwise noted.
+ */
+
+
+/** Argument (in a message).
+ *
+ * The name of the element in this union directly corresponds to the OSC
+ * type tag character in LV2_Event::types.
+ */
+typedef union {
+ /* Standard OSC types */
+ int32_t i; /**< 32 bit signed integer */
+ float f; /**< 32 bit IEEE-754 floating point number ("float") */
+ char s; /**< Standard C, NULL terminated string */
+ uint8_t b; /**< Blob (int32 size then size bytes padded to 32 bits) */
+
+ /* "Nonstandard" OSC types (defined in the OSC standard) */
+ int64_t h; /* 64 bit signed integer */
+ // t /* OSC-timetag */
+ double d; /* 64 bit IEEE 754 floating point number ("double") */
+ // S /* Symbol, represented as an OSC-string */
+ int32_t c; /* Character, represented as a 32-bit integer */
+ // r /* 32 bit RGBA color */
+ // m /* 4 byte MIDI message. Bytes from MSB to LSB are: port id, status byte, data1, data2 */
+ // T /* True. No bytes are allocated in the argument data. */
+ // F /* False. No bytes are allocated in the argument data. */
+ // N /* Nil. No bytes are allocated in the argument data. */
+ // I /* Infinitum. No bytes are allocated in the argument data. */
+ // [ /* The beginning of an array. */
+ // ] /* The end of an array. */
+} LV2_OSC_Argument;
+
+
+
+/** Message.
+ *
+ * This is an OSC message at heart, but with some additional cache information
+ * to allow fast access to parameters. This is the payload of an LV2_Event,
+ * time stamp and size (being generic) are in the containing header.
+ */
+typedef struct {
+ uint32_t data_size; /**< Total size of data, in bytes */
+ uint32_t argument_count; /**< Number of arguments in data */
+ uint32_t types_offset; /**< Offset of types string in data */
+
+ /** Take the address of this member to get a pointer to the remaining data.
+ *
+ * Contents are an argument index:
+ * uint32_t argument_index[argument_count]
+ *
+ * followed by a standard OSC message:
+ * char path[path_length] (padded OSC string)
+ * char types[argument_count] (padded OSC string)
+ * void data[data_size]
+ */
+ char data;
+
+} LV2_OSC_Event;
+
+LV2_OSC_Event* lv2_osc_event_new(const char* path, const char* types, ...);
+
+LV2_OSC_Event* lv2_osc_event_from_raw(uint32_t out_buf_size, void* out_buf,
+ uint32_t raw_msg_size, void* raw_msg);
+
+static inline uint32_t lv2_osc_get_osc_message_size(const LV2_OSC_Event* msg)
+ { return (msg->argument_count * sizeof(char) + 1) + msg->data_size; }
+
+static inline const void* lv2_osc_get_osc_message(const LV2_OSC_Event* msg)
+ { return (const void*)(&msg->data + (sizeof(uint32_t) * msg->argument_count)); }
+
+static inline const char* lv2_osc_get_path(const LV2_OSC_Event* msg)
+ { return (const char*)(&msg->data + (sizeof(uint32_t) * msg->argument_count)); }
+
+static inline const char* lv2_osc_get_types(const LV2_OSC_Event* msg)
+ { return (const char*)(&msg->data + msg->types_offset); }
+
+static inline LV2_OSC_Argument* lv2_osc_get_argument(const LV2_OSC_Event* msg, uint32_t i)
+ { return (LV2_OSC_Argument*)(&msg->data + ((uint32_t*)&msg->data)[i]); }
+
+/*
+int lv2_osc_buffer_append_message(LV2_Event_Buffer* buf, LV2_Event* msg);
+int lv2_osc_buffer_append(LV2_Event_Buffer* buf, double time, const char* path, const char* types, ...);
+void lv2_osc_buffer_compact(LV2_Event_Buffer* buf);
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LV2_OSC_H */
diff --git a/ext/osc.lv2/osc.ttl b/ext/osc.lv2/osc.ttl
new file mode 100644
index 0000000..1cacdab
--- /dev/null
+++ b/ext/osc.lv2/osc.ttl
@@ -0,0 +1,56 @@
+# LV2 OSC Messages Extension
+# Copyright (C) 2007 David Robillard <d@drobilla.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix osc: <http://lv2plug.in/ns/ext/osc#> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+
+<http://lv2plug.in/ns/ext/osc> a lv2:Specification ;
+ doap:license <http://usefulinc.com/doap/licenses/mit> ;
+ doap:name "LV2 OSC Events" ;
+ rdfs:comment "Defines an LV2 event type for standard raw OSC" ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "David Robillard" ;
+ foaf:homepage <http://drobilla.net/> ;
+ rdfs:seeAlso <http://drobilla.net/drobilla.xrdf>
+ ] .
+
+
+#######################
+## Plugin Properties ##
+#######################
+
+osc:interfacePort a rdf:Property ;
+ rdfs:domain lv2:Plugin ;
+ rdfs:range lv2:Port ;
+ rdfs:label "Has a main OSC control port" ;
+ rdfs:comment """
+Specifies a port that can be used as the OSC interface for the plugin as a
+whole. For example, if a host is providing an OSC interface to a plugin at
+/some/osc/path/someplugin and a message /some/osc/path/someplugin/foo is
+received, the message /foo should be sent to this port.
+""" .
+
diff --git a/ext/parameter.lv2/manifest.ttl b/ext/parameter.lv2/manifest.ttl
new file mode 100644
index 0000000..04e511d
--- /dev/null
+++ b/ext/parameter.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/parameter>
+ a lv2:Specification ;
+ rdfs:seeAlso <parameter.ttl> .
+
diff --git a/ext/parameter.lv2/parameter.ttl b/ext/parameter.lv2/parameter.ttl
new file mode 100644
index 0000000..5970844
--- /dev/null
+++ b/ext/parameter.lv2/parameter.ttl
@@ -0,0 +1,110 @@
+# LV2 Parameter Extension
+# Copyright (C) 2010 David Robillard <d@drobilla.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix param: <http://lv2plug.in/ns/ext/parameter#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema> .
+
+<http://lv2plug.in/ns/ext/parameter>
+ a lv2:Specification ;
+ doap:name "LV2 Parameter" ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "David Robillard" ;
+ foaf:homepage <http://drobilla.net/> ;
+ rdfs:seeAlso <http://drobilla.net/drobilla.rdf>
+ ] ;
+ rdfs:comment """
+""" .
+
+
+param:Parameter a rdfs:Class ; a lv2:Resource ;
+ rdfs:label "Parameter" ;
+ rdfs:comment """
+A parameter on an LV2 plugin. Parameters can be manipulated to alter the
+behaviour or output of a plugin. Unlike lv2:ControlPort:
+<ul>
+<li>A parameter may have any data type</li>
+<li>Parameters can be dynamically added or removed</li>
+<li>Parameter values can be manipulated by the plugin</li>
+</ul>
+
+Note that plugins are not required to support this potential functionality,
+parameters can be used to provide a basic LADSPA-like set of floating point
+parameters in a more extensible manner.
+
+Parameters are essentially controls that are not 1:1 associated with ports
+(manipulation of parameters can be accomplished by e.g. sending messages
+to a command port).
+""" .
+
+
+param:supportsType a rdf:Property ;
+ rdfs:domain param:Parameter ;
+ rdfs:range atom:AtomType ;
+ rdfs:label "supports type" ;
+ rdfs:comment """
+Indicates that a Parameter has values of a particular type. A Parameter
+may support many types. Parameter values are always LV2 Atoms as defined
+by the LV2 Atom Extension &lthttp://lv2plug.in/ns/ext/atom#&gt;. Any type
+of LV2 Atom may be used as a parameter value.
+""" .
+
+
+param:value a rdf:Property ;
+ rdfs:domain param:Parameter ;
+ rdfs:label "value" ;
+ rdfs:comment """
+Indicates that a Parameter has a certain value. A Parameter has at most
+one value at any given time. The type of the value specified must be
+one of the types specified by param:supportsType. When used in a plugin
+data file this property specifies the default value of a parameter.
+""" .
+
+
+param:minimum a rdf:Property ;
+ rdfs:domain param:Parameter ;
+ rdfs:label "minimum" ;
+ rdfs:comment """
+Specifies the minimum value of a Parameter (for Parameters with comparable
+types for which this makes sense). The type of the minimum must be one of
+the types specified by param:supportsType. The host MAY attempt to set a
+parameter to any value (of a legal type), i.e. the plugin MUST NOT assume
+attempts to change a parameter are within range and SHOULD clamp accordingly.
+""" .
+
+
+param:maximum a rdf:Property ;
+ rdfs:domain param:Parameter ;
+ rdfs:label "maximum" ;
+ rdfs:comment """
+Specifies the maximum value of a Parameter (for Parameters with comparable
+types for which this makes sense). The type of the maximum must be one of
+the types specified by param:supportsType. The host MAY attempt to set a
+parameter to any value (of a legal type), i.e. the plugin MUST NOT assume
+attempts to change a parameter are within range and SHOULD clamp accordingly.
+""" .
+
diff --git a/ext/persist.lv2/manifest.ttl b/ext/persist.lv2/manifest.ttl
new file mode 100644
index 0000000..f1a7ecd
--- /dev/null
+++ b/ext/persist.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/persist>
+ a lv2:Specification ;
+ rdfs:seeAlso <persist.ttl> .
+
diff --git a/ext/persist.lv2/persist.h b/ext/persist.lv2/persist.h
new file mode 100644
index 0000000..928a297
--- /dev/null
+++ b/ext/persist.lv2/persist.h
@@ -0,0 +1,177 @@
+/* lv2_persist.h - C header file for the LV2 Persist extension.
+ * Copyright (C) 2010 Leonard Ritter <paniq@paniq.org>
+ *
+ * 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
+ */
+
+/** @file
+ * C header for the LV2 Persist extension <http://lv2plug.in/ns/ext/persist>.
+ */
+
+#ifndef LV2_PERSIST_H
+#define LV2_PERSIST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LV2_PERSIST_URI "http://lv2plug.in/ns/ext/persist"
+
+/** Causes the host to store a value under a given key.
+ *
+ * This callback is passed by the host to LV2_Persist.save().
+ * @param callback_data Must be the callback_data passed to LV2_Persist.save().
+ * @param key The URI key (RDF predicate) under which the value is to be stored.
+ * @param value Pointer to the value (RDF object) to be stored.
+ * @param size The size of the data at @a value in bytes.
+ * @param type The type of @a value, as a URI mapped to an integer.
+ *
+ * Unless @a type is 0, @a value is guaranteed to be POD (i.e. a region
+ * of memory that does not contain pointers and can safely be copied
+ * and persisted indefinitely with a simple memcpy). If @a type is 0,
+ * then @a value is a reference, as defined by the LV2 Atom extension
+ * <http://lv2plug.in/ns/ext/atom/>. Hosts are not required to support
+ * references, a plugin MUST NOT expect a host to persist references unless
+ * the host supports the feature <http://lv2plug.in/ns/ext/atom#blobSupport>.
+ *
+ * Note that @a size MUST be > 0, and @a value MUST point to a valid region of
+ * memory @a size bytes long (this is required to make restore unambiguous).
+ * If only the key is of interest, store the empty string (which has size 1).
+ */
+typedef void (*LV2_Persist_Store_Function)(
+ void* callback_data,
+ const char* key,
+ const void* value,
+ size_t size,
+ uint32_t type);
+
+/** Causes the host to retrieve a value under a given key.
+ *
+ * This callback is passed by the host to LV2_Persist.restore().
+ * @param callback_data Must be the callback_data passed to LV2_Persist.restore().
+ * @param key The URI key (RDF predicate) under which a value has been stored.
+ * @param size (Output) If non-NULL, set to the size of the restored value.
+ * @param type (Output) If non-NULL, set to the type of the restored value.
+ * @return A pointer to the restored value (RDF object), or NULL if no value
+ * has been stored under @a key.
+ *
+ * The returned value MUST remain valid until LV2_Persist.restore() returns. The plugin
+ * MUST NOT attempt to access a returned pointer outside of the LV2_Persist.restore()
+ * context (it MUST make a copy in order to do so).
+ */
+typedef const void* (*LV2_Persist_Retrieve_Function)(
+ void* callback_data,
+ const char* key,
+ size_t* size,
+ uint32_t* type);
+
+/** When the plugin's extension_data is called with argument LV2_PERSIST_URI,
+ * the plugin MUST return an LV2_Persist structure, which remains valid for
+ * the lifetime of the plugin.
+ *
+ * The host can use the contained function pointers to save and restore the
+ * state of a plugin instance at any time (provided the threading restrictions
+ * for the given function are met).
+ *
+ * The typical use case is to save the plugin's state when a project is
+ * saved, and to restore the state when a project has been loaded. Other
+ * uses are possible (e.g. cloning plugin instances or taking a snapshot
+ * of plugin state).
+ *
+ * Stored data is only guaranteed to be compatible between instances of plugins
+ * with the same URI (i.e. if a change to a plugin would cause a fatal error
+ * when restoring state saved by a previous version of that plugin, the plugin
+ * URI must change just as it must when a plugin's ports change). Plugin
+ * authors should consider this possibility, and always store sensible data
+ * with meaningful types to avoid such compatibility issues in the future.
+ */
+typedef struct _LV2_Persist {
+ /** Causes the plugin to save state data using a host-provided
+ * @a store callback.
+ *
+ * @param instance The instance handle of the plugin.
+ * @param store The host-provided store callback.
+ * @param callback_data An opaque pointer to host data, e.g. the map or
+ * file where the values are to be stored. If @a store is called,
+ * this MUST be passed as its callback_data parameter.
+ *
+ * The plugin is expected to store everything necessary to completely
+ * restore its state later (possibly much later, in a different
+ * process, on a completely different machine, etc.)
+ *
+ * The @a callback_data pointer and @a store function MUST NOT be
+ * used beyond the scope of save().
+ *
+ * This function has its own special threading class: it may not be
+ * called concurrently with any "Instantiation" function, but it
+ * may be called concurrently with functions in any other class,
+ * unless the definition of that class prohibits it (e.g. it may
+ * not be called concurrently with a "Discovery" function, but it
+ * may be called concurrently with an "Audio" function. The plugin
+ * is responsible for any locking or lock-free techniques necessary
+ * to make this possible.
+ *
+ * Note that in the simple case where state is only modified by
+ * restore(), there are no synchronization issues since save() is
+ * never called concurrently with restore() (though run() may read
+ * it during a save).
+ *
+ * Plugins that dynamically modify state while running, however,
+ * must take care to do so in such a way that a concurrent call to
+ * save() will save a consistent representation of plugin state for a
+ * single point in time. The simplest way to do this is to modify a
+ * copy of the state map and atomically swap a pointer to the entire
+ * map once the changes are complete (for very large state maps,
+ * a purely functional map data structure would be more appropriate
+ * since a complete copy is not necessary).
+ */
+ void (*save)(LV2_Handle instance,
+ LV2_Persist_Store_Function store,
+ void* callback_data);
+
+ /** Causes the plugin to restore state data using a host-provided
+ * @a retrieve callback.
+ *
+ * @param instance The instance handle of the plugin.
+ * @param retrieve The host-provided retrieve callback.
+ * @param callback_data An opaque pointer to host data, e.g. the map or
+ * file from which the values are to be restored. If @a retrieve is
+ * called, this MUST be passed as its callback_data parameter.
+ *
+ * The plugin MAY assume a restored value was set by a previous call to
+ * LV2_Persist.save() by a plugin with the same URI.
+ *
+ * The plugin MUST gracefully fall back to a default value when a
+ * value can not be retrieved. This allows the host to reset the
+ * plugin state with an empty map.
+ *
+ * The @a callback_data pointer and @a store function MUST NOT be used
+ * beyond the scope of restore().
+ *
+ * This function is in the "Instantiation" threading class as defined
+ * by LV2. This means it MUST NOT be called concurrently with any other
+ * function on the same plugin instance.
+ */
+ void (*restore)(LV2_Handle instance,
+ LV2_Persist_Retrieve_Function retrieve,
+ void* callback_data);
+
+} LV2_Persist;
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* LV2_PERSIST_H */
diff --git a/ext/persist.lv2/persist.ttl b/ext/persist.lv2/persist.ttl
new file mode 100644
index 0000000..f1dd86f
--- /dev/null
+++ b/ext/persist.lv2/persist.ttl
@@ -0,0 +1,116 @@
+# LV2 Persist Extension
+# Copyright (C) 2010 Leonard Ritter <paniq@paniq.org>
+# Copyright (C) 2010 David Robillard <d@drobilla.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix persist: <http://lv2plug.in/ns/ext/persist#> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema> .
+
+<http://lv2plug.in/ns/ext/persist>
+ a lv2:Specification ;
+ doap:name "LV2 Persist" ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "David Robillard" ;
+ foaf:homepage <http://drobilla.net/> ;
+ rdfs:seeAlso <http://drobilla.net/drobilla.rdf>
+ ] ;
+ rdfs:comment """
+This extension provides a mechanism for plugins to save and restore state
+across instances, allowing hosts to save configuration/state/data with a
+project or fully clone a plugin instance (including internal state).
+
+The motivating idea behind this extension is that a plugin instance's state
+is entirely represented by port values and a single key/value dictionary.
+This makes state well-defined and easily manageable by hosts. Keys are URIs,
+avoiding conflicts and allowing the same dictionary to be used to store plugin
+state in any context. Values are typed tagged (by URI mapped integers),
+but otherwise are simple binary blobs.
+
+This extension defines plugin instance state and provides a mechanism
+for saving/restoring it, but otherwise makes no restrictions on how a
+plugin works with state. For example, other extensions may define dynamic
+ways to control plugin state at runtime. The idea is that <em>all</em>
+plugin state can be represented with a single (conceptual) dictionary.
+This state representation is tried-and-true, universal, and works well with
+many existing technologies. Accordingly, plugins/extensions that deal with
+instance state in any way SHOULD represent it in a way compatible with this
+extension, i.e. URI keys with URI-typed values. Similarly, plugins SHOULD NOT
+use any other mechanism to store/restore state; this <strong>will</strong>
+cause serious problems, don't do it! Note that you can store values of any
+format whatsoever, so if you have an existing state representation to use
+(e.g. XML), simply store it as a single value under some key.
+
+Files may be persisted using this extension in conjunction with the
+<a href="http://lv2plug.in/ns/ext/files">LV2 Files</a> extension.
+
+Instance state as defined by this extension is RDF compatible, allowing for
+simple and seamless integration with existing technology (LV2 or otherwise).
+An obvious benefit of this is that plugin state can be elegantly described
+in Turtle files; the persist:instanceState predicate is provided for this
+purpose. RDF compatibility is also convenient since LV2 hosts are likely
+to already have mechanisms for working with RDF-style data. Note, however,
+that hosts may store state in any way, and are not required to use any
+specific technology or file format to support this extension.
+""" .
+
+persist:InstanceState
+ a rdfs:Class ;
+ rdfs:label "Plugin Instance State" ;
+ rdfs:comment """
+This class is used to express a plugin instance's state in RDF. The key/value
+properties of the instance form the predicate/object (respectively) of triples
+with a persist:InstanceState as the subject (see persist:instanceState
+for an example). This may be used wherever it is useful to express a
+plugin instance's state in RDF (e.g. for serialisation, storing in a model, or
+transmitting over a network). Note that this class is provided because it
+may be useful for hosts, plugins, or extensions that work with instance state,
+but its use is not required to support the LV2 Persist extension.
+""" .
+
+
+persist:instanceState
+ a rdf:Property ;
+ rdfs:range persist:InstanceState ;
+ rdfs:comment """
+Predicate to relate a plugin instance to an InstanceState. This may be used
+wherever the state of a particular plugin instance needs to be represented.
+Note that the domain of this property is unspecified, since LV2 does not
+define any RDF class for plugin instance. This predicate may be used
+wherever it makes sense to do so, e.g.:
+<pre>
+@prefix eg: &lt;http://example.org/&gt .
+
+&lt;plugininstance&gt; persist:instanceState [
+ eg:somekey "some value" ;
+ eg:someotherkey "some other value" ;
+ eg:favouritenumber 2 .
+]
+</pre>
+Note that this property is provided because it may be useful for hosts,
+plugins, or extensions that work with instance state, but its use is not
+required to support the LV2 Persist extension.
+""" .
+ \ No newline at end of file
diff --git a/ext/polymorphic-port.lv2/manifest.ttl b/ext/polymorphic-port.lv2/manifest.ttl
new file mode 100644
index 0000000..abe3788
--- /dev/null
+++ b/ext/polymorphic-port.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/polymorphic-port>
+ a lv2:Specification ;
+ rdfs:seeAlso <polymorphic-port.ttl> .
+
diff --git a/ext/polymorphic-port.lv2/polymorphic-port.h b/ext/polymorphic-port.lv2/polymorphic-port.h
new file mode 100644
index 0000000..98d691e
--- /dev/null
+++ b/ext/polymorphic-port.lv2/polymorphic-port.h
@@ -0,0 +1,63 @@
+/* lv2_data_access.h - C header file for the LV2 Data Access 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
+ */
+
+/** @file
+ * C header for the LV2 Polymorphic Port extension
+ * <http://lv2plug.in/ns/ext/polymorphic-port>.
+ *
+ * This extension defines a buffer format for ports that can take on
+ * various types dynamically at runtime.
+ */
+
+#ifndef LV2_POLYMORPHIC_PORT_H
+#define LV2_POLYMORPHIC_PORT_H
+
+#define LV2_POLYMORPHIC_PORT_URI "http://lv2plug.in/ns/ext/polymorphic-port"
+
+/** The data field of the LV2_Feature for this extension.
+ *
+ * To support this feature the host must pass an LV2_Feature struct to the
+ * instantiate method with URI "http://lv2plug.in/ns/ext/polymorphic-port"
+ * and data pointed to an instance of this struct.
+ */
+typedef struct {
+
+ /** Set the type of a polymorphic port.
+ * If the plugin specifies constraints on port types, the host MUST NOT
+ * call the run method until all port types have been set to a valid
+ * configuration. Whenever the type for a port is changed, the host
+ * MUST call connect_port before the next call to the run method.
+ * The return value of this function SHOULD be ignored by hosts at this
+ * time (future revisions of this extension may specify return values).
+ * Plugins which do not know of any future revision or extension that
+ * dictates otherwise MUST return 0 from this function.
+ * @param port Index of the port to connect (same as LV2 connect_port)
+ * @param type Mapped URI for the type of data being connected
+ * @param type_data Type specific data defined by type URI (may be NULL)
+ * @return Unused at this time
+ */
+ uint32_t (*set_type)(LV2_Handle instance,
+ uint32_t port,
+ uint32_t type,
+ void* type_data);
+
+} LV2_Polymorphic_Feature;
+
+
+#endif /* LV2_POLYMORPHIC_PORT_H */
+
diff --git a/ext/polymorphic-port.lv2/polymorphic-port.ttl b/ext/polymorphic-port.lv2/polymorphic-port.ttl
new file mode 100644
index 0000000..b3d1b37
--- /dev/null
+++ b/ext/polymorphic-port.lv2/polymorphic-port.ttl
@@ -0,0 +1,71 @@
+# LV2 Polymorphic Port Extension
+# Copyright (C) 2008 David Robillard <d@drobilla.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix polym: <http://lv2plug.in/ns/ext/polymorphic-port#> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+
+<http://lv2plug.in/ns/ext/polymorphic-port> a lv2:Specification ;
+ doap:license <http://usefulinc.com/doap/licenses/mit> ;
+ doap:name "LV2 Polymorphic Ports" ;
+ rdfs:comment "Defines LV2 ports which can dynamically change type" ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "David Robillard" ;
+ foaf:homepage <http://drobilla.net/> ;
+ rdfs:seeAlso <http://drobilla.net/drobilla.rdf>
+ ] .
+
+
+polym:PolymorphicPort a rdfs:Class ;
+ rdfs:label "Polymorphic port" ;
+ rdfs:subClassOf lv2:Port ;
+ rdfs:comment """
+Ports of this type may be connected to buffers of several types. The plugin
+provides a set_type function for the host to specify which type a port is
+currently connected to.
+
+A Port specifies the types it supports using the :supportsType property.
+The type specific in the normal LV2 manner (&lt;port&gt; a &lt;sometype&gt;)
+is the "default type". If the port is connected without set_type being called
+for that port, the type of the buffer is assumed to be the default type.
+In this way polymorphic plugins are backwards compatible and may be used by
+hosts which are not aware of the polymorphic port extension.
+""" .
+
+polym:generic a lv2:PortProperty ;
+ rdfs:label "Generic polymorphic port" ;
+ rdfs:comment """
+Indicates that this port can be connected to a buffer of any type.
+""" .
+
+polym:supportsType a rdf:Property ;
+ rdfs:domain lv2:Port ;
+ rdfs:label "Supports data type" ;
+ rdfs:comment """
+Indicates that this port supports or "understands" a certain data type.
+Hosts MUST NOT connect a port to a buffer unless the port is :generic,
+or is described as supporting the type of that buffer with this property.
+""" .
+
diff --git a/ext/port-groups.lv2/manifest.ttl b/ext/port-groups.lv2/manifest.ttl
new file mode 100644
index 0000000..4f6c01c
--- /dev/null
+++ b/ext/port-groups.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/port-groups>
+ a lv2:Specification ;
+ rdfs:seeAlso <port-groups.ttl> .
+
diff --git a/ext/port-groups.lv2/port-groups.ttl b/ext/port-groups.lv2/port-groups.ttl
new file mode 100644
index 0000000..e0512db
--- /dev/null
+++ b/ext/port-groups.lv2/port-groups.ttl
@@ -0,0 +1,489 @@
+# LV2 Port Groups Extension
+# PROVISIONAL
+# Copyright (C) 2009 David Robillard <d@drobilla.net>
+# Copyright (C) 2008-2009 Lars Luthman <lars.luthman@gmail.com>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix pg: <http://lv2plug.in/ns/ext/port-groups#> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix amb: <http://ambisonics.ch/standards/channels/> .
+
+<http://lv2plug.in/ns/ext/port-groups> a lv2:Specification ;
+ doap:license <http://usefulinc.com/doap/licenses/mit> ;
+ doap:name "LV2 Port Groups" ;
+ rdfs:comment "Defines semantic groupings of LV2 ports" ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "Lars Luthman" ;
+ foaf:mbox <mailto:lars.luthman@gmail.com>
+ ] , [
+ a foaf:Person ;
+ foaf:name "David Robillard" ;
+ foaf:homepage <http://drobilla.net/> ;
+ rdfs:seeAlso <http://drobilla.net/drobilla.rdf>
+ ] .
+
+
+## Core Classes / Properties
+
+pg:Group a rdfs:Class ;
+ rdfs:label "LV2 Port Group" ;
+ rdfs:subClassOf [ a owl:Restriction ;
+ owl:onProperty lv2:symbol ;
+ owl:someValuesFrom xsd:string ;
+ owl:cardinality 1 ;
+ rdfs:comment """
+A pg:Group MUST have exactly one string lv2:symbol. This symbol must be
+unique according to the same rules as the lv2:symbol for an lv2:Port, where
+group symbols and port symbols reside in the same namespace. In other words,
+a group on a plugin MUST NOT have the same symbol as another group or a port
+on that plugin. Rationale: Hosts or bindings may find it useful to construct
+an identifier to refer to groups for the same reasons this is useful for ports.
+"""
+ ] ;
+ rdfs:subClassOf [ a owl:Restriction ;
+ owl:onProperty pg:hasRole ;
+ owl:someValuesFrom pg:RoleAssignment ;
+ owl:minCardinality 1 ;
+ rdfs:comment "A Group MUST have at least one role assignment"
+ ] ;
+ rdfs:comment """
+A grouping of ports that can be logically considered a single "stream", e.g.
+two audio ports in a group may form a stereo stream. The pg:source predicate
+can also be used to describe this correspondence between separate ports/groups.
+""" .
+
+pg:index a rdf:Property ;
+ rdfs:domain pg:RoleAssignment ;
+ rdfs:range xsd:nonNegativeInteger ;
+ rdfs:label "index" ;
+ rdfs:comment "Index of a role within some group" .
+
+pg:RoleAssignment a rdfs:Class ;
+ rdfs:label "Role Assignment" ;
+ rdfs:comment "A numbered role within some Group." ;
+ rdfs:subClassOf [ a owl:Restriction ;
+ owl:onProperty pg:index ;
+ owl:cardinality 1 ;
+ rdfs:comment """
+A RoleAssignment MUST have exactly one index.
+""" ] ;
+ rdfs:subClassOf [ a owl:Restriction ;
+ owl:onProperty pg:role ;
+ owl:cardinality 1 ;
+ rdfs:comment """
+A RoleAssignment MUST have exactly one role.
+""" ] ;
+ rdfs:comment """
+All group definitions MUST define the order of channels. Note that this
+does not have anything to do with port indices, this information is only
+defined here for use by other extensions. For simply assigning groups
+and roles to a basic LV2 plugin, index is irrelevant.
+""" .
+
+pg:hasChannel a rdf:Property ;
+ rdfs:domain pg:Group ;
+ rdfs:range pg:Channel ;
+ rdfs:label "Has port with role" ;
+ rdfs:comment """
+Indicates that a group always has a port with a particular role.
+""" .
+
+pg:sideChainOf a rdf:Property ;
+ rdfs:domain pg:Group , lv2:Port ;
+ rdfs:range pg:Group , lv2:Port ;
+ rdfs:label "Side-chain of" ;
+ rdfs:comment """
+Indicates that this port or group should be considered a "side chain" of
+some other port or group. The precise definition of "side chain" depends
+on the plugin, but in general this group should be considered a modifier to
+some other group, rather than an independent input itself.
+""" .
+
+pg:subGroupOf a rdf:Property ;
+ rdfs:domain pg:Group ;
+ rdfs:range pg:Group ;
+ rdfs:label "Sub-group of" ;
+ rdfs:comment """
+Indicates that this group is a child of another group. This property has
+no meaning with respect to plugin execution, but the host may find this
+information useful (e.g. to provide a compact user interface). Note that
+all groups on a plugin MUST have a unique symbol with respect to the plugin
+as documented for pg:Group, i.e. sub-groups must have a unique symbol among
+all groups and ports on the plugin.
+""" .
+
+pg:source a rdf:Property ;
+ rdfs:domain pg:Group , lv2:Port ;
+ rdfs:range pg:Group , lv2:Port ;
+ rdfs:label "Source group" ;
+ rdfs:comment """
+Indicates that this port or group should be considered the "result" of
+some other port or group. This property only makes sense on groups with
+outputs when the source is a group with inputs. This can be used to convey
+a relationship between corresponding input and output groups with different
+types, e.g. a mono->stereo plugin.
+""" .
+
+pg:mainGroup a rdf:Property ;
+ rdfs:domain lv2:Plugin ;
+ rdfs:range pg:Group ;
+ rdfs:label "Main port group" ;
+ rdfs:comment """
+Indicates that this group should be considered the "main" inputs/outputs of
+the plugin, e.g. it probably makes sense to just connect main groups and set
+some controls. A plugin MUST NOT have more than one :mainGroup property.
+High-level hosts that simply want to insert an plugin in a given stream
+should use this property to determine where the plugin 'fits'.
+""" .
+
+pg:inGroup a rdf:Property ;
+ rdfs:domain lv2:Port ;
+ rdfs:range pg:Group ;
+ rdfs:label "In port group" ;
+ rdfs:comment """
+Indicates that this port is a part of a group of ports on the plugin.
+Ports that have a meaningful "role" that may be useful to hosts SHOULD also
+have a :role property, otherwise ports in the group have no meaningful order.
+""" .
+
+pg:Role a rdfs:Class ;
+ rdfs:label "Port role" ;
+ rdfs:comment """
+The role of a port with respect to its plugin or group. If the port is a
+member of a group (has an :inGroup property) the role is relevant with respect
+to that group. Otherwise the role is relevant with respect to the plugin.
+""" .
+
+pg:role a rdf:Property ;
+ rdfs:domain pg:Port , pg:RoleAssignment;
+ rdfs:range pg:Role ;
+ rdfs:label "Role" ;
+ rdfs:comment """
+Indicates that this port has a particular role with respect to its enclosing
+plugin or group (whichever is smaller). A port may have several roles if it
+makes sense to do so (though some Role or Group definition may forbid this).
+""" .
+
+
+# Discrete
+
+pg:DiscreteGroup a rdfs:Class ;
+ rdfs:subClassOf pg:Group ;
+ rdfs:comment """
+"Discrete" channel configurations. These groups are divided into channels
+where each represents a particular speaker location. The position of sound
+in one of these groups depends on a particular speaker configuration.
+""" .
+
+pg:leftChannel a pg:Role ; rdfs:label "Left" .
+pg:rightChannel a pg:Role ; rdfs:label "Right" .
+pg:centerChannel a pg:Role ; rdfs:label "Center" .
+pg:sideChannel a pg:Role ; rdfs:label "Side" .
+pg:centerLeftChannel a pg:Role ; rdfs:label "Center Left" .
+pg:centerRightChannel a pg:Role ; rdfs:label "Center Right" .
+pg:sideLeftChannel a pg:Role ; rdfs:label "Side Left" .
+pg:sideRightChannel a pg:Role ; rdfs:label "Side Right" .
+pg:rearLeftChannel a pg:Role ; rdfs:label "Rear Left" .
+pg:rearRightChannel a pg:Role ; rdfs:label "Rear Right" .
+pg:rearCenterChannel a pg:Role ; rdfs:label "Rear Center" .
+pg:lfeChannel a pg:Role ; rdfs:label "Sub (LFE)" .
+
+pg:MonoGroup a rdfs:Class ;
+ rdfs:subClassOf pg:DiscreteGroup ;
+ rdfs:label "Mono" ;
+ pg:hasRole [ pg:index 0; pg:role pg:centerChannel ] .
+
+pg:StereoGroup a rdfs:Class ;
+ rdfs:subClassOf pg:DiscreteGroup ;
+ rdfs:label "Stereo" ;
+ pg:hasRole [ pg:index 0; pg:role pg:leftChannel ] ;
+ pg:hasRole [ pg:index 1; pg:role pg:rightChannel ] .
+
+pg:MidSideGroup a rdfs:Class ;
+ rdfs:subClassOf pg:DiscreteGroup ;
+ rdfs:label "Mid-Side Stereo" ;
+ pg:hasRole [ pg:index 0; pg:role pg:centerChannel ] ;
+ pg:hasRole [ pg:index 1; pg:role pg:sideChannel ] .
+
+pg:ThreePointZeroGroup a rdfs:Class ;
+ rdfs:subClassOf pg:DiscreteGroup ;
+ rdfs:label "3.0 Surround" ;
+ pg:hasRole [ pg:index 0; pg:role pg:leftChannel ] ;
+ pg:hasRole [ pg:index 1; pg:role pg:rightChannel ] ;
+ pg:hasRole [ pg:index 2; pg:role pg:rearCenterChannel ] .
+
+pg:FourPointZeroGroup a rdfs:Class ;
+ rdfs:subClassOf pg:DiscreteGroup ;
+ rdfs:label "4.0 Surround (Quadraphonic)" ;
+ pg:hasRole [ pg:index 0; pg:role pg:leftChannel ] ;
+ pg:hasRole [ pg:index 1; pg:role pg:centerChannel ] ;
+ pg:hasRole [ pg:index 2; pg:role pg:rightChannel ] ;
+ pg:hasRole [ pg:index 3; pg:role pg:rearCenterChannel ] .
+
+pg:FivePointZeroGroup a rdfs:Class ;
+ rdfs:subClassOf pg:DiscreteGroup ;
+ rdfs:label "5.0 Surround (3-2 stereo)" ;
+ pg:hasRole [ pg:index 0; pg:role pg:leftChannel ] ;
+ pg:hasRole [ pg:index 1; pg:role pg:centerChannel ] ;
+ pg:hasRole [ pg:index 2; pg:role pg:rightChannel ] ;
+ pg:hasRole [ pg:index 3; pg:role pg:rearLeftChannel ] ;
+ pg:hasRole [ pg:index 4; pg:role pg:rearRightChannel ] .
+
+pg:FivePointOneGroup a rdfs:Class ;
+ rdfs:subClassOf pg:DiscreteGroup ;
+ rdfs:label "5.1 Surround (3-2 stereo)" ;
+ pg:hasRole [ pg:index 0; pg:role pg:leftChannel ] ;
+ pg:hasRole [ pg:index 1; pg:role pg:centerChannel ] ;
+ pg:hasRole [ pg:index 2; pg:role pg:rightChannel ] ;
+ pg:hasRole [ pg:index 3; pg:role pg:rearLeftChannel ] ;
+ pg:hasRole [ pg:index 4; pg:role pg:rearRightChannel ] ;
+ pg:hasRole [ pg:index 5; pg:role pg:lfeChannel ] .
+
+pg:SixPointOneGroup a rdfs:Class ;
+ rdfs:subClassOf pg:DiscreteGroup ;
+ rdfs:label "6.1 Surround" ;
+ pg:hasRole [ pg:index 0; pg:role pg:leftChannel ] ;
+ pg:hasRole [ pg:index 1; pg:role pg:centerChannel ] ;
+ pg:hasRole [ pg:index 2; pg:role pg:rightChannel ] ;
+ pg:hasRole [ pg:index 3; pg:role pg:sideLeftChannel ] ;
+ pg:hasRole [ pg:index 4; pg:role pg:sideRightChannel ] ;
+ pg:hasRole [ pg:index 5; pg:role pg:rearCenterChannel ] ;
+ pg:hasRole [ pg:index 6; pg:role pg:lfeChannel ] .
+
+pg:SevenPointOneGroup a rdfs:Class ;
+ rdfs:subClassOf pg:DiscreteGroup ;
+ rdfs:label "7.1 Surround" ;
+ pg:hasRole [ pg:index 0; pg:role pg:leftChannel ] ;
+ pg:hasRole [ pg:index 1; pg:role pg:centerChannel ] ;
+ pg:hasRole [ pg:index 2; pg:role pg:rightChannel ] ;
+ pg:hasRole [ pg:index 3; pg:role pg:sideLeftChannel ] ;
+ pg:hasRole [ pg:index 4; pg:role pg:sideRightChannel ] ;
+ pg:hasRole [ pg:index 5; pg:role pg:rearLeftChannel ] ;
+ pg:hasRole [ pg:index 6; pg:role pg:rearRightChannel ] ;
+ pg:hasRole [ pg:index 7; pg:role pg:lfeChannel ] .
+
+pg:SevenPointOneWideGroup a rdfs:Class ;
+ rdfs:subClassOf pg:DiscreteGroup ;
+ rdfs:label "7.1 Surround (Wide)" ;
+ pg:hasRole [ pg:index 0; pg:role pg:leftChannel ] ;
+ pg:hasRole [ pg:index 1; pg:role pg:centerLeftChannel ] ;
+ pg:hasRole [ pg:index 2; pg:role pg:centerChannel ] ;
+ pg:hasRole [ pg:index 3; pg:role pg:centerRightChannel ] ;
+ pg:hasRole [ pg:index 4; pg:role pg:rightChannel ] ;
+ pg:hasRole [ pg:index 5; pg:role pg:leftRearChannel ] ;
+ pg:hasRole [ pg:index 6; pg:role pg:rightRearChannel ] ;
+ pg:hasRole [ pg:index 7; pg:role pg:lfeChannel ] .
+
+
+# Ambisonic
+
+pg:AmbisonicGroup a rdfs:Class ;
+ rdfs:subClassOf pg:Group ;
+ rdfs:comment """
+"Ambisonic" channel configurations. These groups are divided into channels
+which together represent a position in an abstract n-dimensional space.
+The position of sound in one of these groups does not depend on a particular
+speaker configuration; a decoder can be used to convert an ambisonic stream
+for any speaker configuration.
+""" .
+
+#amb:ACN0 a pg:Role ; rdfs:label "ACN 0 (W)" .
+#amb:ACN1 a pg:Role ; rdfs:label "ACN 1 (Y)" .
+#amb:ACN2 a pg:Role ; rdfs:label "ACN 2 (Z)" .
+#amb:ACN3 a pg:Role ; rdfs:label "ACN 3 (X)" .
+#amb:ACN4 a pg:Role ; rdfs:label "ACN 4 (V)" .
+#amb:ACN5 a pg:Role ; rdfs:label "ACN 5 (T)" .
+#amb:ACN6 a pg:Role ; rdfs:label "ACN 6 (R)" .
+#amb:ACN7 a pg:Role ; rdfs:label "ACN 7 (S)" .
+#amb:ACN8 a pg:Role ; rdfs:label "ACN 8 (U)" .
+#amb:ACN9 a pg:Role ; rdfs:label "ACN 9 (Q)" .
+#amb:ACN10 a pg:Role ; rdfs:label "ACN 10 (O)" .
+#amb:ACN11 a pg:Role ; rdfs:label "ACN 11 (M)" .
+#amb:ACN12 a pg:Role ; rdfs:label "ACN 12 (K)" .
+#amb:ACN13 a pg:Role ; rdfs:label "ACN 13 (L)" .
+#amb:ACN14 a pg:Role ; rdfs:label "ACN 14 (N)" .
+#amb:ACN15 a pg:Role ; rdfs:label "ACN 15 (P)" .
+
+pg:AmbisonicBH1P0Group a rdfs:Class ;
+ rdfs:subClassOf pg:AmbisonicGroup ;
+ rdfs:label "Ambisonic B stream of horizontal order 1 and peripheral order 0." ;
+ pg:hasRole [ pg:index 0; pg:role amb:ACN0 ] ;
+ pg:hasRole [ pg:index 1; pg:role amb:ACN1 ] ;
+ pg:hasRole [ pg:index 2; pg:role amb:ACN3 ] .
+
+pg:AmbisonicBH1P1Group a rdfs:Class ;
+ rdfs:subClassOf pg:AmbisonicGroup ;
+ rdfs:label "Ambisonic B stream of horizontal order 1 and peripheral order 1." ;
+ pg:hasRole [ pg:index 0; pg:role amb:ACN0 ] ;
+ pg:hasRole [ pg:index 1; pg:role amb:ACN1 ] ;
+ pg:hasRole [ pg:index 2; pg:role amb:ACN2 ] ;
+ pg:hasRole [ pg:index 3; pg:role amb:ACN3 ] .
+
+pg:AmbisonicBH2P0Group a rdfs:Class ;
+ rdfs:subClassOf pg:AmbisonicGroup ;
+ rdfs:label "Ambisonic B stream of horizontal order 2 and peripheral order 0." ;
+ pg:hasRole [ pg:index 0; pg:role amb:ACN0 ] ;
+ pg:hasRole [ pg:index 1; pg:role amb:ACN1 ] ;
+ pg:hasRole [ pg:index 2; pg:role amb:ACN3 ] ;
+ pg:hasRole [ pg:index 3; pg:role amb:ACN4 ] ;
+ pg:hasRole [ pg:index 4; pg:role amb:ACN8 ] .
+
+pg:AmbisonicBH2P1Group a rdfs:Class ;
+ rdfs:subClassOf pg:AmbisonicGroup ;
+ rdfs:label "Ambisonic B stream of horizontal order 2 and peripheral order 1." ;
+ pg:hasRole [ pg:index 0; pg:role amb:ACN0 ] ;
+ pg:hasRole [ pg:index 1; pg:role amb:ACN1 ] ;
+ pg:hasRole [ pg:index 2; pg:role amb:ACN2 ] ;
+ pg:hasRole [ pg:index 3; pg:role amb:ACN3 ] ;
+ pg:hasRole [ pg:index 4; pg:role amb:ACN4 ] ;
+ pg:hasRole [ pg:index 5; pg:role amb:ACN8 ] .
+
+pg:AmbisonicBH2P2Group a rdfs:Class ;
+ rdfs:subClassOf pg:AmbisonicGroup ;
+ rdfs:label "Ambisonic B stream of horizontal order 2 and peripheral order 2." ;
+ pg:hasRole [ pg:index 0; pg:role amb:ACN0 ] ;
+ pg:hasRole [ pg:index 1; pg:role amb:ACN1 ] ;
+ pg:hasRole [ pg:index 2; pg:role amb:ACN2 ] ;
+ pg:hasRole [ pg:index 3; pg:role amb:ACN3 ] ;
+ pg:hasRole [ pg:index 4; pg:role amb:ACN4 ] ;
+ pg:hasRole [ pg:index 5; pg:role amb:ACN5 ] ;
+ pg:hasRole [ pg:index 6; pg:role amb:ACN6 ] ;
+ pg:hasRole [ pg:index 7; pg:role amb:ACN7 ] ;
+ pg:hasRole [ pg:index 8; pg:role amb:ACN8 ] .
+
+pg:AmbisonicBH3P0Group a rdfs:Class ;
+ rdfs:subClassOf pg:AmbisonicGroup ;
+ rdfs:label "Ambisonic B stream of horizontal order 3 and peripheral order 0." ;
+ pg:hasRole [ pg:index 0; pg:role amb:ACN0 ] ;
+ pg:hasRole [ pg:index 1; pg:role amb:ACN1 ] ;
+ pg:hasRole [ pg:index 2; pg:role amb:ACN3 ] ;
+ pg:hasRole [ pg:index 3; pg:role amb:ACN4 ] ;
+ pg:hasRole [ pg:index 4; pg:role amb:ACN8 ] ;
+ pg:hasRole [ pg:index 5; pg:role amb:ACN9 ] ;
+ pg:hasRole [ pg:index 6; pg:role amb:ACN15 ] .
+
+pg:AmbisonicBH3P1Group a rdfs:Class ;
+ rdfs:subClassOf pg:AmbisonicGroup ;
+ rdfs:label "Ambisonic B stream of horizontal order 3 and peripheral order 1." ;
+ pg:hasRole [ pg:index 0; pg:role amb:ACN0 ] ;
+ pg:hasRole [ pg:index 1; pg:role amb:ACN1 ] ;
+ pg:hasRole [ pg:index 2; pg:role amb:ACN2 ] ;
+ pg:hasRole [ pg:index 3; pg:role amb:ACN3 ] ;
+ pg:hasRole [ pg:index 4; pg:role amb:ACN4 ] ;
+ pg:hasRole [ pg:index 5; pg:role amb:ACN8 ] ;
+ pg:hasRole [ pg:index 6; pg:role amb:ACN9 ] ;
+ pg:hasRole [ pg:index 7; pg:role amb:ACN15 ] .
+
+pg:AmbisonicBH3P2Group a rdfs:Class ;
+ rdfs:subClassOf pg:AmbisonicGroup ;
+ rdfs:label "Ambisonic B stream of horizontal order 3 and peripheral order 2." ;
+ pg:hasRole [ pg:index 0; pg:role amb:ACN0 ] ;
+ pg:hasRole [ pg:index 1; pg:role amb:ACN1 ] ;
+ pg:hasRole [ pg:index 2; pg:role amb:ACN2 ] ;
+ pg:hasRole [ pg:index 3; pg:role amb:ACN3 ] ;
+ pg:hasRole [ pg:index 4; pg:role amb:ACN4 ] ;
+ pg:hasRole [ pg:index 5; pg:role amb:ACN5 ] ;
+ pg:hasRole [ pg:index 6; pg:role amb:ACN6 ] ;
+ pg:hasRole [ pg:index 7; pg:role amb:ACN7 ] ;
+ pg:hasRole [ pg:index 8; pg:role amb:ACN8 ] ;
+ pg:hasRole [ pg:index 9; pg:role amb:ACN9 ] ;
+ pg:hasRole [ pg:index 10; pg:role amb:ACN15 ] .
+
+pg:AmbisonicBH3P3Group a rdfs:Class ;
+ rdfs:subClassOf pg:AmbisonicGroup ;
+ rdfs:label "Ambisonic B stream of horizontal order 3 and peripheral order 3." ;
+ pg:hasRole [ pg:index 0; pg:role amb:ACN0 ] ;
+ pg:hasRole [ pg:index 1; pg:role amb:ACN1 ] ;
+ pg:hasRole [ pg:index 2; pg:role amb:ACN2 ] ;
+ pg:hasRole [ pg:index 3; pg:role amb:ACN3 ] ;
+ pg:hasRole [ pg:index 4; pg:role amb:ACN4 ] ;
+ pg:hasRole [ pg:index 5; pg:role amb:ACN5 ] ;
+ pg:hasRole [ pg:index 6; pg:role amb:ACN6 ] ;
+ pg:hasRole [ pg:index 7; pg:role amb:ACN7 ] ;
+ pg:hasRole [ pg:index 8; pg:role amb:ACN8 ] ;
+ pg:hasRole [ pg:index 9; pg:role amb:ACN9 ] ;
+ pg:hasRole [ pg:index 10; pg:role amb:ACN10 ] ;
+ pg:hasRole [ pg:index 11; pg:role amb:ACN11 ] ;
+ pg:hasRole [ pg:index 12; pg:role amb:ACN12 ] ;
+ pg:hasRole [ pg:index 13; pg:role amb:ACN13 ] ;
+ pg:hasRole [ pg:index 14; pg:role amb:ACN14 ] ;
+ pg:hasRole [ pg:index 15; pg:role amb:ACN15 ] .
+
+
+# Controls
+
+pg:ControlGroup a rdfs:Class ;
+ rdfs:subClassOf pg:Group ;
+ rdfs:comment """
+A group representing a set of associated controls.
+""" .
+
+pg:amplitude a pg:Role ; rdfs:label "Amplitude" .
+pg:attack a pg:Role ; rdfs:label "Attack" .
+pg:cutoffFrequency a pg:Role ; rdfs:label "Cutoff Frequency" .
+pg:decay a pg:Role ; rdfs:label "Decay" .
+pg:delay a pg:Role ; rdfs:label "Delay" .
+pg:frequency a pg:Role ; rdfs:label "Frequency" .
+pg:hold a pg:Role ; rdfs:label "Hold" .
+pg:pulseWidth a pg:Role ; rdfs:label "Pulse Width" .
+pg:ratio a pg:Role ; rdfs:label "Ratio" .
+pg:release a pg:Role ; rdfs:label "Release" .
+pg:resonance a pg:Role ; rdfs:label "Resonance" .
+pg:sustain a pg:Role ; rdfs:label "Sustain" .
+pg:threshold a pg:Role ; rdfs:label "Threshold" .
+pg:waveform a pg:Role ; rdfs:label "Waveform" .
+
+pg:EnvelopeControlGroup a rdfs:Class ;
+ rdfs:subClassOf pg:ControlGroup ;
+ rdfs:label "Controls for a DAHDSR envelope." ;
+ pg:mayHavePort pg:delay ;
+ pg:mayHavePort pg:attack ;
+ pg:mayHavePort pg:hold ;
+ pg:mayHavePort pg:decay ;
+ pg:mayHavePort pg:sustain ;
+ pg:mayHavePort pg:release .
+
+pg:OscillatorControlGroup a rdfs:Class ;
+ rdfs:subClassOf pg:ControlGroup ;
+ rdfs:label "Controls for an oscillator." ;
+ pg:mayHavePort pg:frequency ;
+ pg:mayHavePort pg:amplitude ;
+ pg:mayHavePort pg:waveform ;
+ pg:mayHavePort pg:pulseWidth .
+
+pg:FilterControlGroup a rdfs:Class ;
+ rdfs:subClassOf pg:ControlGroup ;
+ rdfs:label "Controls for a filter." ;
+ pg:mayHavePort pg:cutoffFrequency ;
+ pg:mayHavePort pg:resonance .
+
+pg:CompressorControlGroup a rdfs:Class ;
+ rdfs:subClassOf pg:ControlGroup ;
+ rdfs:label "Controls for a compressor." ;
+ pg:mayHavePort pg:threshold ;
+ pg:mayHavePort pg:ratio .
+
diff --git a/ext/presets.lv2/manifest.ttl b/ext/presets.lv2/manifest.ttl
new file mode 100644
index 0000000..9f82f88
--- /dev/null
+++ b/ext/presets.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/presets>
+ a lv2:Specification ;
+ rdfs:seeAlso <presets.ttl> .
+
diff --git a/ext/presets.lv2/presets.ttl b/ext/presets.lv2/presets.ttl
new file mode 100644
index 0000000..804e187
--- /dev/null
+++ b/ext/presets.lv2/presets.ttl
@@ -0,0 +1,88 @@
+# LV2 Presets Extension
+# PROVISIONAL
+# Copyright (C) 2009 David Robillard <d@drobilla.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix pset: <http://lv2plug.in/ns/ext/presets#> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+
+<http://lv2plug.in/ns/ext/presets> a lv2:Specification ;
+ doap:license <http://usefulinc.com/doap/licenses/mit> ;
+ doap:name "LV2 Presets" ;
+ doap:release [
+ doap:revision "2" ;
+ doap:created "2010-03-02"
+ ] ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "David Robillard" ;
+ foaf:homepage <http://drobilla.net/> ;
+ rdfs:seeAlso <http://drobilla.net/drobilla.rdf>
+ ] ;
+ rdfs:comment """
+Defines presets (e.g. named sets of control values) for LV2 plugins.
+""" .
+
+pset:Preset a rdfs:Class ;
+ rdfs:subClassOf lv2:Template ;
+ rdfs:label "LV2 Preset" ;
+ rdfs:comment """
+A Preset for an LV2 Plugin. A preset can be considered an "overlay" on a
+Plugin. Rather than attempting to define all valid predicates for a Preset
+(which is not possible since presets may need to specify values for things
+defined in other extensions), the presets extension simply provides this
+class which can be augmented with any data in the exact same fashion as the
+definition of a Plugin.
+
+A Preset SHOULD have at least one pset:appliesTo property.
+Each Port on a Preset MUST have at least a lv2:symbol property and a
+pset:value property.
+""" .
+
+pset:appliesTo a rdf:Property ;
+ rdfs:domain pset:Preset ;
+ rdfs:range lv2:Plugin ;
+ rdfs:label "Applies to" ;
+ rdfs:comment """
+Specifies the Plugin(s) a Preset may be applied to. When a Preset applies
+to a Plugin, that Preset SHOULD have ports for every control port on that
+plugin, each of which SHOULD have a pset:value property. If the Preset is
+missing ports, or refers to ports which do not exist on the Plugin, then
+the host SHOULD apply all the values in the preset that do match the Plugin.
+
+The Preset MAY have any other values that should be applied to the Plugin
+in some way. The host SHOULD simply ignore any values on a Preset it does
+not understand.
+""" .
+
+pset:value a rdf:Property ;
+ rdfs:domain lv2:Port ;
+ rdfs:label "Has value" ;
+ rdfs:comment """
+Specifies the value of a Port on some Preset. This property is used
+in a similar way to e.g. lv2:default.
+""" .
+
diff --git a/ext/resize-port.lv2/manifest.ttl b/ext/resize-port.lv2/manifest.ttl
new file mode 100644
index 0000000..0f2179b
--- /dev/null
+++ b/ext/resize-port.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/resize-port>
+ a lv2:Specification ;
+ rdfs:seeAlso <resize-port.ttl> .
+
diff --git a/ext/resize-port.lv2/resize-port.h b/ext/resize-port.lv2/resize-port.h
new file mode 100644
index 0000000..4ba533b
--- /dev/null
+++ b/ext/resize-port.lv2/resize-port.h
@@ -0,0 +1,46 @@
+/* LV2 Resize Port Extension
+ * Copyright (C) 2007-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 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 General Public License
+ * for more 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 LV2_RESIZE_PORT_H
+#define LV2_RESIZE_PORT_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#define LV2_RESIZE_PORT_URI "http://lv2plug.in/ns/ext/resize-port"
+
+typedef void* LV2_Resize_Port_Feature_Data;
+
+typedef struct {
+
+ LV2_Resize_Port_Feature_Data data;
+
+ /** Resize a port buffer to at least @a size bytes.
+ *
+ * This function MAY return false, in which case the port buffer was
+ * not resized and the port is still connected to the same location.
+ * Plugins MUST gracefully handle this situation.
+ */
+ bool (*resize_port)(LV2_Resize_Port_Feature_Data data,
+ uint32_t index,
+ size_t size);
+
+} LV2_Resize_Port_Feature;
+
+#endif /* LV2_RESIZE_PORT_H */
+
diff --git a/ext/resize-port.lv2/resize-port.ttl b/ext/resize-port.lv2/resize-port.ttl
new file mode 100644
index 0000000..d6bbb35
--- /dev/null
+++ b/ext/resize-port.lv2/resize-port.ttl
@@ -0,0 +1,85 @@
+# LV2 Contexts Extension
+#
+# Allows for an LV2 plugin to have several independent contexts, each with its
+# own run callback and associated ports.
+#
+# Copyright (C) 2007 David Robillard
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix rsz: <http://lv2plug.in/ns/ext/resize-port#> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+
+<http://lv2plug.in/ns/ext/resize-port>
+ a lv2:Specification ;
+ a lv2:Feature ;
+ doap:name "LV2 Resize Port Extension" ;
+ rdfs:comment """
+An extension that allows LV2 plugins to request a resize of an output port.
+
+Any host which supports this extension must pass an LV2_Feature to
+the plugin's instantiate method with URI http://lv2plug.in/ns/ext/resize-port
+and a pointer to a
+<pre>
+struct {
+ void* host_handle;
+ void (*resize_port)(void* host_handle, uint32_t index);
+}
+</pre>
+where the plugin may call resize_port with the given host_handle from any
+context to demand the resize of an output port buffer. The plugin MUST call
+this function from the context of the given port.
+
+This function MAY return NULL at any time, plugins MUST gracefully handle
+this situation.
+""" .
+
+rsz:asLargeAs a rdf:Property ;
+ rdfs:domain lv2:Port ;
+ rdfs:range lv2:Symbol ;
+ rdfs:label "as large as" ;
+ rdfs:comment """
+Indicates that a port requires at least as much buffer space as the port
+with the given symbol on the same plugin instance. This may be used for
+any ports, but is generally most useful to indicate an output port must
+be at least as large as some input port (because it will copy from it).
+If a port is asLargeAs several ports, it is asLargeAs the largest such port
+(not the sum of those ports' sizes).
+
+The host guarantees that whenever an ObjectPort's run method is called,
+any output O that is obj:asLargeAs an input I is connected to a buffer large
+enough to copy I, or NULL if the port is lv2:connectionOptional.
+""" .
+
+rsz:minimumSize a rdf:Property ;
+ rdfs:domain lv2:Port ;
+ rdfs:range lv2:Symbol ;
+ rdfs:label "minimum size" ;
+ rdfs:comment """
+Indicates that a port requires a buffer at least this large, in bytes.
+Any host that supports the resize-port feature MUST connect any port with a
+minimumSize specified to a buffer at least as large as the value given for
+this property. Any host, especially those that do NOT support dynamic port
+resizing, SHOULD do so or reduced functionality may result.
+""" .
diff --git a/ext/string-port.lv2/manifest.ttl b/ext/string-port.lv2/manifest.ttl
new file mode 100644
index 0000000..c7ba4e1
--- /dev/null
+++ b/ext/string-port.lv2/manifest.ttl
@@ -0,0 +1,6 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/string-port>
+ a lv2:Specification ;
+ rdfs:seeAlso <string-port.ttl> .
diff --git a/ext/string-port.lv2/string-port.h b/ext/string-port.lv2/string-port.h
new file mode 100644
index 0000000..e7fc8c7
--- /dev/null
+++ b/ext/string-port.lv2/string-port.h
@@ -0,0 +1,58 @@
+/* lv2_string_port.h - C header file for LV2 string port extension.
+ * Draft Revision 3
+ * Copyright (C) 2008 Krzysztof Foltman <wdev@foltman.com>
+ *
+ * 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
+ */
+
+/** @file
+ * C header for the LV2 String Port extension
+ * <http://lv2plug.in/ns/ext/string-port#StringTransfer>.
+ */
+
+#ifndef LV2_STRING_PORT_H
+#define LV2_STRING_PORT_H
+
+#include <stdint.h>
+
+/** URI for the string port transfer mechanism feature */
+#define LV2_STRING_PORT_URI "http://lv2plug.in/ns/ext/string-port#StringTransfer"
+
+/** Flag: port data has been updated; for input ports, this flag is set by
+the host. For output ports, this flag is set by the plugin. */
+#define LV2_STRING_DATA_CHANGED_FLAG 1
+
+/** structure for string port data */
+typedef struct
+{
+ /** Buffer for UTF-8 encoded zero-terminated string value; host-allocated */
+ char *data;
+
+ /** Length in bytes (not characters), not including zero byte */
+ size_t len;
+
+ /** Output ports: storage space in bytes; must be >= RDF-specified requirements */
+ size_t storage;
+
+ /** Flags defined above */
+ uint32_t flags;
+
+ /** Undefined (pad to 8 bytes) */
+ uint32_t pad;
+
+} LV2_String_Data;
+
+#endif
+
diff --git a/ext/string-port.lv2/string-port.ttl b/ext/string-port.lv2/string-port.ttl
new file mode 100644
index 0000000..e6adfc2
--- /dev/null
+++ b/ext/string-port.lv2/string-port.ttl
@@ -0,0 +1,105 @@
+# LV2 String Port Extension.
+# Draft Revision 3
+# Copyright (C) 2008 Krzysztof Foltman
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix sp: <http://lv2plug.in/ns/ext/string-port#> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+
+<http://lv2plug.in/ns/ext/string-port> a lv2:Specification ;
+ doap:license <http://usefulinc.com/doap/licenses/mit> ;
+ doap:name "LV2 String Ports" ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "Krzysztof Foltman" ;
+ ] ;
+ rdfs:comment """
+Defines ports which contain string data.
+
+<h4>UI issues</h4>
+When using port_event / write_port (and possible other communication
+mechanisms), the format parameter should contain the numeric value of URI
+LV2_STRING_PORT_URI (mapped with http://lv2plug.in/ns/extensions/ui specified
+as map URI).
+
+It's probably possible to use ports belonging to message context
+&lt;http://lv2plug.in/ns/ext/contexts#MessageContext&gt; for transfer. However,
+contexts mechanism does not offer any way to notify the message recipient
+about which ports have been changed. To remedy that, this extension defines
+a flag LV2_STRING_DATA_CHANGED_FLAG that carries that information inside a
+port value structure.
+
+<h4>Storage</h4>
+The value of string port are assumed to be "persistent": if a host saves
+and restores a state of a plugin (e.g. control port values), the values
+of input string ports should also be assumed to belong to that state. This
+also applies to message context: if a session is being restored, the host
+MUST resend the last value that was sent to the port before session has been
+saved. In other words, string port values "stick" to message ports.
+""" .
+
+sp:StringTransfer a lv2:Feature ;
+ rdfs:label "String data transfer via LV2_String_Data" .
+
+sp:StringPort a lv2:Port ;
+ rdfs:label "String port" ;
+ rdfs:comment """
+Indicates that the port data points to a LV2_String_Data structure
+as defined in accompanying header file.
+
+<h4>Input Port Semantics</h4>
+If the port does not have a context specified (it runs in the default,
+realtime audio processing context), the values in the structure and the actual
+string data MUST remain unchanged for the time a run() function of a plugin
+is executed. However, if the port belongs to a different context, the same
+data MUST remain unchanged only for the time a run() or message_process()
+function of a given context is executed.
+
+<h4>Output Port Semantics</h4>
+The plugin may only change the string or length in a run() function (if
+the port belongs to default context) or in context-defined counterparts
+(if the port belongs to another context). Because of that, using default
+context output string ports is contraindicated for longer strings.
+""" .
+
+sp:default a rdf:Property ;
+ rdfs:label "Default value" ;
+ rdfs:domain sp:StringPort ;
+ rdfs:range xsd:string ;
+ rdfs:comment """
+Gives a default value for a string port.
+""" .
+
+sp:requiredSpace a rdf:Property ;
+ rdfs:label "Required storage space in bytes" ;
+ rdfs:domain sp:StringPort ;
+ rdfs:range xsd:nonNegativeInteger ;
+ rdfs:comment """
+Specifies required buffer space for output string ports and those of
+input string ports that are meant to be GUI-controlled. The host MUST
+allocate a buffer of at least required size to accommodate for all values
+that can be produced by the plugin.
+""" .
+
diff --git a/ext/uri-map.lv2/manifest.ttl b/ext/uri-map.lv2/manifest.ttl
new file mode 100644
index 0000000..62d0bb6
--- /dev/null
+++ b/ext/uri-map.lv2/manifest.ttl
@@ -0,0 +1,6 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/uri-map>
+ a lv2:Specification ;
+ rdfs:seeAlso <uri-map.ttl> .
diff --git a/ext/uri-map.lv2/uri-map.h b/ext/uri-map.lv2/uri-map.h
new file mode 100644
index 0000000..d0d04e4
--- /dev/null
+++ b/ext/uri-map.lv2/uri-map.h
@@ -0,0 +1,87 @@
+/* lv2_uri_map.h - C header file for the LV2 URI Map 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
+ */
+
+/** @file
+ * C header for the LV2 URI Map extension <http://lv2plug.in/ns/ext/uri-map>.
+ *
+ * This extension defines a simple mechanism for plugins to map URIs to
+ * integers, usually for performance reasons (e.g. processing events
+ * typed by URIs in real time). The expected use case is for plugins to
+ * map URIs to integers for things they 'understand' at instantiation time,
+ * and store those values for use in the audio thread without doing any string
+ * comparison. This allows the extensibility of RDF with the performance of
+ * integers (or centrally defined enumerations).
+ */
+
+#ifndef LV2_URI_MAP_H
+#define LV2_URI_MAP_H
+
+#define LV2_URI_MAP_URI "http://lv2plug.in/ns/ext/uri-map"
+
+#include <stdint.h>
+
+
+/** Opaque pointer to host data. */
+typedef void* LV2_URI_Map_Callback_Data;
+
+
+/** The data field of the LV2_Feature for this extension.
+ *
+ * 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/uri-map"
+ * and data pointed to an instance of this struct.
+ */
+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_URI_Map_Callback_Data callback_data;
+
+ /** Get the numeric ID of a URI from the host.
+ *
+ * @param callback_data Must be the callback_data member of this struct.
+ * @param map The 'context' of this URI. Certain extensions may define a
+ * URI that must be passed here with certain restrictions on the
+ * return value (e.g. limited range). This value may be NULL if
+ * the plugin needs an ID for a URI in general.
+ * @param uri The URI to be mapped to an integer ID.
+ *
+ * This function is referentially transparent - any number of calls with
+ * the same arguments is guaranteed to return the same value over the life
+ * of a plugin instance (though the same URI may return different values
+ * with a different map parameter). However, this function is not
+ * necessarily very fast: plugins should cache any IDs they might need in
+ * performance critical situations.
+ * The return value 0 is reserved and means an ID for that URI could not
+ * be created for whatever reason. Extensions may define more precisely
+ * what this means, but in general plugins should gracefully handle 0
+ * and consider whatever they wanted the URI for "unsupported".
+ */
+ uint32_t (*uri_to_id)(LV2_URI_Map_Callback_Data callback_data,
+ const char* map,
+ const char* uri);
+
+} LV2_URI_Map_Feature;
+
+
+#endif /* LV2_URI_MAP_H */
+
diff --git a/ext/uri-map.lv2/uri-map.ttl b/ext/uri-map.lv2/uri-map.ttl
new file mode 100644
index 0000000..0c557d0
--- /dev/null
+++ b/ext/uri-map.lv2/uri-map.ttl
@@ -0,0 +1,54 @@
+# LV2 Data Access Extension
+# Copyright (C) 2008 David Robillard <d@drobilla.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix umap: <http://lv2plug.in/ns/ext/uri-map#> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix lv2ev: <http://lv2plug.in/ns/ext/event#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+
+<http://lv2plug.in/ns/ext/uri-map> a lv2:Specification ;
+ doap:license <http://usefulinc.com/doap/licenses/mit> ;
+ doap:name "LV2 URI Map" ;
+ doap:release [
+ doap:revision "1" ;
+ doap:created "2008-04-16"
+ ] ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "David Robillard" ;
+ foaf:homepage <http://drobilla.net/> ;
+ rdfs:seeAlso <http://drobilla.net/drobilla.xrdf>
+ ] , [
+ a foaf:Person ;
+ foaf:name "Lars Luthman" ;
+ ] ;
+ rdfs:comment """
+This extension defines a simple mechanism for plugins to map URIs to integers,
+usually for performance reasons (e.g. processing events typed by URIs in
+real time). The expected use case is for plugins to map URIs to integers for
+things they 'understand' at instantiation time, and store those values for
+use in the audio thread without doing any string comparison. This allows
+the extensibility of RDF with the performance of integers (or centrally
+defined enumerations).
+""" .
diff --git a/ext/variables.lv2/manifest.ttl b/ext/variables.lv2/manifest.ttl
new file mode 100644
index 0000000..a8e3306
--- /dev/null
+++ b/ext/variables.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/variables>
+ a lv2:Specification ;
+ rdfs:seeAlso <variables.ttl> .
+
diff --git a/ext/variables.lv2/variables-private.h b/ext/variables.lv2/variables-private.h
new file mode 100644
index 0000000..451aeb2
--- /dev/null
+++ b/ext/variables.lv2/variables-private.h
@@ -0,0 +1,48 @@
+/* LV2 Plugin Variables Extension (Private Implementation)
+ * Copyright (C) 2007-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 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 General Public License
+ * for more 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 "lv2_variables.h"
+
+/** An LV2 Plugin Variable (Private) */
+struct _LV2Var_Variable {
+ char* key; /**< Lookup key of variable, full URI */
+ char* type; /**< Type of value, full URI, may be NULL */
+ char* value; /**< Variable value (string literal or URI) */
+};
+
+
+static const char*
+lv2var_variable_key(const LV2Var_Variable var)
+{
+ return var->key;
+}
+
+
+static const char*
+lv2var_variable_type(const LV2Var_Variable var)
+{
+ return var->type;
+}
+
+
+static const char*
+lv2var_variable_value(const LV2Var_Variable var)
+{
+ return var->value;
+}
+
diff --git a/ext/variables.lv2/variables.h b/ext/variables.lv2/variables.h
new file mode 100644
index 0000000..5c51be7
--- /dev/null
+++ b/ext/variables.lv2/variables.h
@@ -0,0 +1,144 @@
+/* LV2 Plugin Variables Extension
+ * Copyright (C) 2007-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 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 General Public License
+ * for more 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 LV2_VARIABLES_H
+#define LV2_VARIABLES_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** @file
+ * This is an LV2 extension allowing plugin instances to have a set of
+ * dynamic named/typed variables (ie key/value metadata).
+ *
+ * Plugin variable values are always in string form (if numeric
+ * variable values are requires in realtime run callbacks, it is assumed
+ * the plugin will cache the converted value).
+ *
+ * Keys are strings, either free-form locally unique strings, or URIs.
+ * Types are URIs (corresponding to some type defined somewhere, e.g. in an
+ * XML namespace or RDF ontology).
+ *
+ * The goal is to provide a powerful key/value system for plugins, which is
+ * useful for setting run-time values (analogous to DSSI's "configure" calls)
+ * which is typed and ideal for serializing to RDF (which means variable
+ * values can be stored in the same file as the plugin's definition) or
+ * network transmission/control.
+ */
+
+
+/** An LV2 Plugin Variable */
+typedef struct _LV2Var_Variable* LV2Var_Variable;
+
+static const char* lv2var_variable_key(const LV2Var_Variable var);
+static const char* lv2var_variable_type(const LV2Var_Variable var);
+static const char* lv2var_variable_value(const LV2Var_Variable var);
+
+
+
+/** Plugin extension data for plugin variables.
+ *
+ * The extension_data function on a plugin (which supports this extension)
+ * will return a pointer to a struct of this type, when called with the URI
+ * http://drobilla.net/ns/lv2/variables
+ */
+typedef struct _LV2Var_Descriptor {
+
+ /** Get the value of a plugin variable (O(log(n), non-blocking).
+ *
+ * @param key_uri Key of variable to look up
+ * @param type_uri Output, set to (shared) type of value (full URI, may be NULL)
+ * @param value Output, set to (shared) value of variable
+ *
+ * @return 0 if variable was found and type, value have been set accordingly,
+ * otherwise non-zero.
+ */
+ int32_t (*get_value)(const char* key_uri,
+ const char** type_uri,
+ const char** value);
+
+
+ /** Set a plugin variable to a typed literal value (O(log(n), allocates memory).
+ *
+ * Note that this function is NOT realtime safe.
+ *
+ * String parameters are copied. The key is the sole unique identifier
+ * for variables; if a variable exists with the given key, it will be
+ * overwritten with the new type and value.
+ *
+ * To set a variable's value to a URI, use rdfs:Resource
+ * (http://www.w3.org/2000/01/rdf-schema#Resource) for the value type.
+ *
+ * @param key_uri Key of variable to set (MUST be a full URI)
+ * @param type_uri Type of value (MUST be a full URI, may be NULL)
+ * @param value Value of variable to set
+ */
+ void (*set_value)(const char* key_uri,
+ const char* type_uri,
+ const char* value);
+
+
+ /** Unset (erase) a variable (O(log(n), deallocates memory).
+ *
+ * Note that this function is NOT realtime safe.
+ *
+ * @param key Key of variable to erase
+ */
+ void (*unset)(const char* key_uri);
+
+
+ /** Clear (erase) all set variables (O(1), deallocates memory).
+ *
+ * Note that this function is NOT realtime safe.
+ */
+ void (*clear)();
+
+
+ /** Get all variables of a plugin (O(log(n), allocates memory).
+ *
+ * @param variables Output, set to a shared array of all set variables
+ *
+ * @return The number of variables found
+ */
+ uint32_t (*get_all_variables)(const LV2Var_Variable** variables);
+
+
+ /** Get the value of a plugin variable (O(log(n), non-blocking).
+ *
+ * @param key_uri Key of variable to look up
+ * @param variable Output, set to point at (shared) variable
+ *
+ * @return 0 if variable was found and variable has been set accordingly,
+ * otherwise non-zero.
+ */
+ int32_t (*get_variable)(const char* key_uri,
+ const LV2Var_Variable** variable);
+
+} LV2Var_Descriptor;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LV2_VARIABLES_H */
+
diff --git a/ext/variables.lv2/variables.ttl b/ext/variables.lv2/variables.ttl
new file mode 100644
index 0000000..b7d1b8c
--- /dev/null
+++ b/ext/variables.lv2/variables.ttl
@@ -0,0 +1,118 @@
+# LV2 Variables Extension
+# Copyright (C) 2008 David Robillard
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix var: <http://lv2plug.in/ns/ext/instance-var#> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+
+<http://lv2plug.in/ns/ext/instance-var> a lv2:Specification ;
+ doap:license <http://usefulinc.com/doap/licenses/mit> ;
+ doap:name "LV2 Instance Variables" ;
+ doap:created "2008-08-18" ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "David Robillard" ;
+ foaf:homepage <http://drobilla.net/> ;
+ rdfs:seeAlso <http://drobilla.net/drobilla.rdf>
+ ] ;
+ rdfs:comment """
+An extension for setting named/typed variables on an instance of an
+LV2 Plugin (or anything else). A "variable" is really just a (reified)
+RDF statement with an implicit subject (e.g. the plugin instance).
+
+Variables serve as a portable, network transparent, and serialisable
+mechanism for clients (e.g. user interfaces, programs) to control any
+parameter of a running plugin instance. Because variables are 'keyed'
+by URI (the predicate), future extensions can define variables with
+specific meanings or restricted/extended types.
+The value (rdf:value) of a variable may be anything, but hosts or plugins
+aren't guaranteed to support anything other than simple typed literals.
+Serialisation and code access to complex variables is considered outside
+the scope of this extension.
+
+Hosts and plugins SHOULD use the following types for appropriate values:
+
+<table>
+<tr><th>RDF Type</th><th>Data Type</th></tr>
+<tr><td>xsd:string</td><td>string</td></tr>
+<tr><td>xsd:decimal</td><td>floating point number</td></tr>
+<tr><td>xsd:integer</td><td>integer number</td></tr>
+<tr><td>xsd:boolean</td><td>boolean value</td></tr>
+</table>
+
+This extension does not currently define a code mechanism for access
+to variables. A future revision, or a different extension, may.
+
+An example of a plugin with several variables:
+<pre>
+&lt;http://example.org/plugin&gt; a lv2:Plugin ;
+ lv2var:variable [
+ rdf:predicate &lt;http://example.org/greetingology#Greeting&gt; ;
+ rdf:value "Hello, cruel world."
+ ] , [
+ rdf:predicate &lt;http://example.org/matheybits#Coeff&gt; ;
+ rdf:value 1.23456
+ ] , [
+ rdf:predicate &lt;http://example.org/databits#BigValue&gt; ;
+ rdf:value [
+ a somext:Something ;
+ someext:foo "Foo?" ;
+ someext:bar "Bar." ;
+ someext:baz 1234.0
+ ]
+ ] .
+</pre>
+""" .
+
+
+var:Variable a rdfs:Class ;
+ rdfs:label "LV2 Variable" ;
+ rdfs:comment "A typed instance variable." ;
+
+ rdfs:subClassOf [
+ a owl:Restriction ;
+ rdfs:comment "Must have exactly one rdf:predicate which is a resource" ;
+ owl:onProperty rdf:predicate ;
+ owl:cardinality 1 ;
+ owl:allValuesFrom rdfs:Resource
+ ], [
+ a owl:Restriction ;
+ rdfs:comment "Must have exactly one rdf:value (of any type)" ;
+ owl:onProperty rdf:value ;
+ owl:cardinality 1
+ ] .
+
+
+var:variable a owl:ObjectProperty ;
+ rdfs:label "Has a Variable" ;
+ rdfs:range var:Variable ;
+ rdfs:comment """
+Relates an LV2 Variable to some Resource, usually a plugin instance.
+The domain of this property is not restricted, it may be used for anything.
+The range is implicitly an lv2var:Variable, the 'a lv2var:Variable' triple
+is not mandatory.
+""" .
+