diff options
Diffstat (limited to 'ext/atom.lv2/atom.ttl')
-rw-r--r-- | ext/atom.lv2/atom.ttl | 485 |
1 files changed, 305 insertions, 180 deletions
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. """ . |