From c6883595c3a4a34bf1a459c3bc1fba91d27f18f8 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 25 Oct 2010 04:05:28 +0000 Subject: Simplify and improve atom extension. Merge atom-port extension into atom extension. Link to code documentation from atom HTML documentation. --- ext/atom.lv2/atom.ttl | 485 +++++++++++++++++++++++++++++++------------------- 1 file changed, 305 insertions(+), 180 deletions(-) (limited to 'ext/atom.lv2/atom.ttl') 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 @@ a lv2:Specification ; - doap:name "LV2 Atom" ; - doap:maintainer [ - a foaf:Person ; - foaf:name "David Robillard" ; - foaf:homepage ; - rdfs:seeAlso - ] ; + 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, 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). +"Atom" (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 +memcpy). + +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 +Event as defined by the +LV2 Event 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 blob support. +A Blob is a dynamically allocated chunk of memory +that (unlike an Atom) is not necessarily POD. Blobs are accessed via a +Reference, which is a special case of Atom that +always has type = 0, 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 EventPort +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: ValuePort and MessagePort, 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 LV2 URI Map 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 LV2_Atom has a 16-bit type and size followed by +a body. + +All concrete Atom types (subclasses of this class) MUST define a precise +binary layout for body. + +The type field is the URI of a subclass of Atom mapped to an +integer using the URI Map +extension's LV2_URI_Map_Feature::uri_to_id with +map = "http://lv2plug.in/ns/ext/event". If a plugin or host +does not understand type, that atom SHOULD be gracefully ignored +(though it MAY be 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 non-reference Atom with a simple memcpy, even if +the implementation does not understand type. """ . -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 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 via functions provided by the host in +LV2_Blob_Support. -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 type = 0. +"Null" is the unique Atom with type = 0 and size = 0. """ . -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 +LV2_Atom_String has an ID +lang followed by the string data in UTF-8 encoding. The length of the +string data in bytes is size - sizeof(uint32_t), including the +terminating NULL character. The lang may be any URI; to +describe a human language, use http://lexvo.org/id/term/LANG where LANG is +an ISO 693-2 or +ISO 693-3 language code. + +For example, "Hello" in English: +
+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";
+
+and French: +
+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";
+
+or a Turtle string: +
+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> ."
+
""" . -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 +URI Map extension's +LV2_URI_Map_Feature::uri_to_id +with map = NULL. """ . -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 -
-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. +An LV2_Atom_Vector is a +16-bit elem_count and elem_type followed +by elem_count atom bodies of type elem_type. +The element type must be a fixed size Atom type, i.e. the +size of each element is the vector's size / elem_count. + +For example, an atom:Vector containing 42 elements of type atom:Float looks +like this in memory:
-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;
 
+ Note that it is possible to construct a valid Atom for each element of the vector, even by an implementation which does not understand elem_type. -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): -
-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] = ...
-
+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 atoms with varying type +and size. -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). -
-uint32_t key;
-LV2_Atom value;
-
+A single property of some Object. An +LV2_Atom_Property +has an ID key and +Atom value. """ . -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 Atom +with a number of properties. An LV2_Atom_Object is an unsigned 32-bit +integer context and id followed by a sequence of +properties. + +The context is mapped using the URI Map extension's LV2_URI_Map_Feature::uri_to_id +with map = NULL, and may be 0 (the default context). + +Note this is an abstract class, i.e. no Atom can exist with +type = uri_to_id(atom:Object). An Object is +either a Resource or a Blank, but the body 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: -
-uint32_t subject;
-uint32_t predicate;
-LV2_Atom object;
-
+atom:Resource a rdfs:Class ; + rdfs:subClassOf atom:Object ; + rdfs:comment """ +An Object where id is the +URI of the resource mapped to an ID. """ . -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 Object where id 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, id is NOT an ID. +""" . -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:Model a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Model" ; + rdfs:comment """ +A description of a set of objects. 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) (size = 0)" . + +atom:Byte + a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Byte (size = 1)" . + +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: -<> ex:hasThing [ a ex:Thing ] +Support for dynamically allocated blobs. If a host supports this feature, it +MUST pass a LV2_Feature with +URI http://lv2plug.in/ns/ext/atom#blobSupport +and data pointing to a LV2_Blob_Support. +""" . -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:Blob a rdfs:Class ; + rdfs:label "Blob" ; + rdfs:comment """ +Base class for all dynamically allocated blobs. An LV2_Blob ia an opaque pointer to host +data. The type and data of a blob can be accessed via host-provided +functions in LV2_Blob_Support. +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 Atom. Ports of this type will +be connected to a 32-bit aligned LV2_Atom +immediately followed by size 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 ValuePort +or 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 = 0 and size = 0). +""" . -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". +
    +
  • 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 a 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. """ . -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 Atom 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. """ . -- cgit v1.2.1