diff options
Diffstat (limited to 'ext')
-rw-r--r-- | ext/atom-port.lv2/atom-port.ttl | 127 | ||||
-rw-r--r-- | ext/atom-port.lv2/manifest.ttl | 7 | ||||
-rw-r--r-- | ext/atom.lv2/atom-helpers.h | 27 | ||||
-rw-r--r-- | ext/atom.lv2/atom.h | 159 | ||||
-rw-r--r-- | ext/atom.lv2/atom.ttl | 485 | ||||
-rw-r--r-- | ext/message.lv2/message.ttl | 4 |
6 files changed, 403 insertions, 406 deletions
diff --git a/ext/atom-port.lv2/atom-port.ttl b/ext/atom-port.lv2/atom-port.ttl deleted file mode 100644 index 7533606..0000000 --- a/ext/atom-port.lv2/atom-port.ttl +++ /dev/null @@ -1,127 +0,0 @@ -# LV2 Atom Port Extension -# Copyright (C) 2010 David Robillard <d@drobilla.net> -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. - -@prefix aport: <http://lv2plug.in/ns/ext/atom-port#> . -@prefix atom: <http://lv2plug.in/ns/ext/atom#> . -@prefix doap: <http://usefulinc.com/ns/doap#> . -@prefix foaf: <http://xmlns.com/foaf/0.1/> . -@prefix lv2: <http://lv2plug.in/ns/lv2core#> . -@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . -@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . -@prefix xsd: <http://www.w3.org/2001/XMLSchema> . - -<http://lv2plug.in/ns/ext/atom-port> - a lv2:Specification ; - doap:name "LV2 Atom Port" ; - doap:maintainer [ - a foaf:Person ; - foaf:name "David Robillard" ; - foaf:homepage <http://drobilla.net/> ; - rdfs:seeAlso <http://drobilla.net/drobilla.rdf> - ] ; - rdfs:comment """ -This extension describes port types that hold polymorphic values -(<a href="http://lv2plug.in/ns/ext/atom#Atom">atom:Atom</a>). There are -two such port types with equivalent buffer formats but different semantics: -value ports (aport:ValuePort) and message ports (aport:MessagePort). -""" . - - -aport:AtomPort a rdfs:Class ; - rdfs:label "Atom Port" ; - rdfs:subClassOf lv2:Port ; - rdfs:comment """ -A port which contains a polymorphic value, or "atom". -Ports of this type will be connected to a 32-bit aligned <a -href="http://lv2plug.in/ns/ext/atom#Atom">atom:Atom</a> (i.e. a uint32_t type, -immediately followed by a uint32_t size, immediately followed by that many -bytes of data). - -This is an abstract port type. A port that is a aport:AtomPort MUST also -have a more descriptive type that is a subClassOf aport:AtomPort which -defines the port's semantics (typically aport:ValuePort or aport:MessagePort). - -Before calling a method on the plugin that writes to an AtomPort output, -the host MUST set the size of the Atom in that output to the amount of -available memory immediately following the Atom header. The plugin MUST -write a valid Atom to that port (leaving it untouched is illegal). If there -is no reasonable value to write to the port, the plugin MUST write null -(the atom with both type and size equal to zero). -""" . - - -#aport:respondsWith a rdf:Property ; -# rdfs:domain aport:MessagePort ; -# rdfs:range lv2:Symbol ; -# rdfs:label "responds with" ; -# rdfs:comment """ -#Indicates that a message port responds to messages via the port with the -#given symbol on the same plugin instance. If -#<pre>input aport:respondsWith output</pre> then after running the plugin with -#a message <em>m</em> in <code>input</code> the host SHOULD interpret the aport: -#in <code>output</code> as the response to <em>m</em>. -#""" . - - -aport:ValuePort a rdfs:Class ; - rdfs:label "Value Port" ; - rdfs:subClassOf aport:AtomPort ; - rdfs:comment """ -An AtomPort that interprets its data as a persistent and time-independent -"value". -<ul> -<li>If a plugin has fixed input values for all ports, all ValuePort outputs -are also fixed regardless of the number of times the plugin is run.</li> -<li>If a plugin has fixed input values for all ports except a ValuePort, -each value V of that ValuePort corresponds to a single set of outputs -for all ports.</li> -<li>If an aport:ValuePort contains a reference then the blob it refers to is -constant; plugin MUST NOT modify the blob in any way.</li> -</ul> -Value ports can be thought of as purely functional ports: if a plugin -callback has only value ports, then the plugin callback is a pure function. -""" . - - -aport:MessagePort a rdfs:Class ; - rdfs:label "Message Port" ; - rdfs:subClassOf aport:AtomPort ; - rdfs:comment """ -An AtomPort that consumes or executes its value as a "message". The contents -of a MessagePort are considered transient and/or time-dependent, and only -apply for a single run invocation. Unlike a ValuePort, a MessagePort may -be used to manipulate and access internal plugin state. - -Intuitively, a MessagePort contains a "command" or "event" (which is reacted -to), NOT a "value" or "signal" (which is computed with). -""" . - -aport:supports a rdf:Property ; - rdfs:domain lv2:Port ; - rdfs:range atom:AtomType ; - rdfs:label "supports" ; - rdfs:comment """ -Indicates that an atom port supports a certain value type. This is distinct -from the port type - e.g. the port type ValuePort can hold atoms with many -different types. This property is used to describe which atom types -a port ``understands''. -""" . - diff --git a/ext/atom-port.lv2/manifest.ttl b/ext/atom-port.lv2/manifest.ttl deleted file mode 100644 index e681793..0000000 --- a/ext/atom-port.lv2/manifest.ttl +++ /dev/null @@ -1,7 +0,0 @@ -@prefix lv2: <http://lv2plug.in/ns/lv2core#> . -@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . - -<http://lv2plug.in/ns/ext/atom-port> - a lv2:Specification ; - rdfs:seeAlso <atom-port.ttl> . - diff --git a/ext/atom.lv2/atom-helpers.h b/ext/atom.lv2/atom-helpers.h index 5913aee..5c98a3f 100644 --- a/ext/atom.lv2/atom-helpers.h +++ b/ext/atom.lv2/atom-helpers.h @@ -46,24 +46,28 @@ lv2_atom_pad_size(uint16_t size) typedef LV2_Atom_Property* LV2_Object_Iter; +/** Get an iterator pointing to @a prop in some LV2_Object */ static inline LV2_Object_Iter lv2_object_get_iter(LV2_Atom_Property* prop) { return (LV2_Object_Iter)prop; } +/** Return true iff @a iter has reached the end of @a object */ static inline bool lv2_object_iter_is_end(const LV2_Atom* object, LV2_Object_Iter iter) { return (uint8_t*)iter >= (object->body + object->size); } +/** Return true iff @a l points to the same property as @a r */ static inline bool lv2_object_iter_equals(const LV2_Object_Iter l, const LV2_Object_Iter r) { return l == r; } +/** Return an iterator to the property following @a iter */ static inline LV2_Object_Iter lv2_object_iter_next(const LV2_Object_Iter iter) { @@ -71,6 +75,7 @@ lv2_object_iter_next(const LV2_Object_Iter iter) (uint8_t*)iter + sizeof(LV2_Atom_Property) + lv2_atom_pad_size(iter->value.size)); } +/** Return the property pointed to by @a iter */ static inline LV2_Atom_Property* lv2_object_iter_get(LV2_Object_Iter iter) { @@ -86,6 +91,7 @@ lv2_object_iter_get(LV2_Object_Iter iter) * LV2_Atom_Property* prop = lv2_object_iter_get(i); * // Do things with prop here... * } + * </pre> */ #define LV2_OBJECT_FOREACH(obj, iter) \ for (LV2_Object_Iter (iter) = lv2_object_get_iter((LV2_Atom_Property*)(obj)->body); \ @@ -98,17 +104,18 @@ lv2_object_iter_get(LV2_Object_Iter iter) * Atom type that contains headerless 32-bit aligned properties. * @param object Pointer to the atom that contains the property to add. object.size * must be valid, but object.type is ignored. - * @param size Must point to the size field of the container atom, and will be - * padded up to 32 bits then increased by @a value_size. - * @param body Must point to the body of the container atom. + * @param key The key of the new property + * @param value_type The type of the new value + * @param value_size The size of the new value + * @param value_body Pointer to the new value's data * @return a pointer to the new LV2_Atom_Property in @a body. */ static inline LV2_Atom_Property* -lv2_atom_append_property(LV2_Atom* object, - uint32_t key, - uint16_t value_type, - uint16_t value_size, - const char* value_body) +lv2_atom_append_property(LV2_Atom* object, + uint32_t key, + uint16_t value_type, + uint16_t value_size, + const uint8_t* value_body) { object->size = lv2_atom_pad_size(object->size); LV2_Atom_Property* prop = (LV2_Atom_Property*)(object->body + object->size); @@ -120,12 +127,14 @@ lv2_atom_append_property(LV2_Atom* object, return prop; } +/** Return true iff @a atom is NULL */ static inline bool lv2_atom_is_null(LV2_Atom* atom) { return !atom || (atom->type == 0 && atom->size == 0); } +/** Return true iff @a object has rdf:type @a type */ static inline bool lv2_atom_is_a(LV2_Atom* object, uint32_t rdf_type, @@ -173,7 +182,7 @@ typedef struct { * linear sweep. By allocating @a q on the stack, objects can be "queried" * quickly without allocating any memory. This function is realtime safe. */ -int +static inline int lv2_object_query(LV2_Atom* object, LV2_Object_Query* query) { int matches = 0; diff --git a/ext/atom.lv2/atom.h b/ext/atom.lv2/atom.h index df73504..f547e80 100644 --- a/ext/atom.lv2/atom.h +++ b/ext/atom.lv2/atom.h @@ -51,16 +51,16 @@ * * Note that an LV2_Atom is the latter two fields of an LV2_Event as defined * by the <a href="http://lv2plug.in/ns/ext/event">LV2 events extension</a>. - * The host MAY marshal an Event to an Atom simply by pointing to the offset - * of the 'type' field of the LV2_Event, which is also the type field (i.e. start) - * of a valid LV2_Atom. The macro LV2_ATOM_FROM_EVENT is provided in this - * header for this purpose. + * The host MAY marshal an <a href="urn:struct:LV2_Event">LV2_Event</a> to + * an <a href="urn:struct:LV2_Atom">LV2_Atom</a> by simply pointing to the + * offset of <code>type</code>. The macro LV2_ATOM_FROM_EVENT is provided + * in this header for this purpose. */ typedef struct _LV2_Atom { - /** The type of this atom. This number represents a URI, mapped to an - * integer using the extension <http://lv2plug.in/ns/ext/uri-map> - * with "http://lv2plug.in/ns/ext/atom" as the 'map' argument. + /** The type of this atom. This number is mapped from a URI using + * the extension <http://lv2plug.in/ns/ext/uri-map> + * with 'map' = "http://lv2plug.in/ns/ext/atom". * Type 0 is a special case which indicates this atom * is a reference and MUST NOT be copied manually. */ @@ -77,66 +77,47 @@ typedef struct _LV2_Atom { /** Reference, an LV2_Atom with type 0 */ typedef LV2_Atom LV2_Atom_Reference; -/** The body of an LV2_Atom with type atom:Vector */ +/** The body of an atom:String */ +typedef struct _LV2_Atom_String { + uint32_t lang; /**< The ID of the language of this string */ + char* str; /**< Null-terminated string data in UTF-8 encoding */ +} LV2_Atom_String; + +/** The body of an atom:Vector */ typedef struct _LV2_Atom_Vector { - uint16_t elem_count; /**< The size of each element in the vector */ + uint16_t elem_count; /**< The number of elements in the vector */ uint16_t elem_type; /**< The type of each element in the vector */ - uint8_t elems[]; /**< Elements follow here */ + uint8_t elems[]; /**< Sequence of element bodies */ } LV2_Atom_Vector; -/** The body of an LV2_Atom with type atom:Property */ +/** The body of an atom:Property */ typedef struct _LV2_Atom_Property { - uint32_t key; /**< Key (predicate) of Object or RDF triple (URIInt) */ - LV2_Atom value; /**< Value (object) of Object or RDF triple */ + uint32_t key; /**< ID of key (predicate) */ + LV2_Atom value; /**< Value (object) */ } LV2_Atom_Property; -/** The body of an LV2_Atom with type atom:Triple */ -typedef struct _LV2_Atom_Triple { - uint32_t subject; /**< Subject of RDF triple (URI mapped integer) */ - LV2_Atom_Property property; /** Property (predicate and object) of subject */ -} LV2_Atom_Triple; +/** The body of an atom:Resource or atom:Blank */ +typedef struct _LV2_Atom_Object { + uint32_t context; /**< ID of context graph, or 0 for the default context */ + uint32_t id; /**< ID for atom:Resource or blank ID for atom:Blank */ + uint8_t properties[]; /**< Sequence of LV2_Atom_Property */ +} LV2_Atom_Object; /* Optional Blob Support */ - -typedef void* LV2_Blob_Data; - /** Dynamically Allocated LV2 Blob. * - * This is a blob of data of any type, dynamically allocated in memory. + * This is an opaque blob of data of any type, dynamically allocated in memory. * Unlike an LV2_Atom, a blob is not necessarily POD. Plugins MUST only * refer to blobs via a Reference (an LV2_Atom with type 0), there is no * way for a plugin to directly copy or destroy a Blob. + * + * This is a pointer to host data which is opaque to the plugin. + * Plugins MUST NOT interpret this data in any way, except via host-provided + * functions in LV2_Blob_Support. */ -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 blobs 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; typedef void* LV2_Blob_Support_Data; @@ -144,11 +125,10 @@ typedef void (*LV2_Blob_Destroy)(LV2_Blob* blob); /** The data field of the LV2_Feature for atom:BlobSupport. * - * A host which supports blobs must pass an LV2_Feature struct to the - * plugin's instantiate method with 'URI' equal to - * "http://lv2plug.in/ns/ext/atom#BlobSupport" 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'. + * A host which supports blobs must pass an LV2_Feature to the plugin's + * instantiate method with 'URI' = "http://lv2plug.in/ns/ext/atom#BlobSupport" + * 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 { @@ -167,35 +147,16 @@ typedef struct { * uint16, like LV2_Atom.size. */ uint16_t ref_size; - - /** Initialize a reference to point to a newly allocated Blob. - * - * @param data Must be the data member of this struct. - * @param ref Pointer to an area of memory at least as large as - * the ref_size field of this struct. On return, this will - * be the unique reference to the new blob, which is owned by the - * caller. Assumed to be uninitialised, i.e. the caller MUST NOT - * pass a valid (owned) reference since this could cause a memory leak. - * @param destroy Function to destroy this blob. 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 - * (since this is allocated by the host). - * @param type Type of blob to allocate (URI mapped integer). - * @param size Size of blob to allocate in bytes. - */ - void (*blob_new)(LV2_Blob_Support_Data data, - LV2_Atom_Reference* ref, - LV2_Blob_Destroy destroy, - uint32_t type, - size_t size); - - /** Return a pointer to the Blob referred to by @a ref. + + /** Return 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). + * methods defined in LV2_Blob_Support (e.g. it MUST NOT be directly + * accessed, copied, or destroyed). The actual payload of the blob can + * be accessed with LV2_Blob_Support.blob_get. */ - LV2_Blob* (*ref_get)(LV2_Blob_Support_Data data, - LV2_Atom_Reference* ref); + LV2_Blob (*ref_get)(LV2_Blob_Support_Data data, + LV2_Atom_Reference* ref); /** Copy a reference. * This copies a reference but not the blob it refers to, @@ -223,6 +184,42 @@ typedef struct { */ void (*ref_reset)(LV2_Blob_Support_Data data, LV2_Atom_Reference* ref); + + /** Initialize a reference to point to a newly allocated Blob. + * + * @param data Must be the data member of this struct. + * @param ref Pointer to an area of memory at least as large as + * the ref_size field of this struct. On return, this will + * be the unique reference to the new blob, which is owned by the + * caller. Assumed to be uninitialised, i.e. the caller MUST NOT + * pass a valid reference since this could cause a memory leak. + * @param destroy Function to destroy this blob. 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 + * (since this is allocated by the host). + * @param type ID of type of blob to allocate. + * @param size Size of blob to allocate in bytes. + */ + void (*blob_new)(LV2_Blob_Support_Data data, + LV2_Atom_Reference* ref, + LV2_Blob_Destroy destroy, + uint32_t type, + size_t size); + + /** Get blob's type as an ID. + * + * The return value may be any type URI, mapped to an integer with the + * URI Map extension with <code>context = NULL</code>. + */ + uint32_t (*blob_type)(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* (*blob_data)(LV2_Blob blob); } LV2_Blob_Support; diff --git a/ext/atom.lv2/atom.ttl b/ext/atom.lv2/atom.ttl index a7d663b..cf048aa 100644 --- a/ext/atom.lv2/atom.ttl +++ b/ext/atom.lv2/atom.ttl @@ -30,255 +30,380 @@ <http://lv2plug.in/ns/ext/atom> a lv2:Specification ; - doap:name "LV2 Atom" ; - doap:maintainer [ - a foaf:Person ; - foaf:name "David Robillard" ; - foaf:homepage <http://drobilla.net/> ; - rdfs:seeAlso <http://drobilla.net/drobilla.rdf> - ] ; + doap:name "LV2 Atom" ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage <http://drobilla.net/> ; + rdfs:seeAlso <http://drobilla.net/drobilla.rdf> + ] ; rdfs:comment """ This extension defines a generic format for a typed piece of data, called an -"atom" (e.g. integers, strings, buffers, data structures, etc). Atoms allow -LV2 plugins and host to communicate and store values of any type and size via -a generic mechanism (e.g. port buffers, event payloads, shared data, etc.). -Atoms are simple a chunk of memory with a type and a size, and are (with -one exception) Plain Old Data (POD) and may be safely copied (e.g. with a -simple call to <code>memcpy</code>). Because they are POD, hosts and plugins -can communicate atoms of any type, even if they do not understand that type. -This allows two plugins that both understand some type to be used together in -a host that does not itself understand that type, or allows a host to send -atoms "through" a plugin that does not understand them (for e.g. routing, -delaying, or buffering plugins). - -Atoms as defined by this extension can be trivially constructed in-place -from events as defined by the <a href="http://lv2plug.in/ns/ext/event">LV2 -Event</a> extension. A valid LV2_Atom (see atom.h) is contained within -any valid LV2_Event (see event.h). An LV2_Event is simply an LV2_Atom -with a time stamp header prepended. Atoms SHOULD be used anywhere a "value" -needs to be stored or communicated, to allow implementations to be -polymorphic and extensible. - -Atoms (the beginning of the LV2_Atom header) MUST be 32-bit aligned. - -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 (unlike other Atoms, meaningful type-oblivious use -of a Blob is impossible). +"<a href="#Atom">Atom</a>" (e.g. integers, strings, buffers, data structures, +etc). Atoms allow LV2 plugins and hosts to communicate, process, serialise, +and store values of any type via a generic mechanism (e.g. LV2 ports, events, +disk, shared memory, network). Atoms are, with one exception, Plain +Old Data (POD) and may be safely copied (e.g. with a simple call to +<code>memcpy</code>). + +Since Atom communication can be implemented generically, plugins that +understand some type can be used together in a host that does not understand +that type, and plugins (e.g. routers, delays) can process atoms of unknown +type. + +An Atom can be trivially constructed in-place from an +<a href="http://lv2plug.in/ns/ext/event#Event">Event</a> as defined by the +<a href="http://lv2plug.in/ns/ext/event">LV2 Event</a> extension. In other +words, an Event is simply an Atom with a time stamp header. Atoms SHOULD +be used anywhere a "value" needs to be stored or communicated, to allow +implementations to be polymorphic and extensible. + +Atoms (the start of the LV2_Atom header) MUST be 32-bit aligned. + +Optionally, the host MAY implement <a href="#blobSupport">blob support</a>. +A <a href="#Blob">Blob</a> is a dynamically allocated chunk of memory +that (unlike an Atom) is not necessarily POD. Blobs are accessed via a +<a href="#Reference">Reference</a>, which is a special case of Atom that +always has <code>type = 0</code>, is 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. + +Atoms can be communicated in many ways. Since an Atom is the payload of an +Event, an <a href="http://lv2plug.in/ns/ext/event#EventPort">EventPort</a> +can be used for communicating Atoms in realtime with sub-sample time stamp +accuracy. This extension also defines two port types for connecting directly +to a single Atom: <a href="ValuePort">ValuePort</a> and <a href="#MessagePort" +>MessagePort</a>, which both have the same buffer format but different +semantics (with respect to how the run() callback interprets the Atom). This extension requires the host to support the <a href="http://lv2plug.in/ns/ext/uri-map">LV2 URI Map</a> extension. """ . -atom:AtomType a rdfs:Class ; - rdfs:label "LV2 Atom Type" ; +atom:Atom a rdfs:Class ; + rdfs:label "Atom" ; 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. - -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. +Abstract base class for all atoms. An <a href="urn:struct:LV2_Atom" +>LV2_Atom</a> has a 16-bit <code>type</code> and <code>size</code> followed by +a <code>body</code>. + +All concrete Atom types (subclasses of this class) MUST define a precise +binary layout for <code>body</code>. + +The <code>type</code> field is the URI of a subclass of Atom mapped to an +integer using the <a href="http://lv2plug.in/ns/ext/uri-map">URI Map</a> +extension's <a href="urn:struct:LV2_URI_Map_Feature" +>LV2_URI_Map_Feature</a>::uri_to_id with +<code>map = "http://lv2plug.in/ns/ext/event"</code>. If a plugin or host +does not understand <code>type</code>, that atom SHOULD be gracefully ignored +(though it MAY be copied if it is not a <a href="#Reference">Reference</a>). + +All atoms are POD by definition except references, which have +<code>type = 0</code>. An Atom MUST NOT contain a Reference. It is safe +to copy any non-reference Atom with a simple <code>memcpy</code>, even if +the implementation does not understand <code>type</code>. """ . -atom:Reference a atom:AtomType ; - rdfs:label "Reference" ; +atom:Reference a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + 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. +Reference to a <a href="#Blob">Blob</a>. The actual contents of a Reference +are opaque and host specific, and must not be copied, serialized, or otherwise +interpreted by a plugin, except via functions provided by the host in +<a href="urn:struct:LV2_Blob_Support">LV2_Blob_Support</a>. -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. +A Reference is a special case of Atom with <code>type = 0</code>. +"Null" is the unique Atom with <code>type = 0</code> and <code>size = 0</code>. """ . -atom:String a atom:AtomType ; - rdfs:label "String" ; +atom:String a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + 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). +A UTF-8 encoded string, with an optional language tag. An +<a href="urn:struct:LV2_Atom_String">LV2_Atom_String</a> has an <a href="#ID">ID</a> +<code>lang</code> followed by the string data in UTF-8 encoding. The length of the +string data in bytes is <code>size - sizeof(uint32_t)</code>, including the +terminating NULL character. The <code>lang</code> may be any URI; to +describe a human language, use http://lexvo.org/id/term/LANG where LANG is +an <a href="http://www.loc.gov/standards/iso639-2/">ISO 693-2</a> or +<a href="http://www.loc.gov/standards/iso639-2/">ISO 693-3</a> language code. + +For example, "Hello" in English: +<pre> +struct LV2_Atom { + uint16_t type = uri_to_id(atom:String); + uint16_t size = 10; +} +uint32_t lang = uri_to_id("http://lexvo.org/id/term/en"); +char str[] = "Hello"; +</pre> +and French: +<pre> +struct LV2_Atom { + uint16_t type = uri_to_id(atom:String); + uint16_t size = 12; +} +uint32_t lang = uri_to_id("http://lexvo.org/id/term/fr"); +char str[] = "Bonjour"; +</pre> +or a Turtle string: +<pre> +struct LV2_Atom { + uint16_t type = uri_to_id(atom:String); + uint16_t size = 60; +} +uint32_t lang = uri_to_id("http://www.w3.org/2008/turtle#turtle"); +char str[] = "<http://example.org/foo> a <http://example.org/Thing> ." +</pre> """ . -atom:URIInt a atom:AtomType ; - rdfs:label "URI mapped to an integer" ; +atom:ID a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Integer ID mapped from a URI" ; 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. +An unsigned 32-bit integer mapped from a URI using the +<a href="http://lv2plug.in/ns/ext/uri-map">URI Map</a> extension's +<a href="urn:struct:LV2_URI_Map_Feature">LV2_URI_Map_Feature</a>::uri_to_id +with <code>map = NULL</code>. """ . -atom:Vector a atom:AtomType ; - rdfs:label "Vector" ; +atom:Vector a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Vector" ; rdfs:comment """ -A POD homogeneous sequence of atoms with equivalent type and size. +A homogeneous sequence of atoms with equivalent type and size. -The body of a vector begins with -<pre> -uint16_t elem_count; // The number of elements in the vector -uint16_t elem_type; // The type of each element -</pre> -followed by <code>elem_count</code> bodies of atoms of type -<code>elem_type</code>, each with equivalent size. For variably sized -content types, this size can be calculated using the total byte size of the -vector, e.g. +An <a href="urn:struct:LV2_Atom_Vector">LV2_Atom_Vector</a> is a +16-bit <code>elem_count</code> and <code>elem_type</code> followed +by <code>elem_count</code> atom bodies of type <code>elem_type</code>. +The element type must be a fixed size <a href="#Atom">Atom</a> type, i.e. the +size of each element is the vector's <code>size / elem_count</code>. + +For example, an atom:Vector containing 42 elements of type atom:Float looks +like this in memory: <pre> -uint16_t elem_size = (vector.size - (2 * sizeof(uint16_t))) / vector.count); +struct LV2_Atom { + uint16_t type = uri_to_id(atom:Vector); + uint16_t size = sizeof(LV2_Atom) + sizeof(LV2_Atom_Vector) + (42 * sizeof(float); +} +struct LV2_Vector { + uint16_t elem_count = 42; + uint16_t elem_type = uri_to_id(atom:Float); +} +float elem_00; +float elem_01; +... +float elem_41; </pre> + Note that it is possible to construct a valid Atom for each element of the vector, even by an implementation which does not understand <code>elem_type</code>. -Note that an Atom is 32-bit aligned by definition, and both the Atom and -Vector headers are 32-bits each, therefore the first element of a Vector is -64-bit aligned. - -For example, an atom:Vector containing 42 elements of type atom:Int32 looks -like this in memory (including the Atom header): -<pre> -uint16_t atom_type = uri_map(atom:Vector) -uint16_t atom_size = (2 * sizeof(uint16_t)) + (42 * sizeof(int32_t)) -uint16_t elem_count = 42 -uint16_t elem_type = uri_map(atom:Int32) -int32_t contents[42] = ... -</pre> +A Vector header is 64-bits, thus the first element of a Vector is 64-bit +aligned if the Vector itself is 64-bit aligned. """ . -atom:Tuple a atom:AtomType ; +atom:Tuple a rdfs:Class ; + rdfs:subClassOf atom:Atom ; rdfs:label "Tuple" ; - rdfs:comment """ -A POD sequence of atoms with varying types and sizes. + rdfs:comment """ +A sequence of <a href="#Atom">atoms</a> with varying <code>type</code> +and <code>size</code>. -The body of a tuple is simply a series of complete atoms, aligned to +The body of a Tuple is simply a sequence of complete atoms, each aligned to 32 bits. """ . -atom:Property a atom:AtomType ; - rdfs:label "RDF property of some object" ; +atom:Property a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Property of an Object" ; rdfs:comment """ -A description of a single property for some object (i.e. an RDF -statement with only predicate (key) and object (value) defined). -<pre> -uint32_t key; -LV2_Atom value; -</pre> +A single property of some <a href="#Object">Object</a>. An +<a href="urn:struct:LV2_Atom_Property">LV2_Atom_Property</a> +has an <a href="#ID">ID</a> <code>key</code> and +<a href="#Atom">Atom</a> <code>value</code>. """ . -atom:Triple a atom:AtomType ; - rdfs:label "RDF triple" ; +atom:Object a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Object" ; rdfs:comment """ -A single RDF triple. - -The subject and predicate of a Triple are implicitly URIs, thus they are stored -as URI mapped integers with type and size ommitted (i.e. a single uint32_t). +Abstract base class for an "Object", i.e. an <a href="#Atom">Atom</a> +with a number of <a href="#Property">properties</a>. An <a +href="urn:struct:LV2_Atom_Object" >LV2_Atom_Object</a> is an unsigned 32-bit +integer <code>context</code> and <code>id</code> followed by a sequence of +<a href="urn:struct:LV2_Atom_Property" >properties</a>. + +The <code>context</code> is mapped using the <a +href="http://lv2plug.in/ns/ext/uri-map">URI Map</a> extension's <a +href="urn:struct:LV2_URI_Map_Feature">LV2_URI_Map_Feature</a>::uri_to_id +with <code>map = NULL</code>, and may be 0 (the default context). + +Note this is an abstract class, i.e. no Atom can exist with +<code>type = uri_to_id(atom:Object)</code>. An Object is +either a <a href="urn:struct:LV2_Resource">Resource</a> or a <a +href="urn:struct:Blank">Blank</a>, but the <code>body</code> always has the +same binary format. Thus, both named and anonymous objects can be handled +with common code using only a 64-bit header for both. +""" . -An atom:Triple is memory is a uint32_t subject immediately followed by the -body of an atom:Property. -An atom:Triple in memory is two uint32_t's followed by an LV2_Atom: -<pre> -uint32_t subject; -uint32_t predicate; -LV2_Atom object; -</pre> +atom:Resource a rdfs:Class ; + rdfs:subClassOf atom:Object ; + rdfs:comment """ +An <a href="#Object">Object</a> where <code>id</code> is the +URI of the resource mapped to an <a href="#ID">ID</a>. """ . -atom:Triples a atom:AtomType ; - rdfs:label "RDF triple set" ; +atom:Blank a rdfs:Class ; + rdfs:subClassOf atom:Object ; rdfs:comment """ -A description in RDF (i.e. a set of triples). +An <a href="#Object">Object</a> where <code>id</code> is the blank node ID of +the object, which is only meaningful within a certain limited scope +(e.g. the container of the Blank) and MUST NOT be used as a global ID. +In particular, <code>id</code> is NOT an <a href="ID">ID</a>. +""" . -An atom:Triples contains any number of RDF triples, describing one or -several resources. The subject and predicate of all triples are implicitly -URI mapped integers, type tags are omitted. The object of triples may be -any atom. -An atom:Triples in memory is a sequence of atom:Triple where each atom:Triple -is immediately followed by the next (without time stamps or sizes), with -padding to ensure each subject is 32-bit aligned, e.g.: -<pre> -uint32_t subject1; -uint32_t predicate1; -LV2_Atom object1; -uint8_t pad[1]; /* e.g. if object1.size == 3 */ -uint32_t subject2; -uint32_t predicate2; -LV2_Atom object2; -... -</pre> +atom:Model a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Model" ; + rdfs:comment """ +A description of a set of <a href="#Object">objects</a>. In memory, a Model is +simply a sequence of objects. """ . - -atom:Blank a atom:AtomType ; - rdfs:label "Blank (anonymous resource)" ; +atom:Bang a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Bang (activity) (<code>size = 0</code>)" . + +atom:Byte + a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Byte (<code>size = 1</code>)" . + +atom:Int32 a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Signed 32-bit integer" . + +atom:Int64 a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Signed 64-bit integer" . + +atom:Bool a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Signed 32-bit integer where 0 is false" . + +atom:Float a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "32-bit IEEE-754 floating point number" . + +atom:Double a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "64-bit IEEE-754 floating point number" . + +atom:blobSupport a lv2:Feature ; + rdfs:label "Blob support" ; rdfs:comment """ -A description of an RDF resource with no URI (a resource with blank node -ID), e.g. the resource of type ex:Thing in the following Turtle description: -<code><> ex:hasThing [ a ex:Thing ]</code> +Support for dynamically allocated blobs. If a host supports this feature, it +MUST pass a <a href="urn:struct:LV2_Feature">LV2_Feature</a> with +<code>URI</code> http://lv2plug.in/ns/ext/atom#blobSupport +and <code>data</code> pointing to a <a href="urn:struct:LV2_Blob_Support" +>LV2_Blob_Support</a>. +""" . -An atom:Blank is conceptually a dictionary where keys (RDF predicates) are -URI mapped integers, and values (RDF objects) are any atom. -An atom:Blank in memory is like an atom:Triples, but with subjects omitted: -<pre> -uint32_t predicate1; -LV2_Atom object1; -uint32_t predicate2; -LV2_Atom object2; -... -</pre> +atom:Blob a rdfs:Class ; + rdfs:label "Blob" ; + rdfs:comment """ +Base class for all dynamically allocated blobs. An <a +href="urn:struct:LV2_Blob" >LV2_Blob</a> ia an opaque pointer to host +data. The type and data of a blob can be accessed via host-provided +functions in <a href="urn:struct:LV2_Blob_Support">LV2_Blob_Support</a>. +The type of a blob can be any URI that describes a data format. Blobs are +always allocated by the host, and unlike atoms are not necessarily POD. + +Blob data MUST NOT be used in any way by an implementation that does not +understand that blob type (unlike Atoms, meaningful type-oblivious use +of a Blob is impossible). """ . -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:AtomPort a rdfs:Class ; + rdfs:subClassOf lv2:Port ; + rdfs:label "Atom Port" ; + rdfs:comment """ +A port which contains an <a href="#Atom">Atom</a>. Ports of this type will +be connected to a 32-bit aligned <a href="urn:struct:LV2_Atom">LV2_Atom</a> +immediately followed by <code>size</code> bytes of data. + +This is an abstract port type, i.e. a port MUST NOT only be an AtomPort, +but must be a more descriptive type that is a subclass of AtomPort which +defines the port's semantics (typically <a href="#ValuePort">ValuePort</a> +or <a href="#MessagePort">MessagePort</a>). + +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 <code>type = 0</code> and <code>size = 0</code>). +""" . -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:ValuePort a rdfs:Class ; + rdfs:subClassOf atom:AtomPort ; + rdfs:label "Value Port" ; + rdfs:comment """ +An AtomPort that interprets its data as a persistent and time-independent +"value". +<ul> +<li>If a plugin has fixed input values for all ports, all ValuePort outputs +are also fixed regardless of the number of times the plugin is run.</li> +<li>If a plugin has fixed input values for all ports except a ValuePort, +each value V of that ValuePort corresponds to a single set of outputs +for all ports.</li> +<li>If a ValuePort contains a reference then the blob it refers to is +constant; plugin MUST NOT modify the blob in any way.</li> +</ul> +Value ports can be thought of as purely functional ports: if a plugin +callback has only value ports, then the plugin callback is a pure function. """ . -atom:BlobType a rdfs:Class ; - rdfs:label "Blob Type" ; +atom:MessagePort a rdfs:Class ; + rdfs:subClassOf atom:AtomPort ; + rdfs:label "Message Port" ; 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. +An AtomPort that "receives", "consumes", "executes", or "sends" its value. +The Atom contained in a MessagePort is considered transient and/or +time-dependent, and is only valid for a single run invocation. Unlike a +ValuePort, a MessagePort may be used to manipulate internal plugin state. -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). +Intuitively, a MessagePort contains a "message" or "command" or "event" +which is reacted to, NOT a "value" or "signal" (which is computed with). +""" . + +atom:supports a rdf:Property ; + rdfs:domain lv2:Port ; + rdfs:range atom:Atom ; + rdfs:label "supports" ; + rdfs:comment """ +Indicates that a Port supports a certain <a href="#Atom">Atom</a> 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 expects to receive or send. """ . diff --git a/ext/message.lv2/message.ttl b/ext/message.lv2/message.ttl index 60ec021..ae7d438 100644 --- a/ext/message.lv2/message.ttl +++ b/ext/message.lv2/message.ttl @@ -76,7 +76,7 @@ This is an abstract port class, the actual format and semantics of the port buffer (and messages) are defined by some other port type, i.e. a cmdControlPort MUST have another type which defines the format and semantics of the port buffer contents (likely candidates are -<a href="http://lv2plug.in/ns/ext/atom-port#MessagePort">atom-port:MessagePort</a> +<a href="http://lv2plug.in/ns/ext/atom#MessagePort">atom:MessagePort</a> or <a href="http://lv2plug.in/ns/ext/event#EventPort">ev:EventPort</a>). """ . @@ -95,7 +95,7 @@ This is an abstract port class, the actual format and semantics of the port buffer (and messages) are defined by some other port type, i.e. a cmdControlPort MUST have another type which defines the format and semantics of the port buffer contents (likely candidates are -<a href="http://lv2plug.in/ns/ext/atom-port#MessagePort">atom-port:MessagePort</a> +<a href="http://lv2plug.in/ns/ext/atom#MessagePort">atom:MessagePort</a> or <a href="http://lv2plug.in/ns/ext/event#EventPort">ev:EventPort</a>). """ . |