Some Atom handling refactoring
Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
This commit is contained in:
		
							parent
							
								
									d39cea5a98
								
							
						
					
					
						commit
						11c9fc653d
					
				| @ -29,7 +29,7 @@ proc instantiate(descriptor: ptr Lv2Descriptor; sampleRate: cdouble; | ||||
|     if amp.map == nil: | ||||
|         return nil | ||||
| 
 | ||||
|     amp.midi_urid = amp.map[].map(amp.map[].handle, lv2MidiMidiEvent) | ||||
|     amp.midi_urid = amp.map.map(amp.map.handle, lv2MidiMidiEvent) | ||||
| 
 | ||||
|     return cast[Lv2Handle](amp) | ||||
| 
 | ||||
| @ -56,17 +56,17 @@ proc run(instance: Lv2Handle; nSamples: cuint) {.cdecl.} = | ||||
|     atomSequenceClear(amp.output) | ||||
|     amp.output.atom.type = amp.input.atom.type | ||||
| 
 | ||||
|     if amp.input.atom.size > 8: | ||||
|     if not atomSequenceIsEmpty(amp.input): | ||||
|         #echo &"Event sequence size: {amp.input.atom.size}" | ||||
|         let noteOffset = clamp(floor(amp.transposition[] + 0.5), -12, 12).uint8 | ||||
| 
 | ||||
|         for ev in items(amp.input): | ||||
|             if Urid(ev.body.`type`) == amp.midi_urid: | ||||
|         for ev in amp.input: | ||||
|             if ev.body.`type` == amp.midi_urid: | ||||
|                 var msg = cast[ptr UncheckedArray[uint8]](atomContents(AtomEvent, ev)) | ||||
|                 #echo &"0x{toHex(msg[0], 2)} 0x{toHex(msg[1], 2)} 0x{toHex(msg[2], 2)}" | ||||
| 
 | ||||
|                 case midiGetMessageType(msg[]): | ||||
|                 of midiMsgNoteOff, midiMsgNoteOn, midiMsgNotePressure: | ||||
|                     let noteOffset = clamp(floor(amp.transposition[] + 0.5), -12, 12).uint8 | ||||
|                     msg[1] = clamp(msg[1] + noteOffset, 0, 127).uint8 | ||||
|                 else: | ||||
|                     discard | ||||
|  | ||||
| @ -7,6 +7,7 @@ | ||||
| ## | ||||
| 
 | ||||
| import ptrmath | ||||
| import urid | ||||
| 
 | ||||
| const | ||||
|     lv2AtomBaseUri ="http://lv2plug.in/ns/ext/atom" | ||||
| @ -64,7 +65,7 @@ type | ||||
|     ## The header of an atom:Atom. | ||||
|     Atom* {.bycopy.} = object | ||||
|         size*: uint32  ## Size in bytes, not including type and size. | ||||
|         `type`*: uint32  ## of this atom (mapped URI). | ||||
|         `type`*: Urid  ## Type of this atom (mapped URI). | ||||
| 
 | ||||
|     ## An atom:Int or atom:Bool.  May be cast to Atom. | ||||
|     AtomInt* {.bycopy.} = object | ||||
| @ -92,7 +93,7 @@ type | ||||
|     ## An atom:URID.  May be cast to Atom. | ||||
|     AtomUrid* {.bycopy.} = object | ||||
|         atom*: Atom  ## Atom header. | ||||
|         body*: uint32  ## URID. | ||||
|         body*: Urid  ## Urid. | ||||
| 
 | ||||
|     ## An atom:String.  May be cast to Atom. | ||||
|     AtomString* {.bycopy.} = object | ||||
| @ -101,8 +102,8 @@ type | ||||
| 
 | ||||
|     ## The body of an atom:Literal. | ||||
|     AtomLiteralBody* {.bycopy.} = object | ||||
|         datatype*: uint32  ## DataURID. | ||||
|         lang*: uint32  ## Language URID. | ||||
|         datatype*: Urid  ## Datatype Urid. | ||||
|         lang*: Urid  ## Language Urid. | ||||
|         ## Contents (a null-terminated UTF-8 string) follow here. | ||||
| 
 | ||||
|     ## An atom:Literal.  May be cast to Atom. | ||||
| @ -128,8 +129,8 @@ type | ||||
| 
 | ||||
|     ## The body of an atom:Property (typically in an atom:Object). | ||||
|     AtomPropertyBody* {.bycopy.} = object | ||||
|         key*: uint32  ## Key (predicate) (mapped URI). | ||||
|         context*: uint32  ## Context URID (may be, and generally is, 0). | ||||
|         key*: Urid  ## Key (predicate) (mapped URI). | ||||
|         context*: Urid  ## Context URID (may be, and generally is, 0). | ||||
|         value*: Atom  ## Value atom header. | ||||
|         ## Value atom body follows here. | ||||
| 
 | ||||
| @ -140,8 +141,8 @@ type | ||||
| 
 | ||||
|     ## The body of an atom:Object. May be cast to Atom. | ||||
|     AtomObjectBody* {.bycopy.} = object | ||||
|         id*: uint32  ## URID, or 0 for blank. | ||||
|         otype*: uint32  ## URID (same as rdf:type, for fast dispatch). | ||||
|         id*: Urid  ## Urid, or 0 for blank. | ||||
|         otype*: Urid  ## Urid (same as rdf:type, for fast dispatch). | ||||
|         ## Contents (a series of property bodies) follow here. | ||||
| 
 | ||||
|     ## An atom:Object.  May be cast to Atom. | ||||
| @ -176,7 +177,7 @@ type | ||||
|     ## </pre> | ||||
|     ## | ||||
|     AtomSequenceBody* {.bycopy.} = object | ||||
|         unit*: uint32  ## URID of unit of event time stamps. | ||||
|         unit*: Urid  ## Urid of unit of event time stamps. | ||||
|         pad*: uint32  ## Currently unused. | ||||
|         ## Contents (a series of events) follow here. | ||||
| 
 | ||||
|  | ||||
| @ -13,6 +13,7 @@ | ||||
| from system/ansi_c import c_memcmp, c_memcpy | ||||
| import ../atom | ||||
| import ../ptrmath | ||||
| import ../urid | ||||
| 
 | ||||
| ## | ||||
| ## Pad a size to 64 bits. | ||||
| @ -31,7 +32,7 @@ proc atomTotalSize*(atom: ptr Atom): uint32 {.inline.} = | ||||
| ## Return true iff `atom` is null. | ||||
| ## | ||||
| proc atomIsNull*(atom: ptr Atom): bool {.inline.} = | ||||
|     return atom == nil or (atom.`type` == 0 and atom.size == 0) | ||||
|     return atom == nil or (atom.`type` == Urid(0) and atom.size == 0) | ||||
| 
 | ||||
| ## | ||||
| ## Return true iff `a` is equal to `b`. | ||||
| @ -46,31 +47,30 @@ proc atomEquals*(a: ptr Atom; b: ptr Atom): bool {.inline.} = | ||||
| ## | ||||
| ## Get an iterator pointing to the first event in a Sequence body. | ||||
| ## | ||||
| proc atomSequenceBegin*(body: ptr AtomSequenceBody): ptr AtomEvent {.inline.} = | ||||
|     return cast[ptr AtomEvent](body + 1) | ||||
| 
 | ||||
| template atomSequenceBegin*(body: ptr AtomSequenceBody): ptr AtomEvent = | ||||
|     cast[ptr AtomEvent](body + 1) | ||||
| 
 | ||||
| ## | ||||
| ## Get an iterator pointing to the end of a Sequence body. | ||||
| ## | ||||
| proc atomSequenceEnd*(body: ptr AtomSequenceBody; size: uint32): ptr AtomEvent {.inline.} = | ||||
|     return cast[ptr AtomEvent](cast[ptr uint8](body) + atomPadSize(size)) | ||||
| template atomSequenceEnd*(body: ptr AtomSequenceBody; size: Natural): ptr AtomEvent = | ||||
|     cast[ptr AtomEvent](cast[ptr uint8](body) + atomPadSize(size.uint32)) | ||||
| 
 | ||||
| ## | ||||
| ## Return true iff `i` has reached the end of `body`. | ||||
| ## | ||||
| proc atomSequenceIsEnd*(body: ptr AtomSequenceBody; size: Natural; i: ptr AtomEvent): bool {.inline.} = | ||||
|     return cast[ptr uint8](i) >= (cast[ptr uint8](body) + size.uint) | ||||
| template atomSequenceIsEnd*(body: ptr AtomSequenceBody; size: Natural; i: ptr AtomEvent): bool = | ||||
|     cast[ptr uint8](i) >= (cast[ptr uint8](body) + size.uint) | ||||
| 
 | ||||
| ## | ||||
| ## Return an iterator to the element following `i`. | ||||
| ## | ||||
| proc atomSequenceNext*(i: ptr AtomEvent): ptr AtomEvent {.inline.} = | ||||
|     return cast[ptr AtomEvent](cast[ptr uint8](i) + sizeof(AtomEvent) + atomPadSize(i.body.size)) | ||||
| template atomSequenceNext*(i: ptr AtomEvent): ptr AtomEvent = | ||||
|     cast[ptr AtomEvent](cast[ptr uint8](i) + sizeof(AtomEvent) + atomPadSize(i.body.size)) | ||||
| 
 | ||||
| ## | ||||
| ## An iterator for looping over all events in a Sequence. | ||||
| ## @param seq  The sequence to iterate over | ||||
| ## An iterator for looping over all events in an AtomSequence. | ||||
| ## @param seq  Pointer to the sequence to iterate over | ||||
| ## | ||||
| iterator items*(seq: ptr AtomSequence): ptr AtomEvent {.inline.} = | ||||
|     var event = atomSequenceBegin(seq.body.addr) | ||||
| @ -78,11 +78,28 @@ iterator items*(seq: ptr AtomSequence): ptr AtomEvent {.inline.} = | ||||
|         yield event | ||||
|         event = atomSequenceNext(event) | ||||
| 
 | ||||
| ## TODO: Like LV2_ATOM_SEQUENCE_FOREACH but for a headerless sequence body. | ||||
| ##  | ||||
| ## An iterator for looping over all events in an AtomSequenceBody. | ||||
| ## @param body  Pointer to the sequence body to iterate over | ||||
| ## @param size  Size in bytes of the sequence body (including the 8 bytes of AtomSequenceBody) | ||||
| ##  | ||||
| iterator items*(body: ptr AtomSequenceBody, size: Natural): ptr AtomEvent {.inline.} = | ||||
|     var event = atomSequenceBegin(body) | ||||
|     while not atomSequenceIsEnd(body, size, event): | ||||
|         yield event | ||||
|         event = atomSequenceNext(event) | ||||
| 
 | ||||
| ## | ||||
| ## Sequence Utilities | ||||
| ## | ||||
| 
 | ||||
| ## | ||||
| ## Test if AtomSequence is empty, i.e the body has no events | ||||
| ## | ||||
| template atomSequenceIsEmpty*(seq: ptr AtomSequence): bool = | ||||
|     seq.atom.size == sizeof(AtomSequenceBody).uint32 | ||||
| 
 | ||||
| ## | ||||
| ## Clear all events from `sequence`. | ||||
| ## | ||||
| ## This simply resets the size field, the other fields are left untouched. | ||||
| @ -118,48 +135,60 @@ proc atomSequenceAppendEvent*(seq: ptr AtomSequence; capacity: uint32; | ||||
| ## | ||||
| ## Get an iterator pointing to the first element in `tup`. | ||||
| ## | ||||
| proc atomTupleBegin*(tup: ptr AtomTuple): ptr Atom {.inline.} = | ||||
|     return cast[ptr Atom](atomContents(Atom, tup)) | ||||
| template atomTupleBegin*(tup: ptr AtomTuple): ptr Atom = | ||||
|     cast[ptr Atom](atomContents(Atom, tup)) | ||||
| 
 | ||||
| ## | ||||
| ## Return true iff `i` has reached the end of `body`. | ||||
| ## | ||||
| proc atomTupleIsEnd*(body: pointer; size: Natural; i: ptr Atom): bool {.inline.} = | ||||
|     return cast[ptr uint8](i) >= (cast[ptr uint8](body) + size.int) | ||||
| template atomTupleIsEnd*(body: pointer; size: Natural; i: ptr Atom): bool = | ||||
|     cast[ptr uint8](i) >= (cast[ptr uint8](body) + size.uint) | ||||
| 
 | ||||
| ## | ||||
| ## Return an iterator to the element following `i`. | ||||
| ## | ||||
| proc atomTupleNext*(i: ptr Atom): ptr Atom {.inline.} = | ||||
|     return cast[ptr Atom](cast[ptr uint8](i) + sizeof(Atom) + atomPadSize(i.size)) | ||||
| template atomTupleNext*(i: ptr Atom): ptr Atom = | ||||
|     cast[ptr Atom](cast[ptr uint8](i) + sizeof(Atom) + atomPadSize(i.size)) | ||||
| 
 | ||||
| 
 | ||||
| ## TODO: | ||||
| ## | ||||
| ## A iterator for looping over all properties of a Tuple. | ||||
| ## @param tuple The tuple to iterate over | ||||
| ## An iterator for looping over all elements of an AtomTuple. | ||||
| ## @param tuple Pointer to the tuple to iterate over | ||||
| ## | ||||
| iterator items*(tup: ptr AtomTuple): ptr Atom {.inline.} = | ||||
|     var atom = atomTupleBegin(tup) | ||||
|     while not atomTupleIsEnd(atomBody(tup), tup.atom.size, atom): | ||||
|         yield atom | ||||
|         atom = atomTupleNext(atom) | ||||
| 
 | ||||
| ## TODO:  | ||||
| ## Like LV2_ATOM_TUPLE_FOREACH but for a headerless tuple body. | ||||
| ## | ||||
| ## An iterator for looping over all elements of a headerless tuple. | ||||
| ## @param tuple Pointer to the first Atom of the tuple to iterate over | ||||
| ## @param size  Size in bytes of the tuple body | ||||
| ## | ||||
| iterator items*(tup: ptr Atom, size: Natural): ptr Atom {.inline.} = | ||||
|     var atom = tup | ||||
|     while not atomTupleIsEnd(tup, size, atom): | ||||
|         yield atom | ||||
|         atom = atomTupleNext(atom) | ||||
| 
 | ||||
| ## | ||||
| ## Object Iterator | ||||
| ## | ||||
| ## Return a pointer to the first property in `body`. | ||||
| ## | ||||
| proc atomObjectBegin*(body: ptr AtomObjectBody): ptr AtomPropertyBody {.inline.} = | ||||
|     return cast[ptr AtomPropertyBody](body + 1) | ||||
| template atomObjectBegin*(body: ptr AtomObjectBody): ptr AtomPropertyBody = | ||||
|     cast[ptr AtomPropertyBody](body + 1) | ||||
| 
 | ||||
| ## | ||||
| ## Return true iff `i` has reached the end of `obj`. | ||||
| ## | ||||
| proc atomObjectIsEnd*(body: ptr AtomObjectBody; size: Natural; i: ptr AtomPropertyBody): bool {.inline.} = | ||||
|     return cast[ptr uint8](i) >= (cast[ptr uint8](body) + size.int) | ||||
| template atomObjectIsEnd*(body: ptr AtomObjectBody; size: Natural; i: ptr AtomPropertyBody): bool = | ||||
|     cast[ptr uint8](i) >= (cast[ptr uint8](body) + size.uint) | ||||
| 
 | ||||
| ## | ||||
| ## Return an iterator to the property following `i`. | ||||
| ## | ||||
| proc atomObjectNext*(i: ptr AtomPropertyBody): ptr AtomPropertyBody {.inline.} = | ||||
| template atomObjectNext*(i: ptr AtomPropertyBody): ptr AtomPropertyBody = | ||||
|     let value = cast[ptr Atom](cast[ptr uint8](i) + 2 * sizeof(uint32)) | ||||
|     return cast[ptr AtomPropertyBody](cast[ptr uint8](i) + atomPadSize(sizeof(AtomPropertyBody).uint32 + value.size)) | ||||
| 
 | ||||
|  | ||||
| @ -14,81 +14,82 @@ const | ||||
|     lv2UridMap* = lv2UridPrefix & "map" | ||||
|     lv2UridUnmap* = lv2UridPrefix & "unmap" | ||||
| 
 | ||||
| ## | ||||
| ## Opaque pointer to host data for UridMap. | ||||
| ## | ||||
| type UridMapHandle* = pointer | ||||
| type | ||||
|     ## | ||||
|     ## URI mapped to an integer. | ||||
|     ## | ||||
|     Urid* = distinct uint32 | ||||
| 
 | ||||
| ## | ||||
| ## Opaque pointer to host data for uridUnmap. | ||||
| ## | ||||
| type UridUnmapHandle* = pointer | ||||
|     ## | ||||
|     ## Opaque pointer to host data for UridMap. | ||||
|     ## | ||||
|     UridMapHandle* = pointer | ||||
| 
 | ||||
| ## | ||||
| ## URI mapped to an integer. | ||||
| ## | ||||
| type Urid* = distinct uint32 | ||||
|     ## | ||||
|     ## Opaque pointer to host data for uridUnmap. | ||||
|     ## | ||||
|     UridUnmapHandle* = pointer | ||||
| 
 | ||||
| ## | ||||
| ## URID Map Feature (lv2UridMap) | ||||
| ## | ||||
| type UridMap* {.bycopy.} = object | ||||
|     ## | ||||
|     ## Opaque pointer to host data. | ||||
|     ## URID Map Feature (lv2UridMap) | ||||
|     ## | ||||
|     ## This MUST be passed to map_uri() whenever it is called. | ||||
|     ## Otherwise, it must not be interpreted in any way. | ||||
|     ## | ||||
|     handle*: UridMapHandle | ||||
|     ## | ||||
|     ## Get the numeric ID of a URI. | ||||
|     ## | ||||
|     ## If the ID does not already exist, it will be created. | ||||
|     ## | ||||
|     ## This function is referentially transparent; any number of calls with the | ||||
|     ## same arguments is guaranteed to return the same value over the life of a | ||||
|     ## plugin instance.  Note, however, that several URIs MAY resolve to the | ||||
|     ## same ID if the host considers those URIs equivalent. | ||||
|     ## | ||||
|     ## This function is not necessarily very fast or RT-safe: plugins SHOULD | ||||
|     ## cache any IDs they might need in performance critical situations. | ||||
|     ## | ||||
|     ## The return value 0 is reserved and indicates that an ID for that URI | ||||
|     ## could not be created for whatever reason.  However, hosts SHOULD NOT | ||||
|     ## return 0 from this function in non-exceptional circumstances (i.e. the | ||||
|     ## URI map SHOULD be dynamic). | ||||
|     ## | ||||
|     ## @param handle Must be the callback_data member of this struct. | ||||
|     ## @param uri The URI to be mapped to an integer ID. | ||||
|     ## | ||||
|     map*: proc (handle: UridMapHandle; uri: cstring): Urid | ||||
|     UridMap* {.bycopy.} = object | ||||
|         ## | ||||
|         ## Opaque pointer to host data. | ||||
|         ## | ||||
|         ## This MUST be passed to map_uri() whenever it is called. | ||||
|         ## Otherwise, it must not be interpreted in any way. | ||||
|         ## | ||||
|         handle*: UridMapHandle | ||||
|         ## | ||||
|         ## Get the numeric ID of a URI. | ||||
|         ## | ||||
|         ## If the ID does not already exist, it will be created. | ||||
|         ## | ||||
|         ## This function is referentially transparent; any number of calls with the | ||||
|         ## same arguments is guaranteed to return the same value over the life of a | ||||
|         ## plugin instance.  Note, however, that several URIs MAY resolve to the | ||||
|         ## same ID if the host considers those URIs equivalent. | ||||
|         ## | ||||
|         ## This function is not necessarily very fast or RT-safe: plugins SHOULD | ||||
|         ## cache any IDs they might need in performance critical situations. | ||||
|         ## | ||||
|         ## The return value 0 is reserved and indicates that an ID for that URI | ||||
|         ## could not be created for whatever reason.  However, hosts SHOULD NOT | ||||
|         ## return 0 from this function in non-exceptional circumstances (i.e. the | ||||
|         ## URI map SHOULD be dynamic). | ||||
|         ## | ||||
|         ## @param handle Must be the callback_data member of this struct. | ||||
|         ## @param uri The URI to be mapped to an integer ID. | ||||
|         ## | ||||
|         map*: proc (handle: UridMapHandle; uri: cstring): Urid | ||||
| 
 | ||||
| ## | ||||
| ## URI Unmap Feature (lv2UridUnmap) | ||||
| ## | ||||
| type UridUnmap* {.bycopy.} = object | ||||
|     ## | ||||
|     ## Opaque pointer to host data. | ||||
|     ## URI Unmap Feature (lv2UridUnmap) | ||||
|     ## | ||||
|     ## This MUST be passed to unmap() whenever it is called. | ||||
|     ## Otherwise, it must not be interpreted in any way. | ||||
|     ## | ||||
|     handle*: UridUnmapHandle | ||||
|     ## | ||||
|     ## Get the URI for a previously mapped numeric ID. | ||||
|     ## | ||||
|     ## Returns NULL if `urid` is not yet mapped.  Otherwise, the corresponding | ||||
|     ## URI is returned in a canonical form.  This MAY not be the exact same | ||||
|     ## string that was originally passed to LV2_URID_Map::map(), but it MUST be | ||||
|     ## an identical URI according to the URI syntax specification (RFC3986).  A | ||||
|     ## non-NULL return for a given `urid` will always be the same for the life | ||||
|     ## of the plugin.  Plugins that intend to perform string comparison on | ||||
|     ## unmapped URIs SHOULD first canonicalise URI strings with a call to | ||||
|     ## map_uri() followed by a call to unmap_uri(). | ||||
|     ## | ||||
|     ## @param handle Must be the callback_data member of this struct. | ||||
|     ## @param urid The ID to be mapped back to the URI string. | ||||
|     ## | ||||
|     unmap*: proc (handle: UridUnmapHandle; urid: Urid): cstring | ||||
|     UridUnmap* {.bycopy.} = object | ||||
|         ## | ||||
|         ## Opaque pointer to host data. | ||||
|         ## | ||||
|         ## This MUST be passed to unmap() whenever it is called. | ||||
|         ## Otherwise, it must not be interpreted in any way. | ||||
|         ## | ||||
|         handle*: UridUnmapHandle | ||||
|         ## | ||||
|         ## Get the URI for a previously mapped numeric ID. | ||||
|         ## | ||||
|         ## Returns NULL if `urid` is not yet mapped.  Otherwise, the corresponding | ||||
|         ## URI is returned in a canonical form.  This MAY not be the exact same | ||||
|         ## string that was originally passed to LV2_URID_Map::map(), but it MUST be | ||||
|         ## an identical URI according to the URI syntax specification (RFC3986).  A | ||||
|         ## non-NULL return for a given `urid` will always be the same for the life | ||||
|         ## of the plugin.  Plugins that intend to perform string comparison on | ||||
|         ## unmapped URIs SHOULD first canonicalise URI strings with a call to | ||||
|         ## map_uri() followed by a call to unmap_uri(). | ||||
|         ## | ||||
|         ## @param handle Must be the callback_data member of this struct. | ||||
|         ## @param urid The ID to be mapped back to the URI string. | ||||
|         ## | ||||
|         unmap*: proc (handle: UridUnmapHandle; urid: Urid): cstring | ||||
| 
 | ||||
| proc `==`* (x: Urid, y: Urid): bool {.borrow.} | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user