1@prefix atom: <http://lv2plug.in/ns/ext/atom#> . 2@prefix lv2: <http://lv2plug.in/ns/lv2core#> . 3@prefix owl: <http://www.w3.org/2002/07/owl#> . 4@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . 5@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . 6@prefix ui: <http://lv2plug.in/ns/extensions/ui#> . 7@prefix units: <http://lv2plug.in/ns/extensions/units#> . 8@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . 9 10<http://lv2plug.in/ns/ext/atom> 11 a owl:Ontology ; 12 rdfs:seeAlso <atom.h> , 13 <util.h> , 14 <forge.h> , 15 <lv2-atom.doap.ttl> ; 16 lv2:documentation """ 17 18<p>An #Atom is a simple generic data container for holding any type of Plain 19Old Data (POD). An #Atom can contain simple primitive types like integers, 20floating point numbers, and strings; as well as structured data like lists and 21dictionary-like <q>Objects</q>. Since Atoms are POD, they can be easily copied 22(e.g. using <code>memcpy</code>) anywhere and are suitable for use in real-time 23code.</p> 24 25<p>Every atom starts with an LV2_Atom header, followed by the contents. This 26allows code to process atoms without requiring special code for every type of 27data. For example, plugins that mutually understand a type can be used 28together in a host that does not understand that type, because the host is only 29required to copy atoms, not interpret their contents. Similarly, plugins (such 30as routers, delays, or data structures) can meaningfully process atoms of a 31type unknown to them.</p> 32 33<p>Atoms should be used anywhere values of various types must be stored or 34transmitted. The port type #AtomPort can be used to transmit atoms via ports. 35An #AtomPort that contains an #Sequence can be used for sample accurate event 36communication, such as MIDI, and replaces the earlier event extension.</p> 37 38<h3>Serialisation</h3> 39 40<p>Each Atom type defines a binary format for use at runtime, but also a 41serialisation that is natural to express in Turtle format. Thus, this 42specification defines a powerful real-time appropriate data model, as well as a 43portable way to serialise any data in that model. This is particularly useful 44for inter-process communication, saving/restoring state, and describing values 45in plugin data files.</p> 46 47<h3>Custom Atom Types</h3> 48 49<p>While it is possible to define new Atom types for any binary format, the 50standard types defined here are powerful enough to describe almost anything. 51Implementations SHOULD build structures out of the types provided here, rather 52than define new binary formats (e.g. use #Tuple or #Object rather than 53a new C <code>struct</code> type). Current implementations have support for 54serialising all standard types, so new binary formats are an implementation 55burden which harms interoperabilty. In particular, plugins SHOULD NOT expect 56UI communication or state saving with custom Atom types to work. In general, 57new Atom types should only be defined where absolutely necessary due to 58performance reasons and serialisation is not a concern.</p> 59""" . 60 61atom:cType 62 a rdf:Property , 63 owl:DatatypeProperty , 64 owl:FunctionalProperty ; 65 rdfs:label "C type" ; 66 rdfs:domain rdfs:Class ; 67 rdfs:range lv2:Symbol ; 68 rdfs:comment """The identifier for a C type describing the binary representation of an Atom of this type.""" . 69 70atom:Atom 71 a rdfs:Class ; 72 rdfs:label "Atom" ; 73 atom:cType "LV2_Atom" ; 74 lv2:documentation """ 75<p>Abstract base class for all atoms. An LV2_Atom has a 32-bit 76<code>size</code> and <code>type</code> followed by a body of <code>size</code> 77bytes. Atoms MUST be 64-bit aligned.</p> 78 79<p>All concrete Atom types (subclasses of this class) MUST define a precise 80binary layout for their body.</p> 81 82<p>The <code>type</code> field is the URI of an Atom type mapped to an integer. 83Implementations SHOULD gracefully pass through, or ignore, atoms with unknown 84types.</p> 85 86<p>All atoms are POD by definition except references, which as a special case 87have <code>type = 0</code>. An Atom MUST NOT contain a Reference. It is safe 88to copy any non-reference Atom with a simple <code>memcpy</code>, even if the 89implementation does not understand <code>type</code>. Though this extension 90reserves the type 0 for references, the details of reference handling are 91currently unspecified. A future revision of this extension, or a different 92extension, may define how to use non-POD data and references. Implementations 93MUST NOT send references to another implementation unless the receiver is 94explicitly known to support references (e.g. by supporting a feature).</p> 95 96<p>The atom with both <code>type</code> <em>and</em> <code>size</code> 0 is 97<q>null</q>, which is not considered a Reference.</p> 98""" . 99 100atom:Chunk 101 a rdfs:Class , 102 rdfs:Datatype ; 103 rdfs:subClassOf atom:Atom ; 104 rdfs:label "Chunk of memory" ; 105 owl:onDatatype xsd:base64Binary ; 106 lv2:documentation """ 107<p>A chunk of memory with undefined contents. This type is used to indicate a 108certain amount of space is available. For example, output ports with a 109variably sized type are connected to a Chunk so the plugin knows the size of 110the buffer available for writing.</p> 111 112<p>The use of a Chunk should be constrained to a local scope, since 113interpreting it is impossible without context. However, if serialised to RDF, 114a Chunk may be represented directly as an xsd:base64Binary string, e.g.:</p> 115 116<pre class="turtle-code"> 117[] eg:someChunk "vu/erQ=="^^xsd:base64Binary . 118</pre> 119""" . 120 121atom:Number 122 a rdfs:Class ; 123 rdfs:subClassOf atom:Atom ; 124 rdfs:label "Number" . 125 126atom:Int 127 a rdfs:Class , 128 rdfs:Datatype ; 129 rdfs:subClassOf atom:Number ; 130 rdfs:label "Signed 32-bit integer" ; 131 atom:cType "LV2_Atom_Int" ; 132 owl:onDatatype xsd:int . 133 134atom:Long 135 a rdfs:Class , 136 rdfs:Datatype ; 137 rdfs:subClassOf atom:Number ; 138 rdfs:label "Signed 64-bit integer" ; 139 atom:cType "LV2_Atom_Long" ; 140 owl:onDatatype xsd:long . 141 142atom:Float 143 a rdfs:Class , 144 rdfs:Datatype ; 145 rdfs:subClassOf atom:Number ; 146 rdfs:label "32-bit floating point number" ; 147 atom:cType "LV2_Atom_Float" ; 148 owl:onDatatype xsd:float . 149 150atom:Double 151 a rdfs:Class , 152 rdfs:Datatype ; 153 rdfs:subClassOf atom:Number ; 154 rdfs:label "64-bit floating point number" ; 155 atom:cType "LV2_Atom_Double" ; 156 owl:onDatatype xsd:double . 157 158atom:Bool 159 a rdfs:Class , 160 rdfs:Datatype ; 161 rdfs:subClassOf atom:Atom ; 162 rdfs:label "Boolean" ; 163 atom:cType "LV2_Atom_Bool" ; 164 owl:onDatatype xsd:boolean ; 165 rdfs:comment "An Int where 0 is false and any other value is true." . 166 167atom:String 168 a rdfs:Class , 169 rdfs:Datatype ; 170 rdfs:subClassOf atom:Atom ; 171 rdfs:label "String" ; 172 atom:cType "LV2_Atom_String" ; 173 owl:onDatatype xsd:string ; 174 lv2:documentation """ 175<p>A UTF-8 encoded string.</p> 176 177<p>The body of an LV2_Atom_String is a C string in UTF-8 encoding, i.e. an 178array of bytes (<code>uint8_t</code>) terminated with a NULL byte 179(<code>'\\0'</code>).</p> 180 181<p>This type is for free-form strings, but SHOULD NOT be used for typed data or 182text in any language. Use atom:Literal unless translating the string does not 183make sense and the string has no meaningful datatype.</p> 184""" . 185 186atom:Literal 187 a rdfs:Class ; 188 rdfs:subClassOf atom:Atom ; 189 rdfs:label "String Literal" ; 190 atom:cType "LV2_Atom_Literal" ; 191 lv2:documentation """ 192<p>A UTF-8 encoded string literal, with an optional datatype or language.</p> 193 194<p>This type is compatible with rdfs:Literal and is capable of expressing a 195string in any language or a value of any type. A Literal has a 196<code>datatype</code> and <code>lang</code> followed by string data in UTF-8 197encoding. The length of the string data in bytes is <code>size - 198sizeof(LV2_Atom_Literal)</code>, including the terminating NULL character. The 199<code>lang</code> field SHOULD be a URI of the form 200<http://lexvo.org/id/iso639-3/LANG> or 201<http://lexvo.org/id/iso639-1/LANG> where LANG is a 3-character ISO 693-3 202language code, or a 2-character ISO 693-1 language code, respectively.</p> 203 204<p>A Literal may have a <code>datatype</code> OR a <code>lang</code>, but never 205both.</p> 206 207<p>For example, a Literal can be "Hello" in English:</p> 208<pre class="c-code"> 209void set_to_hello_in_english(LV2_Atom_Literal* lit) { 210 lit->atom.type = map(expand("atom:Literal")); 211 lit->atom.size = 14; 212 lit->body.datatype = 0; 213 lit->body.lang = map("http://lexvo.org/id/iso639-1/en"); 214 memcpy(LV2_ATOM_CONTENTS(LV2_Atom_Literal, lit), 215 "Hello", 216 sizeof("Hello")); // Assumes enough space 217} 218</pre> 219 220<p>or a Turtle string:</p> 221<pre class="c-code"> 222void set_to_turtle_string(LV2_Atom_Literal* lit, const char* ttl) { 223 lit->atom.type = map(expand("atom:Literal")); 224 lit->atom.size = 64; 225 lit->body.datatype = map("http://www.w3.org/2008/turtle#turtle"); 226 lit->body.lang = 0; 227 memcpy(LV2_ATOM_CONTENTS(LV2_Atom_Literal, lit), 228 ttl, 229 strlen(ttl) + 1); // Assumes enough space 230} 231</pre> 232""" . 233 234atom:Path 235 a rdfs:Class , 236 rdfs:Datatype ; 237 rdfs:subClassOf atom:URI ; 238 owl:onDatatype atom:URI ; 239 rdfs:label "File path string" ; 240 lv2:documentation """ 241<p>A local file path.</p> 242 243<p>A Path is a URI reference with only a path component: no scheme, authority, 244query, or fragment. In particular, paths to files in the same bundle may be 245cleanly written in Turtle files as a relative URI. However, implementations 246may assume any binary Path (e.g. in an event payload) is a valid file path 247which can passed to system functions like fopen() directly, without any 248character encoding or escape expansion required.</p> 249 250<p>Any implemenation that creates a Path atom to transmit to another is 251responsible for ensuring it is valid. A Path SHOULD always be absolute, unless 252there is some mechanism in place that defines a base path. Since this is not 253the case for plugin instances, effectively any Path sent to or received from a 254plugin instance MUST be absolute.</p> 255""" . 256 257atom:URI 258 a rdfs:Class , 259 rdfs:Datatype ; 260 rdfs:subClassOf atom:String ; 261 owl:onDatatype xsd:anyURI ; 262 rdfs:label "URI string" ; 263 lv2:documentation """ 264<p>A URI string. This is useful when a URI is needed but mapping is 265inappropriate, for example with temporary or relative URIs. Since the ability 266to distinguish URIs from plain strings is often necessary, URIs MUST NOT be 267transmitted as atom:String.</p> 268 269<p>This is not strictly a URI, since UTF-8 is allowed. Escaping and related 270issues are the host's responsibility.</p> 271""" . 272 273atom:URID 274 a rdfs:Class ; 275 rdfs:subClassOf atom:Atom ; 276 rdfs:label "Integer URID" ; 277 atom:cType "LV2_Atom_URID" ; 278 lv2:documentation """ 279<p>An unsigned 32-bit integer mapped from a URI (e.g. with LV2_URID_Map).</p> 280""" . 281 282atom:Vector 283 a rdfs:Class ; 284 rdfs:subClassOf atom:Atom ; 285 rdfs:label "Vector" ; 286 atom:cType "LV2_Atom_Vector" ; 287 lv2:documentation """ 288<p>A homogeneous series of atom bodies with equivalent type and size.</p> 289 290<p>An LV2_Atom_Vector is a 32-bit <code>child_size</code> and 291<code>child_type</code> followed by <code>size / child_size</code> atom 292bodies.</p> 293 294<p>For example, an atom:Vector containing 42 elements of type atom:Float:</p> 295<pre class="c-code"> 296struct VectorOf42Floats { 297 uint32_t size; // sizeof(LV2_Atom_Vector_Body) + (42 * sizeof(float); 298 uint32_t type; // map(expand("atom:Vector")) 299 uint32_t child_size; // sizeof(float) 300 uint32_t child_type; // map(expand("atom:Float")) 301 float elems[42]; 302}; 303</pre> 304 305<p>Note that it is possible to construct a valid Atom for each element 306of the vector, even by an implementation which does not understand 307<code>child_type</code>.</p> 308 309<p>If serialised to RDF, a Vector SHOULD have the form:</p> 310 311<pre class="turtle-code"> 312eg:someVector 313 a atom:Vector ; 314 atom:childType atom:Int ; 315 rdf:value ( 316 "1"^^xsd:int 317 "2"^^xsd:int 318 "3"^^xsd:int 319 "4"^^xsd:int 320 ) . 321</pre> 322""" . 323 324atom:Tuple 325 a rdfs:Class ; 326 rdfs:subClassOf atom:Atom ; 327 rdfs:label "Tuple" ; 328 lv2:documentation """ 329<p>A series of Atoms with varying <code>type</code> and <code>size</code>.</p> 330 331<p>The body of a Tuple is simply a series of complete atoms, each aligned to 33264 bits.</p> 333 334<p>If serialised to RDF, a Tuple SHOULD have the form:</p> 335 336<pre class="turtle-code"> 337eg:someVector 338 a atom:Tuple ; 339 rdf:value ( 340 "1"^^xsd:int 341 "3.5"^^xsd:float 342 "etc" 343 ) . 344</pre> 345 346""" . 347 348atom:Property 349 a rdfs:Class ; 350 rdfs:subClassOf atom:Atom ; 351 rdfs:label "Property" ; 352 atom:cType "LV2_Atom_Property" ; 353 lv2:documentation """ 354<p>A property of an atom:Object. An LV2_Atom_Property has a URID 355<code>key</code> and <code>context</code>, and an Atom <code>value</code>. 356This corresponds to an RDF Property, where the <q>key</q> is the <q>predicate</q> 357and the <q>value</q> is the object.</p> 358 359<p>The <code>context</code> field can be used to specify a different context 360for each property, where this is useful. Otherwise, it may be 0.</p> 361 362<p>Properties generally only exist as part of an atom:Object. Accordingly, 363they will typically be represented directly as properties in RDF (see 364atom:Object). If this is not possible, they may be expressed as partial 365reified statements, e.g.:</p> 366 367<pre class="turtle-code"> 368eg:someProperty 369 rdf:predicate eg:theKey ; 370 rdf:object eg:theValue . 371</pre> 372""" . 373 374atom:Object 375 a rdfs:Class ; 376 rdfs:subClassOf atom:Atom ; 377 rdfs:label "Object" ; 378 atom:cType "LV2_Atom_Object" ; 379 lv2:documentation """ 380<p>An <q>Object</q> is an atom with a set of properties. This corresponds to 381an RDF Resource, and can be thought of as a dictionary with URID keys.</p> 382 383<p>An LV2_Atom_Object body has a uint32_t <code>id</code> and 384<code>type</code>, followed by a series of atom:Property bodies 385(LV2_Atom_Property_Body). The LV2_Atom_Object_Body::otype field is equivalent 386to a property with key rdf:type, but is included in the structure to allow for 387fast dispatching.</p> 388 389<p>Code SHOULD check for objects using lv2_atom_forge_is_object() or 390lv2_atom_forge_is_blank() if a forge is available, rather than checking the 391atom type directly. This will correctly handle the deprecated atom:Resource 392and atom:Blank types.</p> 393 394<p>When serialised to RDF, an Object is represented as a resource, e.g.:</p> 395 396<pre class="turtle-code"> 397eg:someObject 398 eg:firstPropertyKey "first property value" ; 399 eg:secondPropertyKey "first loser" ; 400 eg:andSoOn "and so on" . 401</pre> 402""" . 403 404atom:Resource 405 a rdfs:Class ; 406 rdfs:subClassOf atom:Object ; 407 rdfs:label "Resource" ; 408 owl:deprecated "true"^^xsd:boolean ; 409 atom:cType "LV2_Atom_Object" ; 410 lv2:documentation """ 411<p>This class is deprecated. Use atom:Object instead.</p> 412 413<p>An atom:Object where the <code>id</code> field is a URID, i.e. an Object 414with a URI.</p> 415""" . 416 417atom:Blank 418 a rdfs:Class ; 419 rdfs:subClassOf atom:Object ; 420 rdfs:label "Blank" ; 421 owl:deprecated "true"^^xsd:boolean ; 422 atom:cType "LV2_Atom_Object" ; 423 lv2:documentation """ 424<p>This class is deprecated. Use atom:Object with ID 0 instead.</p> 425 426<p>An atom:Object where the LV2_Atom_Object::id is a blank node ID (NOT a URI). 427The ID of a Blank is valid only within the context the Blank appears in. For 428ports this is the context of the associated run() call, i.e. all ports share 429the same context so outputs can contain IDs that correspond to IDs of blanks in 430the input.</p> 431""" . 432 433atom:Sound 434 a rdfs:Class ; 435 rdfs:subClassOf atom:Vector ; 436 rdfs:label "Sound" ; 437 atom:cType "LV2_Atom_Sound" ; 438 lv2:documentation """ 439<p>An atom:Vector of atom:Float which represents an audio waveform. The format 440is the same as the buffer format for lv2:AudioPort (except the size may be 441arbitrary). An atom:Sound inherently depends on the sample rate, which is 442assumed to be known from context. Because of this, directly serialising an 443atom:Sound is probably a bad idea, use a standard format like WAV instead.</p> 444""" . 445 446atom:frameTime 447 a rdf:Property , 448 owl:DatatypeProperty , 449 owl:FunctionalProperty ; 450 rdfs:range xsd:decimal ; 451 rdfs:label "frame time" ; 452 lv2:documentation """ 453<p>Time stamp in audio frames. Typically used for events.</p> 454""" . 455 456atom:beatTime 457 a rdf:Property , 458 owl:DatatypeProperty , 459 owl:FunctionalProperty ; 460 rdfs:range xsd:decimal ; 461 rdfs:label "beat time" ; 462 lv2:documentation """ 463<p>Time stamp in beats. Typically used for events.</p> 464""" . 465 466atom:Event 467 a rdfs:Class ; 468 rdfs:label "Event" ; 469 atom:cType "LV2_Atom_Event" ; 470 lv2:documentation """ 471<p>An atom with a time stamp prefix, typically an element of an atom:Sequence. 472Note this is not an Atom type.</p> 473""" . 474 475atom:Sequence 476 a rdfs:Class ; 477 rdfs:subClassOf atom:Atom ; 478 rdfs:label "Sequence" ; 479 atom:cType "LV2_Atom_Sequence" ; 480 lv2:documentation """ 481<p>A sequence of atom:Event, i.e. a series of time-stamped Atoms.</p> 482 483<p>LV2_Atom_Sequence_Body.unit describes the time unit for the contained atoms. 484If the unit is known from context (e.g. run() stamps are always audio frames), 485this field may be zero. Otherwise, it SHOULD be either units:frame or 486units:beat, in which case ev.time.frames or ev.time.beats is valid, 487respectively.</p> 488 489<p>If serialised to RDF, a Sequence has a similar form to atom:Vector, but for 490brevity the elements may be assumed to be atom:Event, e.g.:</p> 491 492<pre class="turtle-code"> 493eg:someSequence 494 a atom:Sequence ; 495 rdf:value ( 496 [ 497 atom:frameTime 1 ; 498 rdf:value "901A01"^^midi:MidiEvent 499 ] [ 500 atom:frameTime 3 ; 501 rdf:value "902B02"^^midi:MidiEvent 502 ] 503 ) . 504</pre> 505""" . 506 507atom:AtomPort 508 a rdfs:Class ; 509 rdfs:subClassOf lv2:Port ; 510 rdfs:label "Atom Port" ; 511 lv2:documentation """ 512<p>A port which contains an atom:Atom. Ports of this type are connected to an 513LV2_Atom with a type specified by atom:bufferType.</p> 514 515<p>Output ports with a variably sized type MUST be initialised by the host 516before every run() to an atom:Chunk with size set to the available space. The 517plugin reads this size to know how much space is available for writing. In all 518cases, the plugin MUST write a complete atom (including header) to outputs. 519However, to be robust, hosts SHOULD initialise output ports to a safe sentinel 520(e.g. the null Atom) before calling run().</p> 521""" . 522 523atom:bufferType 524 a rdf:Property , 525 owl:ObjectProperty ; 526 rdfs:domain atom:AtomPort ; 527 rdfs:range rdfs:Class ; 528 rdfs:label "buffer type" ; 529 lv2:documentation """ 530<p>Indicates that an AtomPort may be connected to a certain Atom type. A port 531MAY support several buffer types. The host MUST NOT connect a port to an Atom 532with a type not explicitly listed with this property. The value of this 533property MUST be a sub-class of atom:Atom. For example, an input port that is 534connected directly to an LV2_Atom_Double value is described like so:</p> 535 536<pre class="turtle-code"> 537<plugin> 538 lv2:port [ 539 a lv2:InputPort , atom:AtomPort ; 540 atom:bufferType atom:Double ; 541 ] . 542</pre> 543 544<p>This property only describes the types a port may be <em>directly</em> 545connected to. It says nothing about the expected contents of containers. For 546that, use atom:supports.</p> 547""" . 548 549atom:childType 550 a rdf:Property , 551 owl:ObjectProperty ; 552 rdfs:label "child type" ; 553 rdfs:comment "The type of a container's children." . 554 555atom:supports 556 a rdf:Property ; 557 rdfs:label "supports" ; 558 rdfs:range rdfs:Class ; 559 lv2:documentation """ 560<p>Indicates that a particular Atom type is supported.</p> 561 562<p>This property is defined loosely, it may be used to indicate that anything 563<q>supports</q> an Atom type, wherever that may be useful. It applies 564<q>recursively</q> where collections are involved.</p> 565 566<p>In particular, this property can be used to describe which event types are 567expected by a port. For example, a port that receives MIDI events is described 568like so:</p> 569 570<pre class="turtle-code"> 571<plugin> 572 lv2:port [ 573 a lv2:InputPort , atom:AtomPort ; 574 atom:bufferType atom:Sequence ; 575 atom:supports midi:MidiEvent ; 576 ] . 577</pre> 578""" . 579 580atom:eventTransfer 581 a ui:PortProtocol ; 582 rdfs:label "event transfer" ; 583 lv2:documentation """ 584<p>Transfer of individual events in a port buffer. Useful as the 585<code>format</code> for a LV2UI_Write_Function.</p> 586 587<p>This protocol applies to ports which contain events, usually in an 588atom:Sequence. The host must transfer each individual event to the recipient. 589The format of the received data is an LV2_Atom, there is no timestamp 590header.</p> 591""" . 592 593atom:atomTransfer 594 a ui:PortProtocol ; 595 rdfs:label "atom transfer" ; 596 lv2:documentation """ 597<p>Transfer of the complete atom in a port buffer. Useful as the 598<code>format</code> for a LV2UI_Write_Function.</p> 599 600<p>This protocol applies to atom ports. The host must transfer the complete 601atom contained in the port, including header.</p> 602""" . 603