From cef9811dac46a9d54dab0f0d82ce5c3ae032fc7c Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 4 Oct 2010 18:21:08 +0000 Subject: Initial import of lv2plug.in universe. --- ext/atom-port.lv2/atom-port.ttl | 127 +++++++ ext/atom-port.lv2/manifest.ttl | 7 + ext/atom.lv2/atom.h | 232 ++++++++++++ ext/atom.lv2/atom.ttl | 272 ++++++++++++++ ext/atom.lv2/manifest.ttl | 7 + ext/command.lv2/command.ttl | 73 ++++ ext/command.lv2/manifest.ttl | 7 + ext/contexts.lv2/contexts.h | 72 ++++ ext/contexts.lv2/contexts.ttl | 202 +++++++++++ ext/contexts.lv2/manifest.ttl | 7 + ext/contexts.lv2/test.c | 65 ++++ ext/data-access.lv2/data-access.h | 57 +++ ext/data-access.lv2/data-access.ttl | 46 +++ ext/data-access.lv2/manifest.ttl | 7 + ext/dyn-manifest.lv2/Makefile | 20 ++ ext/dyn-manifest.lv2/dyn-manifest.h | 245 +++++++++++++ ext/dyn-manifest.lv2/dyn-manifest.ttl | 109 ++++++ ext/dyn-manifest.lv2/manifest.ttl | 7 + ext/event.lv2/event-helpers.h | 243 +++++++++++++ ext/event.lv2/event.h | 259 ++++++++++++++ ext/event.lv2/event.ttl | 192 ++++++++++ ext/event.lv2/lv2_event.pc.in | 10 + ext/event.lv2/manifest.ttl | 7 + ext/files.lv2/files.h | 61 ++++ ext/files.lv2/files.ttl | 94 +++++ ext/files.lv2/manifest.ttl | 7 + ext/host-info.lv2/host-info.ttl | 116 ++++++ ext/host-info.lv2/manifest.ttl | 7 + ext/instance-access.lv2/instance-access.h | 39 ++ ext/instance-access.lv2/instance-access.ttl | 46 +++ ext/instance-access.lv2/manifest.ttl | 7 + ext/midi.lv2/manifest.ttl | 7 + ext/midi.lv2/midi.ttl | 87 +++++ ext/osc.lv2/lv2_osc.c | 314 +++++++++++++++++ ext/osc.lv2/lv2_osc.pc.in | 10 + ext/osc.lv2/lv2_osc_print.c | 66 ++++ ext/osc.lv2/lv2_osc_test.c | 55 +++ ext/osc.lv2/manifest.ttl | 7 + ext/osc.lv2/osc-print.h | 42 +++ ext/osc.lv2/osc.h | 123 +++++++ ext/osc.lv2/osc.ttl | 56 +++ ext/parameter.lv2/manifest.ttl | 7 + ext/parameter.lv2/parameter.ttl | 110 ++++++ ext/persist.lv2/manifest.ttl | 7 + ext/persist.lv2/persist.h | 177 ++++++++++ ext/persist.lv2/persist.ttl | 116 ++++++ ext/polymorphic-port.lv2/manifest.ttl | 7 + ext/polymorphic-port.lv2/polymorphic-port.h | 63 ++++ ext/polymorphic-port.lv2/polymorphic-port.ttl | 71 ++++ ext/port-groups.lv2/manifest.ttl | 7 + ext/port-groups.lv2/port-groups.ttl | 489 ++++++++++++++++++++++++++ ext/presets.lv2/manifest.ttl | 7 + ext/presets.lv2/presets.ttl | 88 +++++ ext/resize-port.lv2/manifest.ttl | 7 + ext/resize-port.lv2/resize-port.h | 46 +++ ext/resize-port.lv2/resize-port.ttl | 85 +++++ ext/string-port.lv2/manifest.ttl | 6 + ext/string-port.lv2/string-port.h | 58 +++ ext/string-port.lv2/string-port.ttl | 105 ++++++ ext/uri-map.lv2/manifest.ttl | 6 + ext/uri-map.lv2/uri-map.h | 87 +++++ ext/uri-map.lv2/uri-map.ttl | 54 +++ ext/variables.lv2/manifest.ttl | 7 + ext/variables.lv2/variables-private.h | 48 +++ ext/variables.lv2/variables.h | 144 ++++++++ ext/variables.lv2/variables.ttl | 118 +++++++ 66 files changed, 5337 insertions(+) create mode 100644 ext/atom-port.lv2/atom-port.ttl create mode 100644 ext/atom-port.lv2/manifest.ttl create mode 100644 ext/atom.lv2/atom.h create mode 100644 ext/atom.lv2/atom.ttl create mode 100644 ext/atom.lv2/manifest.ttl create mode 100644 ext/command.lv2/command.ttl create mode 100644 ext/command.lv2/manifest.ttl create mode 100644 ext/contexts.lv2/contexts.h create mode 100644 ext/contexts.lv2/contexts.ttl create mode 100644 ext/contexts.lv2/manifest.ttl create mode 100644 ext/contexts.lv2/test.c create mode 100644 ext/data-access.lv2/data-access.h create mode 100644 ext/data-access.lv2/data-access.ttl create mode 100644 ext/data-access.lv2/manifest.ttl create mode 100644 ext/dyn-manifest.lv2/Makefile create mode 100644 ext/dyn-manifest.lv2/dyn-manifest.h create mode 100644 ext/dyn-manifest.lv2/dyn-manifest.ttl create mode 100644 ext/dyn-manifest.lv2/manifest.ttl create mode 100644 ext/event.lv2/event-helpers.h create mode 100644 ext/event.lv2/event.h create mode 100644 ext/event.lv2/event.ttl create mode 100644 ext/event.lv2/lv2_event.pc.in create mode 100644 ext/event.lv2/manifest.ttl create mode 100644 ext/files.lv2/files.h create mode 100644 ext/files.lv2/files.ttl create mode 100644 ext/files.lv2/manifest.ttl create mode 100644 ext/host-info.lv2/host-info.ttl create mode 100644 ext/host-info.lv2/manifest.ttl create mode 100644 ext/instance-access.lv2/instance-access.h create mode 100644 ext/instance-access.lv2/instance-access.ttl create mode 100644 ext/instance-access.lv2/manifest.ttl create mode 100644 ext/midi.lv2/manifest.ttl create mode 100644 ext/midi.lv2/midi.ttl create mode 100644 ext/osc.lv2/lv2_osc.c create mode 100644 ext/osc.lv2/lv2_osc.pc.in create mode 100644 ext/osc.lv2/lv2_osc_print.c create mode 100644 ext/osc.lv2/lv2_osc_test.c create mode 100644 ext/osc.lv2/manifest.ttl create mode 100644 ext/osc.lv2/osc-print.h create mode 100644 ext/osc.lv2/osc.h create mode 100644 ext/osc.lv2/osc.ttl create mode 100644 ext/parameter.lv2/manifest.ttl create mode 100644 ext/parameter.lv2/parameter.ttl create mode 100644 ext/persist.lv2/manifest.ttl create mode 100644 ext/persist.lv2/persist.h create mode 100644 ext/persist.lv2/persist.ttl create mode 100644 ext/polymorphic-port.lv2/manifest.ttl create mode 100644 ext/polymorphic-port.lv2/polymorphic-port.h create mode 100644 ext/polymorphic-port.lv2/polymorphic-port.ttl create mode 100644 ext/port-groups.lv2/manifest.ttl create mode 100644 ext/port-groups.lv2/port-groups.ttl create mode 100644 ext/presets.lv2/manifest.ttl create mode 100644 ext/presets.lv2/presets.ttl create mode 100644 ext/resize-port.lv2/manifest.ttl create mode 100644 ext/resize-port.lv2/resize-port.h create mode 100644 ext/resize-port.lv2/resize-port.ttl create mode 100644 ext/string-port.lv2/manifest.ttl create mode 100644 ext/string-port.lv2/string-port.h create mode 100644 ext/string-port.lv2/string-port.ttl create mode 100644 ext/uri-map.lv2/manifest.ttl create mode 100644 ext/uri-map.lv2/uri-map.h create mode 100644 ext/uri-map.lv2/uri-map.ttl create mode 100644 ext/variables.lv2/manifest.ttl create mode 100644 ext/variables.lv2/variables-private.h create mode 100644 ext/variables.lv2/variables.h create mode 100644 ext/variables.lv2/variables.ttl (limited to 'ext') 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 +# +# 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: . +@prefix atom: . +@prefix doap: . +@prefix foaf: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . + + + a lv2:Specification ; + doap:name "LV2 Atom Port" ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] ; + rdfs:comment """ +This extension describes port types that hold polymorphic values +(atom:Atom). 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 atom:Atom (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 +#
input aport:respondsWith output
then after running the plugin with +#a message m in input the host SHOULD interpret the aport: +#in output as the response to m. +#""" . + + +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". +
    +
  • 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.
  • +
  • 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.
  • +
  • If an aport:ValuePort contains a reference then the blob it refers to is +constant; plugin MUST NOT modify the blob in any way.
  • +
+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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . + 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 + * + * 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 . + * 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 +#include + +#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 LV2 events extension. + * 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 + * 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 +# +# 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: . +@prefix doap: . +@prefix foaf: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . + + + a lv2:Specification ; + doap:name "LV2 Atom" ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] ; + 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 memcpy). 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 LV2 +Event 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 LV2 URI Map 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 <http://lv2plug.in/ns/ext/uri-map>. 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 +
+uint16_t elem_count; // The number of elements in the vector
+uint16_t elem_type;  // The type of each element
+
+followed by elem_count bodies of atoms of type +elem_type, each with equivalent size. For variably sized +content types, this size can be calculated using the total byte size of the +vector, e.g. +
+uint16_t elem_size = (vector.size - (2 * sizeof(uint16_t))) / vector.count);
+
+Note that it is possible to construct a valid Atom for each element of the +vector, even by an implementation which does not understand type. + +For example, an atom:Vector containing 42 elements of type atom:Int32 looks +like this in memory: +
+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] = ...
+
+""" . + + +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: +
+uint32_t subject;
+uint32_t predicate;
+LV2_Atom object;
+
+""" . + + +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.: +
+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;
+...
+
+""" . + + +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: +<> ex:hasThing [ a ex:Thing ] + +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: +
+uint32_t predicate1;
+LV2_Atom object1;
+uint32_t predicate2;
+LV2_Atom object2;
+...
+
+""" . + + +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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . + 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 +# +# 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: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . +@prefix doap: . +@prefix foaf: . + + + a lv2:Specification ; + doap:name "LV2 Command" ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] ; + 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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . + 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 + * + * 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 + * . + */ + +#ifndef LV2_CONTEXTS_H +#define LV2_CONTEXTS_H + +#include + +#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: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . +@prefix doap: . +@prefix foaf: . + + + 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 +
+struct {
+	void* host_handle;
+	void (*request_run)(void* host_handle, const char* context_uri);
+}
+
+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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . + 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 +#include +#include +#include +#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 + * + * 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 + * . + * + * 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 +# +# 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: . +@prefix lv2: . +@prefix lv2ev: . +@prefix rdf: . +@prefix rdfs: . +@prefix doap: . +@prefix foaf: . + + a lv2:Specification ; + doap:license ; + 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 ; + rdfs:seeAlso + ] ; + 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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . + 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 + * 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 +#include "lv2.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* ************************************************************************* */ + + +/** @file + * C header for the LV2 Dynamic Manifest extension + * . + * 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: + * + * 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: + * + * a lv2:Plugin; + * lv2:binary ; + * 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 +# 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: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix owl: . +@prefix xsd: . +@prefix doap: . +@prefix foaf: . + + + a doap:Project ; + a lv2:Specification ; + doap:license ; + doap:name "LV2 Dynamic Manifest" ; + doap:homepage ; + 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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . + 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 + * + * 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 +#include +#include +#include +#include +#include "event.lv2/event.h" + +/** @file + * Helper functions for the LV2 Event extension + * . + * + * 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 + * Copyright (C) 2008-2009 David Robillard + * + * 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 + +/** @file + * C header for the LV2 Event extension . + * + * 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 +# +# 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: . +@prefix lv2: . +@prefix lv2ev: . +@prefix rdf: . +@prefix rdfs: . +@prefix doap: . +@prefix foaf: . + + a lv2:Specification ; + doap:license ; + 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 ; + rdfs:seeAlso + ] , [ + 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: +
+<http://example.org/some-plugin>
+	lv2:port [
+		a ev:EventPort, lv2:InputPort ;
+		lv2:index 0 ;
+		ev:supportsEvent <http://lv2plug.in/ns/ext/midi#MidiEvent> ;
+		lv2:symbol "midi_input" ;
+		lv2:name "MIDI input" ;
+	] .
+
+""" . + +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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . + 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 + * + * 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 . + */ + +#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 + * . + */ +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 +# Copyright (C) 2010 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 files: . +@prefix atom: . +@prefix doap: . +@prefix foaf: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . + + + a lv2:Specification ; + doap:name "LV2 Files" ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] ; + 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 LV2 Persist 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 type 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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . + 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 +# +# 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: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix owl: . +@prefix xsd: . +@prefix doap: . +@prefix foaf: . +@prefix amb: . + + a lv2:Specification ; + doap:license ; + doap:name "LV2 Host Info" ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] ; + 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: +
+@prefix hi: <http://lv2plug.in/ns/ext/host-info#> .
+
+<http://example.org/some-host> a hi:Host ;
+	doap:name "Foo Rack" ;
+	hi:supportsExtension [
+		hi:extension <http://example.org/some-extension> ;
+		hi:sinceVersion "1.2.0"
+	] .
+
+"""^^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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . + 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 + * + * 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 + * . + * + * 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 +# +# 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: . +@prefix lv2: . +@prefix lv2ev: . +@prefix rdf: . +@prefix rdfs: . +@prefix doap: . +@prefix foaf: . + + a lv2:Specification ; + doap:license ; + 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 ; + rdfs:seeAlso + ] ; + 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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . + 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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . + 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 +# +# Based on lv2-midiport.h: +# Copyright (C) 2006 Lars Luthman +# +# 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: . +@prefix lv2: . +@prefix lv2ev: . +@prefix rdfs: . +@prefix doap: . +@prefix foaf: . + + a lv2:Specification ; + doap:license ; + 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 ; + rdfs:seeAlso + ] , [ + 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: +
    +
  • Running status is not allowed. Every event must have its own status + byte.
  • + +
  • 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.
  • + +
  • "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.
  • + +
  • 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.
  • + +
  • 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.
  • +
+"""^^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 . + */ + +#include +#include +#include +#include +#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 . + */ + +#include +#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 +#include +#include +#include +#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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . + 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 . + */ + +/** @file + * Helper functions for printing LV2 OSC messages as defined by the + * LV2 OSC extension . + */ + +#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 + * + * 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 + +#ifdef __cplusplus +extern "C" { +#endif + +/** @file + * C header for the LV2 OSC extension . + * 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 +# +# 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: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . +@prefix doap: . +@prefix foaf: . + + a lv2:Specification ; + doap:license ; + 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 ; + rdfs:seeAlso + ] . + + +####################### +## 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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . + 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 +# +# 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: . +@prefix doap: . +@prefix foaf: . +@prefix lv2: . +@prefix param: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . + + + a lv2:Specification ; + doap:name "LV2 Parameter" ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] ; + 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: +
    +
  • A parameter may have any data type
  • +
  • Parameters can be dynamically added or removed
  • +
  • Parameter values can be manipulated by the plugin
  • +
+ +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 <http://lv2plug.in/ns/ext/atom#>. 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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . + 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 + * + * 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 . + */ + +#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 + * . Hosts are not required to support + * references, a plugin MUST NOT expect a host to persist references unless + * the host supports the feature . + * + * 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 +# Copyright (C) 2010 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 persist: . +@prefix doap: . +@prefix foaf: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . + + + a lv2:Specification ; + doap:name "LV2 Persist" ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] ; + 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 all +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 will +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 +LV2 Files 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.: +
+@prefix eg: <http://example.org/> .
+
+<plugininstance> persist:instanceState [
+    eg:somekey "some value" ;
+    eg:someotherkey "some other value" ;
+    eg:favouritenumber 2 .
+]
+
+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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . + 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 + * + * 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 + * . + * + * 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 +# +# 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: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix doap: . +@prefix foaf: . + + a lv2:Specification ; + doap:license ; + 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 ; + rdfs:seeAlso + ] . + + +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 (<port> a <sometype>) +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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . + 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 +# Copyright (C) 2008-2009 Lars Luthman +# +# 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: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix owl: . +@prefix xsd: . +@prefix doap: . +@prefix foaf: . +@prefix amb: . + + a lv2:Specification ; + doap:license ; + doap:name "LV2 Port Groups" ; + rdfs:comment "Defines semantic groupings of LV2 ports" ; + doap:maintainer [ + a foaf:Person ; + foaf:name "Lars Luthman" ; + foaf:mbox + ] , [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] . + + +## 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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . + 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 +# +# 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: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix owl: . +@prefix xsd: . +@prefix doap: . +@prefix foaf: . + + a lv2:Specification ; + doap:license ; + 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 ; + rdfs:seeAlso + ] ; + 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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . + 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 + * + * 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 +#include + +#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: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . +@prefix doap: . +@prefix foaf: . + + + 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 +
+struct {
+	void* host_handle;
+	void (*resize_port)(void* host_handle, uint32_t index);
+}
+
+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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . 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 + * + * 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 + * . + */ + +#ifndef LV2_STRING_PORT_H +#define LV2_STRING_PORT_H + +#include + +/** 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: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . +@prefix doap: . +@prefix foaf: . + + a lv2:Specification ; + doap:license ; + doap:name "LV2 String Ports" ; + doap:maintainer [ + a foaf:Person ; + foaf:name "Krzysztof Foltman" ; + ] ; + rdfs:comment """ +Defines ports which contain string data. + +

UI issues

+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 +<http://lv2plug.in/ns/ext/contexts#MessageContext> 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. + +

Storage

+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. + +

Input Port Semantics

+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. + +

Output Port Semantics

+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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . 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 + * + * 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 . + * + * 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 + + +/** 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 +# +# 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: . +@prefix lv2: . +@prefix lv2ev: . +@prefix rdf: . +@prefix rdfs: . +@prefix doap: . +@prefix foaf: . + + a lv2:Specification ; + doap:license ; + 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 ; + rdfs:seeAlso + ] , [ + 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: . +@prefix rdfs: . + + + a lv2:Specification ; + rdfs:seeAlso . + 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 + * + * 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 + * + * 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 + +#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: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . +@prefix doap: . +@prefix foaf: . +@prefix owl: . + + a lv2:Specification ; + doap:license ; + doap:name "LV2 Instance Variables" ; + doap:created "2008-08-18" ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] ; + 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: + + + + + + + +
RDF TypeData Type
xsd:stringstring
xsd:decimalfloating point number
xsd:integerinteger number
xsd:booleanboolean value
+ +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: +
+<http://example.org/plugin> a lv2:Plugin ;
+	lv2var:variable [
+		rdf:predicate <http://example.org/greetingology#Greeting> ;
+		rdf:value "Hello, cruel world."
+	] , [
+		rdf:predicate <http://example.org/matheybits#Coeff> ;
+		rdf:value 1.23456
+	] , [
+		rdf:predicate <http://example.org/databits#BigValue> ;
+		rdf:value [
+			a somext:Something ;
+			someext:foo "Foo?" ;
+			someext:bar "Bar." ;
+			someext:baz 1234.0
+		]
+	] .
+
+""" . + + +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. +""" . + -- cgit v1.2.1