1 /* 2 Copyright 2008-2016 David Robillard <http://drobilla.net> 3 Copyright 2018 Ethan Reker <http://cutthroughrecordings.com> 4 Copyright 2019 Guillaume Piolat <http://www.auburnsounds.com> 5 6 Permission to use, copy, modify, and/or distribute this software for any 7 purpose with or without fee is hereby granted, provided that the above 8 copyright notice and this permission notice appear in all copies. 9 10 THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 module dplug.lv2.atom; 19 20 version(LV2): 21 22 /** 23 @defgroup atom Atom 24 25 A generic value container and several data types, see 26 <http://lv2plug.in/ns/ext/atom> for details. 27 28 @{ 29 */ 30 31 import core.stdc.stdint; 32 import core.stdc.stddef; 33 import core.stdc.string; 34 35 36 enum LV2_ATOM_URI = "http://lv2plug.in/ns/ext/atom"; ///< http://lv2plug.in/ns/ext/atom 37 enum LV2_ATOM_PREFIX = LV2_ATOM_URI ~ "#"; ///< http://lv2plug.in/ns/ext/atom# 38 enum LV2_ATOM__Atom = LV2_ATOM_PREFIX ~ "Atom"; ///< http://lv2plug.in/ns/ext/atom#Atom 39 enum LV2_ATOM__AtomPort = LV2_ATOM_PREFIX ~ "AtomPort"; ///< http://lv2plug.in/ns/ext/atom#AtomPort 40 enum LV2_ATOM__Blank = LV2_ATOM_PREFIX ~ "Blank"; ///< http://lv2plug.in/ns/ext/atom#Blank 41 enum LV2_ATOM__Bool = LV2_ATOM_PREFIX ~ "Bool"; ///< http://lv2plug.in/ns/ext/atom#Bool 42 enum LV2_ATOM__Chunk = LV2_ATOM_PREFIX ~ "Chunk"; ///< http://lv2plug.in/ns/ext/atom#Chunk 43 enum LV2_ATOM__Double = LV2_ATOM_PREFIX ~ "Double"; ///< http://lv2plug.in/ns/ext/atom#Double 44 enum LV2_ATOM__Event = LV2_ATOM_PREFIX ~ "Event"; ///< http://lv2plug.in/ns/ext/atom#Event 45 enum LV2_ATOM__Float = LV2_ATOM_PREFIX ~ "Float"; ///< http://lv2plug.in/ns/ext/atom#Float 46 enum LV2_ATOM__Int = LV2_ATOM_PREFIX ~ "Int"; ///< http://lv2plug.in/ns/ext/atom#Int 47 enum LV2_ATOM__Literal = LV2_ATOM_PREFIX ~ "Literal"; ///< http://lv2plug.in/ns/ext/atom#Literal 48 enum LV2_ATOM__Long = LV2_ATOM_PREFIX ~ "Long"; ///< http://lv2plug.in/ns/ext/atom#Long 49 enum LV2_ATOM__Number = LV2_ATOM_PREFIX ~ "Number"; ///< http://lv2plug.in/ns/ext/atom#Number 50 enum LV2_ATOM__Object = LV2_ATOM_PREFIX ~ "Object"; ///< http://lv2plug.in/ns/ext/atom#Object 51 enum LV2_ATOM__Path = LV2_ATOM_PREFIX ~ "Path"; ///< http://lv2plug.in/ns/ext/atom#Path 52 enum LV2_ATOM__Property = LV2_ATOM_PREFIX ~ "Property"; ///< http://lv2plug.in/ns/ext/atom#Property 53 enum LV2_ATOM__Resource = LV2_ATOM_PREFIX ~ "Resource"; ///< http://lv2plug.in/ns/ext/atom#Resource 54 enum LV2_ATOM__Sequence = LV2_ATOM_PREFIX ~ "Sequence"; ///< http://lv2plug.in/ns/ext/atom#Sequence 55 enum LV2_ATOM__Sound = LV2_ATOM_PREFIX ~ "Sound"; ///< http://lv2plug.in/ns/ext/atom#Sound 56 enum LV2_ATOM__String = LV2_ATOM_PREFIX ~ "String"; ///< http://lv2plug.in/ns/ext/atom#String 57 enum LV2_ATOM__Tuple = LV2_ATOM_PREFIX ~ "Tuple"; ///< http://lv2plug.in/ns/ext/atom#Tuple 58 enum LV2_ATOM__URI = LV2_ATOM_PREFIX ~ "URI"; ///< http://lv2plug.in/ns/ext/atom#URI 59 enum LV2_ATOM__URID = LV2_ATOM_PREFIX ~ "URID"; ///< http://lv2plug.in/ns/ext/atom#URID 60 enum LV2_ATOM__Vector = LV2_ATOM_PREFIX ~ "Vector"; ///< http://lv2plug.in/ns/ext/atom#Vector 61 enum LV2_ATOM__atomTransfer= LV2_ATOM_PREFIX ~ "atomTransfer"; ///< http://lv2plug.in/ns/ext/atom#atomTransfer 62 enum LV2_ATOM__beatTime = LV2_ATOM_PREFIX ~ "beatTime"; ///< http://lv2plug.in/ns/ext/atom#beatTime 63 enum LV2_ATOM__bufferType = LV2_ATOM_PREFIX ~ "bufferType"; ///< http://lv2plug.in/ns/ext/atom#bufferType 64 enum LV2_ATOM__childType = LV2_ATOM_PREFIX ~ "childType"; ///< http://lv2plug.in/ns/ext/atom#childType 65 enum LV2_ATOM__eventTransfer = LV2_ATOM_PREFIX~ "eventTransfer"; ///< http://lv2plug.in/ns/ext/atom#eventTransfer 66 enum LV2_ATOM__frameTime = LV2_ATOM_PREFIX ~ "frameTime"; ///< http://lv2plug.in/ns/ext/atom#frameTime 67 enum LV2_ATOM__supports = LV2_ATOM_PREFIX ~ "supports"; ///< http://lv2plug.in/ns/ext/atom#supports 68 enum LV2_ATOM__timeUnit = LV2_ATOM_PREFIX ~ "timeUnit"; ///< http://lv2plug.in/ns/ext/atom#timeUnit 69 enum LV2_ATOM_REFERENCE_TYPE = 0; ///< The special type for a reference atom 70 71 extern(C) { 72 73 /** @cond */ 74 /** This expression will fail to compile if double does not fit in 64 bits. */ 75 // typedef char lv2_atom_assert_double_fits_in_64_bits[ 76 // ((sizeof(double) <= sizeof(uint64_t)) * 2) - 1]; 77 // alias lv2_atom_assert_double_fits_in_64_bits[((sizeof(double) <= sizeof(uint64_t)) * 2) - 1] = char; 78 /** @endcond */ 79 80 /** 81 Return a pointer to the contents of an Atom. The "contents" of an atom 82 is the data past the complete type-specific header. 83 @param type The type of the atom, e.g. LV2_Atom_String. 84 @param atom A variable-sized atom. 85 */ 86 // #define LV2_ATOM_CONTENTS(type, atom) \ 87 // ((void*)((uint8_t*)(atom) + sizeof(type))) 88 void* LV2_ATOM_CONTENTS(alias type)(LV2_Atom* atom) 89 { 90 return cast(void*)(cast(uint8_t*)(cast(void*)atom) + type.sizeof); 91 } 92 93 // /** 94 // Const version of LV2_ATOM_CONTENTS. 95 // */ 96 // #define LV2_ATOM_CONTENTS_CONST(type, atom) \ 97 // ((const void*)((const uint8_t*)(atom) + sizeof(type))) 98 template LV2_ATOM_CONTENTS_CONST(alias type, alias atom) 99 { 100 auto LV2_ATOM_CONTENTS_CONST = (cast(const void*)(cast(const uint8_t*)(atom) + sizeof(type))); 101 } 102 103 /** 104 Return a pointer to the body of an Atom. The "body" of an atom is the 105 data just past the LV2_Atom head (i.e. the same offset for all types). 106 */ 107 108 void* LV2_ATOM_BODY(LV2_Atom* atom) nothrow @nogc 109 { 110 return LV2_ATOM_CONTENTS!LV2_Atom(atom); 111 } 112 113 114 /** 115 Const version of LV2_ATOM_BODY. 116 */ 117 // #define LV2_ATOM_BODY_CONST(atom) LV2_ATOM_CONTENTS_CONST(LV2_Atom, atom) 118 alias LV2_ATOM_BODY_CONST(atom) = LV2_ATOM_CONTENTS_CONST!(LV2_Atom, atom); 119 120 121 /** The header of an atom:Atom. */ 122 struct LV2_Atom { 123 uint32_t size; /**< Size in bytes, not including type and size. */ 124 uint32_t type; /**< Type of this atom (mapped URI). */ 125 } 126 127 /** An atom:Int or atom:Bool. May be cast to LV2_Atom. */ 128 struct LV2_Atom_Int { 129 LV2_Atom atom; /**< Atom header. */ 130 int32_t body_; /**< Integer value. */ 131 } 132 133 /** An atom:Long. May be cast to LV2_Atom. */ 134 struct LV2_Atom_Long { 135 LV2_Atom atom; /**< Atom header. */ 136 int64_t body_; /**< Integer value. */ 137 } 138 139 /** An atom:Float. May be cast to LV2_Atom. */ 140 struct LV2_Atom_Float { 141 LV2_Atom atom; /**< Atom header. */ 142 float body_; /**< Floating point value. */ 143 } 144 145 /** An atom:Double. May be cast to LV2_Atom. */ 146 struct LV2_Atom_Double { 147 LV2_Atom atom; /**< Atom header. */ 148 double body_; /**< Floating point value. */ 149 } 150 151 /** An atom:Bool. May be cast to LV2_Atom. */ 152 alias LV2_Atom_Bool = LV2_Atom_Int; 153 154 /** An atom:URID. May be cast to LV2_Atom. */ 155 struct LV2_Atom_URID { 156 LV2_Atom atom; /**< Atom header. */ 157 uint32_t body_; /**< URID. */ 158 } 159 160 /** An atom:String. May be cast to LV2_Atom. */ 161 struct LV2_Atom_String { 162 LV2_Atom atom; /**< Atom header. */ 163 /* Contents (a null-terminated UTF-8 string) follow here. */ 164 } 165 166 /** The body of an atom:Literal. */ 167 struct LV2_Atom_Literal_Body { 168 uint32_t datatype; /**< Datatype URID. */ 169 uint32_t lang; /**< Language URID. */ 170 /* Contents (a null-terminated UTF-8 string) follow here. */ 171 } 172 173 /** An atom:Literal. May be cast to LV2_Atom. */ 174 struct LV2_Atom_Literal { 175 LV2_Atom atom; /**< Atom header. */ 176 LV2_Atom_Literal_Body body_; /**< Body. */ 177 } 178 179 /** An atom:Tuple. May be cast to LV2_Atom. */ 180 struct LV2_Atom_Tuple { 181 LV2_Atom atom; /**< Atom header. */ 182 /* Contents (a series of complete atoms) follow here. */ 183 } 184 185 /** The body of an atom:Vector. */ 186 struct LV2_Atom_Vector_Body { 187 uint32_t child_size; /**< The size of each element in the vector. */ 188 uint32_t child_type; /**< The type of each element in the vector. */ 189 /* Contents (a series of packed atom bodies) follow here. */ 190 } 191 192 /** An atom:Vector. May be cast to LV2_Atom. */ 193 struct LV2_Atom_Vector { 194 LV2_Atom atom; /**< Atom header. */ 195 LV2_Atom_Vector_Body body_; /**< Body. */ 196 } 197 198 /** The body of an atom:Property (e.g. in an atom:Object). */ 199 struct LV2_Atom_Property_Body { 200 uint32_t key; /**< Key (predicate) (mapped URI). */ 201 uint32_t context; /**< Context URID (may be, and generally is, 0). */ 202 LV2_Atom value; /**< Value atom header. */ 203 /* Value atom body follows here. */ 204 } 205 206 /** An atom:Property. May be cast to LV2_Atom. */ 207 struct LV2_Atom_Property { 208 LV2_Atom atom; /**< Atom header. */ 209 LV2_Atom_Property_Body body_; /**< Body. */ 210 } 211 212 /** The body of an atom:Object. May be cast to LV2_Atom. */ 213 struct LV2_Atom_Object_Body { 214 uint32_t id; /**< URID, or 0 for blank. */ 215 uint32_t otype; /**< Type URID (same as rdf:type, for fast dispatch). */ 216 /* Contents (a series of property bodies) follow here. */ 217 } 218 219 /** An atom:Object. May be cast to LV2_Atom. */ 220 struct LV2_Atom_Object { 221 LV2_Atom atom; /**< Atom header. */ 222 LV2_Atom_Object_Body body_; /**< Body. */ 223 } 224 225 /** The header of an atom:Event. Note this type is NOT an LV2_Atom. */ 226 struct LV2_Atom_Event { 227 /** Time stamp. Which type is valid is determined by context. */ 228 union Time { 229 int64_t frames; /**< Time in audio frames. */ 230 double beats; /**< Time in beats. */ 231 } 232 Time time; 233 LV2_Atom body_; /**< Event body atom header. */ 234 /* Body atom contents follow here. */ 235 } 236 237 /** 238 The body of an atom:Sequence (a sequence of events). 239 240 The unit field is either a URID that described an appropriate time stamp 241 type, or may be 0 where a default stamp type is known. For 242 LV2_Descriptor::run(), the default stamp type is audio frames. 243 244 The contents of a sequence is a series of LV2_Atom_Event, each aligned 245 to 64-bits, e.g.: 246 <pre> 247 | Event 1 (size 6) | Event 2 248 | | | | | | | | | 249 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 250 |FRAMES |SUBFRMS|TYPE |SIZE |DATADATADATAPAD|FRAMES |SUBFRMS|... 251 </pre> 252 */ 253 struct LV2_Atom_Sequence_Body { 254 uint32_t unit; /**< URID of unit of event time stamps. */ 255 uint32_t pad; /**< Currently unused. */ 256 /* Contents (a series of events) follow here. */ 257 } 258 259 /** An atom:Sequence. */ 260 struct LV2_Atom_Sequence { 261 LV2_Atom atom; /**< Atom header. */ 262 LV2_Atom_Sequence_Body body_; /**< Body. */ 263 } 264 265 } 266 267 268 nothrow: 269 @nogc: 270 271 /** Pad a size to 64 bits. */ 272 uint32_t lv2_atom_pad_size(uint32_t size) 273 { 274 return (size + 7U) & (~7U); 275 } 276 277 /** Get an iterator pointing to the first event in a Sequence body. */ 278 LV2_Atom_Event* lv2_atom_sequence_begin(const LV2_Atom_Sequence_Body* body_) 279 { 280 return cast(LV2_Atom_Event*)(body_ + 1); 281 } 282 283 /** Get an iterator pointing to the end of a Sequence body. */ 284 LV2_Atom_Event* lv2_atom_sequence_end(const LV2_Atom_Sequence_Body* body_, uint32_t size) 285 { 286 return cast(LV2_Atom_Event*)(cast(const uint8_t*)body_ + lv2_atom_pad_size(size)); 287 } 288 289 /** Return true iff `i` has reached the end of `body`. */ 290 bool lv2_atom_sequence_is_end(const LV2_Atom_Sequence_Body* body_, 291 uint32_t size, 292 const LV2_Atom_Event* i) 293 { 294 return cast(const uint8_t*)i >= (cast(const uint8_t*)body_ + size); 295 } 296 297 /** Return an iterator to the element following `i`. */ 298 LV2_Atom_Event* lv2_atom_sequence_next(const LV2_Atom_Event* i) 299 { 300 return cast(LV2_Atom_Event*)(cast(const uint8_t*)i 301 + LV2_Atom_Event.sizeof 302 + lv2_atom_pad_size(i.body_.size)); 303 } 304 305 306 /** Return a pointer to the first property in `body`. */ 307 LV2_Atom_Property_Body* lv2_atom_object_begin(const LV2_Atom_Object_Body* body_) 308 { 309 return cast(LV2_Atom_Property_Body*)(body_ + 1); 310 } 311 312 /** Return true iff `i` has reached the end of `obj`. */ 313 bool lv2_atom_object_is_end(const LV2_Atom_Object_Body* body_, 314 uint32_t size, 315 const LV2_Atom_Property_Body* i) 316 { 317 return cast(const uint8_t*)i >= (cast(const uint8_t*)body_ + size); 318 } 319 320 /** Return an iterator to the property following `i`. */ 321 LV2_Atom_Property_Body* lv2_atom_object_next(const LV2_Atom_Property_Body* i) 322 { 323 const (LV2_Atom*) value = cast(const LV2_Atom*)( 324 cast(const uint8_t*)i + 2 * uint32_t.sizeof); 325 return cast(LV2_Atom_Property_Body*)( 326 cast(const uint8_t*)i + lv2_atom_pad_size( 327 cast(uint32_t)LV2_Atom_Property_Body.sizeof + value.size)); 328 }