diff options
Diffstat (limited to 'libs/ardour/lv2/lv2plug.in/ns/ext/atom/forge.h')
-rw-r--r-- | libs/ardour/lv2/lv2plug.in/ns/ext/atom/forge.h | 618 |
1 files changed, 0 insertions, 618 deletions
diff --git a/libs/ardour/lv2/lv2plug.in/ns/ext/atom/forge.h b/libs/ardour/lv2/lv2plug.in/ns/ext/atom/forge.h deleted file mode 100644 index ea5977e500..0000000000 --- a/libs/ardour/lv2/lv2plug.in/ns/ext/atom/forge.h +++ /dev/null @@ -1,618 +0,0 @@ -/* - Copyright 2008-2012 David Robillard <http://drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/** - @file forge.h An API for constructing LV2 atoms. - - This file provides an API for constructing Atoms which makes it relatively - simple to build nested atoms of arbitrary complexity without requiring - dynamic memory allocation. - - The API is based on successively appending the appropriate pieces to build a - complete Atom. The size of containers is automatically updated. Functions - that begin a container return (via their frame argument) a stack frame which - must be popped when the container is finished. - - All output is written to a user-provided buffer or sink function. This - makes it popssible to create create atoms on the stack, on the heap, in LV2 - port buffers, in a ringbuffer, or elsewhere, all using the same API. - - This entire API is realtime safe if used with a buffer or a realtime safe - sink, except lv2_atom_forge_init() which is only realtime safe if the URI - map function is. - - Note these functions are all static inline, do not take their address. - - This header is non-normative, it is provided for convenience. -*/ - -#ifndef LV2_ATOM_FORGE_H -#define LV2_ATOM_FORGE_H - -#include <assert.h> - -#include "lv2/lv2plug.in/ns/ext/atom/atom.h" -#include "lv2/lv2plug.in/ns/ext/atom/util.h" -#include "lv2/lv2plug.in/ns/ext/urid/urid.h" - -#ifdef __cplusplus -extern "C" { -#else -# include <stdbool.h> -#endif - -/** Handle for LV2_Atom_Forge_Sink. */ -typedef void* LV2_Atom_Forge_Sink_Handle; - -/** A reference to a chunk of written output. */ -typedef intptr_t LV2_Atom_Forge_Ref; - -/** Sink function for writing output. See lv2_atom_forge_set_sink(). */ -typedef LV2_Atom_Forge_Ref -(*LV2_Atom_Forge_Sink)(LV2_Atom_Forge_Sink_Handle handle, - const void* buf, - uint32_t size); - -/** Function for resolving a reference. See lv2_atom_forge_set_sink(). */ -typedef LV2_Atom* -(*LV2_Atom_Forge_Deref_Func)(LV2_Atom_Forge_Sink_Handle handle, - LV2_Atom_Forge_Ref ref); - -/** A stack frame used for keeping track of nested Atom containers. */ -typedef struct _LV2_Atom_Forge_Frame { - struct _LV2_Atom_Forge_Frame* parent; - LV2_Atom_Forge_Ref ref; -} LV2_Atom_Forge_Frame; - -/** A "forge" for creating atoms by appending to a buffer. */ -typedef struct { - uint8_t* buf; - uint32_t offset; - uint32_t size; - - LV2_Atom_Forge_Sink sink; - LV2_Atom_Forge_Deref_Func deref; - LV2_Atom_Forge_Sink_Handle handle; - - LV2_Atom_Forge_Frame* stack; - - LV2_URID Blank; - LV2_URID Bool; - LV2_URID Double; - LV2_URID Float; - LV2_URID Int; - LV2_URID Long; - LV2_URID Literal; - LV2_URID Path; - LV2_URID Property; - LV2_URID Resource; - LV2_URID Sequence; - LV2_URID String; - LV2_URID Tuple; - LV2_URID URI; - LV2_URID URID; - LV2_URID Vector; -} LV2_Atom_Forge; - -static inline void -lv2_atom_forge_set_buffer(LV2_Atom_Forge* forge, uint8_t* buf, size_t size); - -/** - Initialise @p forge. - - URIs will be mapped using @p map and stored, a reference to @p map itself is - not held. -*/ -static inline void -lv2_atom_forge_init(LV2_Atom_Forge* forge, LV2_URID_Map* map) -{ - lv2_atom_forge_set_buffer(forge, NULL, 0); - forge->Blank = map->map(map->handle, LV2_ATOM__Blank); - forge->Bool = map->map(map->handle, LV2_ATOM__Bool); - forge->Double = map->map(map->handle, LV2_ATOM__Double); - forge->Float = map->map(map->handle, LV2_ATOM__Float); - forge->Int = map->map(map->handle, LV2_ATOM__Int); - forge->Long = map->map(map->handle, LV2_ATOM__Long); - forge->Literal = map->map(map->handle, LV2_ATOM__Literal); - forge->Path = map->map(map->handle, LV2_ATOM__Path); - forge->Property = map->map(map->handle, LV2_ATOM__Property); - forge->Resource = map->map(map->handle, LV2_ATOM__Resource); - forge->Sequence = map->map(map->handle, LV2_ATOM__Sequence); - forge->String = map->map(map->handle, LV2_ATOM__String); - forge->Tuple = map->map(map->handle, LV2_ATOM__Tuple); - forge->URI = map->map(map->handle, LV2_ATOM__URI); - forge->URID = map->map(map->handle, LV2_ATOM__URID); - forge->Vector = map->map(map->handle, LV2_ATOM__Vector); -} - -static inline LV2_Atom* -lv2_atom_forge_deref(LV2_Atom_Forge* forge, LV2_Atom_Forge_Ref ref) -{ - if (forge->buf) { - return (LV2_Atom*)ref; - } else { - return forge->deref(forge->handle, ref); - } -} - -/** - @name Object Stack - @{ -*/ - -/** - Push a stack frame. - This is done automatically by container functions (which take a stack frame - pointer), but may be called by the user to push the top level container when - writing to an existing Atom. -*/ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_push(LV2_Atom_Forge* forge, - LV2_Atom_Forge_Frame* frame, - LV2_Atom_Forge_Ref ref) -{ - frame->parent = forge->stack; - frame->ref = ref; - forge->stack = frame; - return ref; -} - -/** Pop a stack frame. This must be called when a container is finished. */ -static inline void -lv2_atom_forge_pop(LV2_Atom_Forge* forge, LV2_Atom_Forge_Frame* frame) -{ - assert(frame == forge->stack); - forge->stack = frame->parent; -} - -/** Return true iff the top of the stack has the given type. */ -static inline bool -lv2_atom_forge_top_is(LV2_Atom_Forge* forge, uint32_t type) -{ - return forge->stack && - lv2_atom_forge_deref(forge, forge->stack->ref)->type == type; -} - -/** - @} - @name Output Configuration - @{ -*/ - -/** Set the output buffer where @p forge will write atoms. */ -static inline void -lv2_atom_forge_set_buffer(LV2_Atom_Forge* forge, uint8_t* buf, size_t size) -{ - forge->buf = buf; - forge->size = size; - forge->offset = 0; - forge->deref = NULL; - forge->sink = NULL; - forge->handle = NULL; - forge->stack = NULL; -} - -/** - Set the sink function where @p forge will write output. - - The return value of forge functions is an LV2_Atom_Forge_Ref which is an - integer type safe to use as a pointer but is otherwise opaque. The sink - function must return a ref that can be dereferenced to access as least - sizeof(LV2_Atom) bytes of the written data, so sizes can be updated. For - ringbuffers, this should be possible as long as the size of the buffer is a - multiple of sizeof(LV2_Atom), since atoms are always aligned. - - Note that 0 is an invalid reference, so if you are using a buffer offset be - sure to offset it such that 0 is never a valid reference. You will get - confusing errors otherwise. -*/ -static inline void -lv2_atom_forge_set_sink(LV2_Atom_Forge* forge, - LV2_Atom_Forge_Sink sink, - LV2_Atom_Forge_Deref_Func deref, - LV2_Atom_Forge_Sink_Handle handle) -{ - forge->buf = NULL; - forge->size = forge->offset = 0; - forge->deref = deref; - forge->sink = sink; - forge->handle = handle; - forge->stack = NULL; -} - -/** - @} - @name Low Level Output - @{ -*/ - -/** - Write raw output. This is used internally, but is also useful for writing - atom types not explicitly supported by the forge API. Note the caller is - responsible for ensuring the output is approriately padded. -*/ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_raw(LV2_Atom_Forge* forge, const void* data, uint32_t size) -{ - LV2_Atom_Forge_Ref out = 0; - if (forge->sink) { - out = forge->sink(forge->handle, data, size); - } else { - out = (LV2_Atom_Forge_Ref)forge->buf + forge->offset; - uint8_t* mem = forge->buf + forge->offset; - if (forge->offset + size > forge->size) { - return 0; - } - forge->offset += size; - memcpy(mem, data, size); - } - for (LV2_Atom_Forge_Frame* f = forge->stack; f; f = f->parent) { - lv2_atom_forge_deref(forge, f->ref)->size += size; - } - return out; -} - -/** Pad output accordingly so next write is 64-bit aligned. */ -static inline void -lv2_atom_forge_pad(LV2_Atom_Forge* forge, uint32_t written) -{ - const uint64_t pad = 0; - const uint32_t pad_size = lv2_atom_pad_size(written) - written; - lv2_atom_forge_raw(forge, &pad, pad_size); -} - -/** Write raw output, padding to 64-bits as necessary. */ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_write(LV2_Atom_Forge* forge, const void* data, uint32_t size) -{ - LV2_Atom_Forge_Ref out = lv2_atom_forge_raw(forge, data, size); - if (out) { - lv2_atom_forge_pad(forge, size); - } - return out; -} - -/** Write a null-terminated string body. */ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_string_body(LV2_Atom_Forge* forge, - const char* str, - uint32_t len) -{ - LV2_Atom_Forge_Ref out = lv2_atom_forge_raw(forge, str, len); - if (out && (out = lv2_atom_forge_raw(forge, "", 1))) { - lv2_atom_forge_pad(forge, len + 1); - } - return out; -} - -/** - @} - @name Atom Output - @{ -*/ - -/** Write an atom:Atom header. */ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_atom(LV2_Atom_Forge* forge, uint32_t size, uint32_t type) -{ - const LV2_Atom a = { size, type }; - return lv2_atom_forge_raw(forge, &a, sizeof(a)); -} - -/** Write a primitive (fixed-size) atom. */ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_primitive(LV2_Atom_Forge* forge, const LV2_Atom* a) -{ - if (lv2_atom_forge_top_is(forge, forge->Vector)) { - return lv2_atom_forge_raw(forge, LV2_ATOM_BODY(a), a->size); - } else { - return lv2_atom_forge_write(forge, a, sizeof(LV2_Atom) + a->size); - } -} - -/** Write an atom:Int. */ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_int(LV2_Atom_Forge* forge, int32_t val) -{ - const LV2_Atom_Int a = { { sizeof(val), forge->Int }, val }; - return lv2_atom_forge_primitive(forge, &a.atom); -} - -/** Write an atom:Long. */ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_long(LV2_Atom_Forge* forge, int64_t val) -{ - const LV2_Atom_Long a = { { sizeof(val), forge->Long }, val }; - return lv2_atom_forge_primitive(forge, &a.atom); -} - -/** Write an atom:Float. */ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_float(LV2_Atom_Forge* forge, float val) -{ - const LV2_Atom_Float a = { { sizeof(val), forge->Float }, val }; - return lv2_atom_forge_primitive(forge, &a.atom); -} - -/** Write an atom:Double. */ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_double(LV2_Atom_Forge* forge, double val) -{ - const LV2_Atom_Double a = { { sizeof(val), forge->Double }, val }; - return lv2_atom_forge_primitive(forge, &a.atom); -} - -/** Write an atom:Bool. */ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_bool(LV2_Atom_Forge* forge, bool val) -{ - const LV2_Atom_Bool a = { { sizeof(int32_t), forge->Bool }, val ? 1 : 0 }; - return lv2_atom_forge_primitive(forge, &a.atom); -} - -/** Write an atom:URID. */ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_urid(LV2_Atom_Forge* forge, LV2_URID id) -{ - const LV2_Atom_URID a = { { sizeof(id), forge->URID }, id }; - return lv2_atom_forge_primitive(forge, &a.atom); -} - -/** Write an atom compatible with atom:String. Used internally. */ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_typed_string(LV2_Atom_Forge* forge, - uint32_t type, - const char* str, - uint32_t len) -{ - const LV2_Atom_String a = { { len + 1, type } }; - LV2_Atom_Forge_Ref out = lv2_atom_forge_raw(forge, &a, sizeof(a)); - if (out) { - if (!lv2_atom_forge_string_body(forge, str, len)) { - LV2_Atom* atom = lv2_atom_forge_deref(forge, out); - atom->size = atom->type = 0; - out = 0; - } - } - return out; -} - -/** Write an atom:String. Note that @p str need not be NULL terminated. */ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_string(LV2_Atom_Forge* forge, const char* str, uint32_t len) -{ - return lv2_atom_forge_typed_string(forge, forge->String, str, len); -} - -/** - Write an atom:URI. Note that @p uri need not be NULL terminated. - This does not map the URI, but writes the complete URI string. To write - a mapped URI, use lv2_atom_forge_urid(). -*/ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_uri(LV2_Atom_Forge* forge, const char* uri, uint32_t len) -{ - return lv2_atom_forge_typed_string(forge, forge->URI, uri, len); -} - -/** Write an atom:Path. Note that @p path need not be NULL terminated. */ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_path(LV2_Atom_Forge* forge, const char* path, uint32_t len) -{ - return lv2_atom_forge_typed_string(forge, forge->Path, path, len); -} - -/** Write an atom:Literal. */ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_literal(LV2_Atom_Forge* forge, - const char* str, - uint32_t len, - uint32_t datatype, - uint32_t lang) -{ - const LV2_Atom_Literal a = { - { sizeof(LV2_Atom_Literal) - sizeof(LV2_Atom) + len + 1, - forge->Literal }, - { datatype, - lang } - }; - LV2_Atom_Forge_Ref out = lv2_atom_forge_raw(forge, &a, sizeof(a)); - if (out) { - if (!lv2_atom_forge_string_body(forge, str, len)) { - LV2_Atom* atom = lv2_atom_forge_deref(forge, out); - atom->size = atom->type = 0; - out = 0; - } - } - return out; -} - -/** Start an atom:Vector. */ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_vector_head(LV2_Atom_Forge* forge, - LV2_Atom_Forge_Frame* frame, - uint32_t child_size, - uint32_t child_type) -{ - const LV2_Atom_Vector a = { - { sizeof(LV2_Atom_Vector_Body), forge->Vector }, - { child_size, child_type } - }; - return lv2_atom_forge_push( - forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a))); -} - -/** Write a complete atom:Vector. */ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_vector(LV2_Atom_Forge* forge, - uint32_t child_size, - uint32_t child_type, - uint32_t n_elems, - const void* elems) -{ - const LV2_Atom_Vector a = { - { sizeof(LV2_Atom_Vector_Body) + n_elems * child_size, forge->Vector }, - { child_size, child_type } - }; - LV2_Atom_Forge_Ref out = lv2_atom_forge_write(forge, &a, sizeof(a)); - if (out) { - lv2_atom_forge_write(forge, elems, child_size * n_elems); - } - return out; -} - -/** - Write the header of an atom:Tuple. - - The passed frame will be initialised to represent this tuple. To complete - the tuple, write a sequence of atoms, then pop the frame with - lv2_atom_forge_pop(). - - For example: - @code - // Write tuple (1, 2.0) - LV2_Atom_Forge_Frame frame; - LV2_Atom* tup = (LV2_Atom*)lv2_atom_forge_tuple(forge, &frame); - lv2_atom_forge_int32(forge, 1); - lv2_atom_forge_float(forge, 2.0); - lv2_atom_forge_pop(forge, &frame); - @endcode -*/ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_tuple(LV2_Atom_Forge* forge, LV2_Atom_Forge_Frame* frame) -{ - const LV2_Atom_Tuple a = { { 0, forge->Tuple } }; - return lv2_atom_forge_push( - forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a))); -} - -/** - Write the header of an atom:Resource. - - The passed frame will be initialised to represent this object. To complete - the object, write a sequence of properties, then pop the frame with - lv2_atom_forge_pop(). - - For example: - @code - LV2_URID eg_Cat = map("http://example.org/Cat"); - LV2_URID eg_name = map("http://example.org/name"); - - // Write object header - LV2_Atom_Forge_Frame frame; - lv2_atom_forge_resource(forge, &frame, 1, eg_Cat); - - // Write property: eg:name = "Hobbes" - lv2_atom_forge_property_head(forge, eg_name, 0); - lv2_atom_forge_string(forge, "Hobbes", strlen("Hobbes")); - - // Finish object - lv2_atom_forge_pop(forge, &frame); - @endcode -*/ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_resource(LV2_Atom_Forge* forge, - LV2_Atom_Forge_Frame* frame, - LV2_URID id, - LV2_URID otype) -{ - const LV2_Atom_Object a = { - { sizeof(LV2_Atom_Object) - sizeof(LV2_Atom), forge->Resource }, - { id, otype } - }; - LV2_Atom_Forge_Ref out = lv2_atom_forge_write(forge, &a, sizeof(a)); - return lv2_atom_forge_push(forge, frame, out); -} - -/** - The same as lv2_atom_forge_resource(), but for object:Blank. -*/ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_blank(LV2_Atom_Forge* forge, - LV2_Atom_Forge_Frame* frame, - uint32_t id, - LV2_URID otype) -{ - const LV2_Atom_Object a = { - { sizeof(LV2_Atom_Object) - sizeof(LV2_Atom), forge->Blank }, - { id, otype } - }; - LV2_Atom_Forge_Ref out = lv2_atom_forge_write(forge, &a, sizeof(a)); - return lv2_atom_forge_push(forge, frame, out); -} - -/** - Write the header for a property body (likely in an Object). - See lv2_atom_forge_object() documentation for an example. -*/ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_property_head(LV2_Atom_Forge* forge, - LV2_URID key, - LV2_URID context) -{ - const LV2_Atom_Property_Body a = { key, context, { 0, 0 } }; - return lv2_atom_forge_write(forge, &a, 2 * sizeof(uint32_t)); -} - -/** - Write the header for a Sequence. - The size of the returned sequence will be 0, so passing it as the parent - parameter to other forge methods will do the right thing. -*/ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_sequence_head(LV2_Atom_Forge* forge, - LV2_Atom_Forge_Frame* frame, - uint32_t unit) -{ - const LV2_Atom_Sequence a = { - { sizeof(LV2_Atom_Sequence) - sizeof(LV2_Atom), forge->Sequence }, - { unit, 0 } - }; - LV2_Atom_Forge_Ref out = lv2_atom_forge_write(forge, &a, sizeof(a)); - return lv2_atom_forge_push(forge, frame, out); -} - -/** - Write the time stamp header of an Event (in a Sequence) in audio frames. - After this, call the appropriate forge method(s) to write the body, passing - the same @p parent parameter. Note the returned LV2_Event is NOT an Atom. -*/ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_frame_time(LV2_Atom_Forge* forge, int64_t frames) -{ - return lv2_atom_forge_write(forge, &frames, sizeof(frames)); -} - -/** - Write the time stamp header of an Event (in a Sequence) in beats. - After this, call the appropriate forge method(s) to write the body, passing - the same @p parent parameter. Note the returned LV2_Event is NOT an Atom. -*/ -static inline LV2_Atom_Forge_Ref -lv2_atom_forge_beat_time(LV2_Atom_Forge* forge, double beats) -{ - return lv2_atom_forge_write(forge, &beats, sizeof(beats)); -} - -/** - @} -*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* LV2_ATOM_FORGE_H */ |