From 272a00fd7f75c7510c946b515149dafe67d1da34 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 13 Apr 2012 22:44:21 +0000 Subject: Document standard serialisation format for all Atom types. --- lv2/lv2plug.in/ns/ext/atom/atom.ttl | 193 ++++++++++++++++++++++++++++-------- 1 file changed, 150 insertions(+), 43 deletions(-) (limited to 'lv2/lv2plug.in/ns') diff --git a/lv2/lv2plug.in/ns/ext/atom/atom.ttl b/lv2/lv2plug.in/ns/ext/atom/atom.ttl index d2ac20c..a614a7d 100644 --- a/lv2/lv2plug.in/ns/ext/atom/atom.ttl +++ b/lv2/lv2plug.in/ns/ext/atom/atom.ttl @@ -26,22 +26,23 @@ dcs:blame ] ; lv2:documentation """ -

This extension defines a generic container for data, called an Atom, -and several basic Atom types which can be used to express structured data. -Atoms are (with one exception) Plain Old Data (POD), which means they can be -easily copied generically (e.g. using memcpy), and are suitable -for use in high-performance and real-time 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. Similarly, plugins (such as routers, delays, or data stores) can +

This specification defines a generic container for data, called an +Atom, and several basic Atom types which can be used to express +structured data. An atom:Atom is (with one exception) Plain Old Data (POD), +which means it can be copied generically (e.g. using a simple +memcpy), and is suitable for use in real-time code.

+ +

The purpose of Atoms is to allow implementations that process and/or +transmit data to be independent of that data's type. For example, plugins that +mutually understand a type can be used together in a host that does not +understand that type, because the host's required facilities are generic. +Similarly, plugins (such as routers, delays, or data structures) can meaningfully process atoms of a type unknown to them.

Atoms can and should be used anywhere values of various types must be stored -or transmitted. This extension defines a port type, atom:AtomPort, for -transmitting atoms via ports. The atom:Sequence type in an atom:AtomPort -replaces the LV2 event -extension.

+or transmitted. The port type atom:AtomPort can be used to transmit atoms via +ports. The atom:Sequence type in an atom:AtomPort replaces the LV2 event extension.

The types defined in this extension should be powerful enough to express almost any structure. Implementations SHOULD build structures out of the types @@ -53,6 +54,16 @@ where absolutely necessary.

Implementing this extension requires a facility for mapping URIs to integers, such as the LV2 URID extension.

+ +

Serialisation

+ +

An Atom type primarily defines a binary format (i.e. a C data type) for use +at runtime. However, each Atom type also has a standard serialisation format +which SHOULD be used wherever an atom needs to be expressed as a string or in +Turtle. Thus, this specification not only defines binary data types for +plugins to use, but a complete data model with a portable RDF-compatible +serialisation. This is useful for inter-process communication as well as +saving state.

""" . atom:cType @@ -61,10 +72,23 @@ atom:cType owl:FunctionalProperty ; rdfs:label "C type" ; rdfs:domain rdfs:Class ; - rdfs:range xsd:string ; + rdfs:range lv2:Symbol ; rdfs:comment """ -The identifier for a C type describing the in-memory representation of -an instance of this class. +The identifier for a C type describing the binary representation of an Atom of +this type. +""" . + +atom:stringType + a rdf:Property , + owl:ObjectProperty , + owl:FunctionalProperty ; + rdfs:label "String type" ; + rdfs:domain rdfs:Class ; + rdfs:range rdfs:Datatype ; + lv2:documentation """ +

The type to be used when representing an Atom of this type as a string +(e.g. in XML or RDF). Typically an XML Schema Datatype URI.

""" . atom:Atom @@ -73,14 +97,14 @@ atom:Atom atom:cType "LV2_Atom" ; lv2:documentation """

Abstract base class for all atoms. An LV2_Atom has a 32-bit -type and size followed by a body of size +size and type followed by a body of size bytes. Atoms MUST be 64-bit aligned.

All concrete Atom types (subclasses of this class) MUST define a precise binary layout for their body.

The type field is the URI of an Atom type mapped to an integer. -Implementations SHOULD gracefully ignore, or pass through, atoms with unknown +Implementations SHOULD gracefully pass through, or ignore, atoms with unknown types.

All atoms are POD by definition except references, which as a special case @@ -91,8 +115,9 @@ reserves the type 0 for references, the details of reference handling are currently unspecified. A future revision of this extension, or a different extension, may define how to use non-POD data and references. Implementations MUST NOT send references to another implementation unless the receiver is -explicitly known to support references (e.g. by supporting a feature). The -atom with both type and size 0 is +explicitly known to support references (e.g. by supporting a feature).

+ +

The atom with both type and size 0 is null, which is not considered a Reference.

""" . @@ -100,11 +125,20 @@ atom:Chunk a rdfs:Class ; rdfs:subClassOf atom:Atom ; rdfs:label "Chunk of memory" ; + atom:stringType xsd:base64Binary ; lv2:documentation """

A chunk of memory with undefined contents. This type is used to indicate a certain amount of space is available. For example, output ports with a variably sized type are connected to a Chunk so the plugin knows the size of the buffer available for writing.

+ +

The use of a Chunk should be constrained to a local scope, since +interpreting it is impossible without context. However, if serialised to RDF, +a Chunk may be represented directly as an xsd:base64Binary string, e.g.:

+ +
+[] eg:someChunk "vu/erQ=="^^xsd:base64Binary .
+
""" . atom:Number @@ -116,31 +150,36 @@ atom:Int a rdfs:Class ; rdfs:subClassOf atom:Number ; rdfs:label "Signed 32-bit integer" ; - atom:cType "LV2_Atom_Int" . + atom:cType "LV2_Atom_Int" ; + atom:stringType xsd:int . atom:Long a rdfs:Class ; rdfs:subClassOf atom:Number ; rdfs:label "Signed 64-bit integer" ; - atom:cType "LV2_Atom_Long" . + atom:cType "LV2_Atom_Long" ; + atom:stringType xsd:long . atom:Float a rdfs:Class ; rdfs:subClassOf atom:Number ; rdfs:label "32-bit IEEE-754 floating point number" ; - atom:cType "LV2_Atom_Float" . + atom:cType "LV2_Atom_Float" ; + atom:stringType xsd:float . atom:Double a rdfs:Class ; rdfs:subClassOf atom:Number ; rdfs:label "64-bit IEEE-754 floating point number" ; - atom:cType "LV2_Atom_Double" . + atom:cType "LV2_Atom_Double" ; + atom:stringType xsd:double . atom:Bool a rdfs:Class ; rdfs:subClassOf atom:Atom ; rdfs:label "Boolean" ; atom:cType "LV2_Atom_Bool" ; + atom:stringType xsd:boolean ; rdfs:comment "An Int where 0 is false and any other value is true." . atom:String @@ -148,6 +187,7 @@ atom:String rdfs:subClassOf atom:Atom ; rdfs:label "String" ; atom:cType "LV2_Atom_String" ; + atom:stringType xsd:string ; lv2:documentation """

A UTF-8 encoded string.

@@ -155,10 +195,9 @@ atom:String array of bytes (uint8_t) terminated with a NULL byte ('\\0').

-

This type can be used for free-form strings, but in most cases it is better to -use atom:Literal since this supports a language tag or datatype. Implementations -SHOULD NOT use atom:String unless translating the string does not make sense and -the string has no meaningful datatype.

+

This type is for free-form strings, but SHOULD NOT be used for typed data or +text in any language. Use atom:Literal unless translating the string does not +make sense and the string has no meaningful datatype.

""" . atom:Literal @@ -169,7 +208,7 @@ atom:Literal lv2:documentation """

A UTF-8 encoded string literal, with an optional datatype or language.

-

This type is compatible with rdf:Literal and is capable of expressing a +

This type is compatible with rdfs:Literal and is capable of expressing a string in any language or a value of any type. A Literal has a datatype and lang followed by string data in UTF-8 encoding. The length of the string data in bytes is size - @@ -185,10 +224,10 @@ both.

For example, a Literal can be "Hello" in English:

 void set_to_hello_in_english(LV2_Atom_Literal* lit) {
-     lit->atom.type = map(expand("atom:Literal"));
-     lit->atom.size = 14;
-     lit->datatype  = 0;
-     lit->lang      = map("http://lexvo.org/id/iso639-1/en");
+     lit->atom.type     = map(expand("atom:Literal"));
+     lit->atom.size     = 14;
+     lit->body.datatype = 0;
+     lit->body.lang     = map("http://lexvo.org/id/iso639-1/en");
      memcpy(LV2_ATOM_CONTENTS(LV2_Atom_Literal, lit),
             "Hello",
             sizeof("Hello"));  // Assumes enough space
@@ -198,10 +237,10 @@ void set_to_hello_in_english(LV2_Atom_Literal* lit) {
 

or a Turtle string:

 void set_to_turtle_string(LV2_Atom_Literal* lit, const char* ttl) {
-     lit->atom.type = map(expand("atom:Literal"));
-     lit->atom.size = 64;
-     lit->datatype  = map("http://www.w3.org/2008/turtle#turtle");
-     lit->lang      = 0;
+     lit->atom.type     = map(expand("atom:Literal"));
+     lit->atom.size     = 64;
+     lit->body.datatype = map("http://www.w3.org/2008/turtle#turtle");
+     lit->body.lang     = 0;
      memcpy(LV2_ATOM_CONTENTS(LV2_Atom_Literal, lit),
             ttl,
             strlen(ttl) + 1);  // Assumes enough space
@@ -223,6 +262,7 @@ atom:URI
 	a rdfs:Class ;
 	rdfs:subClassOf atom:String ;
 	rdfs:label "URI string" ;
+	atom:stringType xsd:anyURI ;
 	lv2:documentation """
 

A URI string. This is identical in format to atom:String, except the string is a URI. This is useful when a URI is needed but mapping is inappropriate, @@ -269,6 +309,20 @@ struct VectorOf42Floats {

Note that it is possible to construct a valid Atom for each element of the vector, even by an implementation which does not understand child_type.

+ +

If serialised to RDF, a Vector SHOULD have the form:

+ +
+eg:someVector
+     a atom:Vector ;
+     atom:childType atom:Int ;
+     rdf:value (
+         "1"^^xsd:int
+         "2"^^xsd:int
+         "3"^^xsd:int
+         "4"^^xsd:int
+     ) .
+
""" . atom:Tuple @@ -280,6 +334,19 @@ atom:Tuple

The body of a Tuple is simply a series of complete atoms, each aligned to 64 bits.

+ +

If serialised to RDF, a Tuple SHOULD have the form:

+ +
+eg:someVector
+     a atom:Tuple ;
+     rdf:value (
+         "1"^^xsd:int
+         "3.5"^^xsd:float
+         "etc"
+     ) .
+
+ """ . atom:Property @@ -295,6 +362,17 @@ and the value is the object.

The context field can be used to specify a different context for each property, where this is useful. Otherwise, it may be 0.

+ +

Properties generally only exist as part of an atom:Object. Accordingly, +they will typically be represented directly as properties in RDF (see +atom:Object). If this is not possible, they may be expressed as partial +reified statements, e.g.:

+ +
+eg:someProperty
+    rdf:predicate eg:theKey ;
+    rdf:object eg:theValue .
+
""" . atom:Object @@ -314,6 +392,16 @@ structure to allow for fast dispatch.

This is an abstract Atom type, an Object is always either a atom:Resource or a atom:Blank.

+ +

If serialised to RDF, an Object SHOULD be represented directly as a +resource, e.g.:

+ +
+eg:someObject
+    eg:firstPropertyKey "first property value" ;
+    eg:secondPropertyKey "first loser" ;
+    eg:andSoOn "and so on" .
+
""" . atom:Resource @@ -348,7 +436,8 @@ atom:Sound

An atom:Vector of atom:Float which represents an audio waveform. The format is the same as the buffer format for lv2:AudioPort (except the size may be arbitrary). An atom:Sound inherently depends on the sample rate, which is -assumed to be known.

+assumed to be known from context. Because of this, directly serialising an +atom:Sound is probably a bad idea, use a standard format like WAV instead.

""" . atom:TimeUnit @@ -383,7 +472,7 @@ atom:Frames lv2:documentation """

Time in audio frames. Converting this to absolute time depends on the sample rate. When this is the stamp unit for an atom:Sequence, its events have -int64_t time stamps (event.time.frames)

+int64_t time stamps (LV2_Atom_Event.time.frames)

""" . atom:Beats @@ -393,15 +482,16 @@ atom:Beats lv2:documentation """

Time in beats. Converting this to absolute time depends on the tempo. When this is the stamp unit for an atom:Sequence, the events in that sequence have a -double stamp (event.time.beats).

""" . +double stamp (LV2_Atom_Event.time.beats).

+""" . atom:Event a rdfs:Class ; rdfs:label "Event" ; atom:cType "LV2_Atom_Event" ; lv2:documentation """ -

An atom with a time stamp header prepended, typically an element of an -atom:Sequence. Note this is not an Atom type.

+

An atom with a time stamp prefix, typically an element of an atom:Sequence. +Note this is not an Atom type.

""" . atom:Sequence @@ -411,6 +501,23 @@ atom:Sequence atom:cType "LV2_Atom_Sequence" ; lv2:documentation """

A sequence of atom:Event, i.e. a series of time-stamped Atoms.

+ +

If serialised to RDF, a Sequence has a similar form to atom:Vector, but for +brevity the elements may be assumed to be atom:Event, e.g.:

+ +
+eg:someSequence
+    a atom:Sequence ;
+    rdf:value (
+        [
+            atom:frameTime 1 ;
+            rdf:value "901A01"^^midi:MidiEvent
+        ] [
+            atom:frameTime 3 ;
+            rdf:value "902B02"^^midi:MidiEvent
+        ]
+    ) .
+
""" . atom:AtomPort @@ -418,7 +525,7 @@ atom:AtomPort rdfs:subClassOf lv2:Port ; rdfs:label "Atom Port" ; lv2:documentation """ -

A port which contains an lv2:Atom. Ports of this type are connected to an +

A port which contains an atom:Atom. Ports of this type are connected to an LV2_Atom with a type specified by atom:bufferType.

Output ports with a variably sized type MUST be initialised by the host -- cgit v1.2.1