From 75d524c764a6f91aa9662040a2c218e8d2802438 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 16 Feb 2012 23:05:48 +0000 Subject: Add atom:eventTransfer (for UIs that talk to atom event ports). Add lv2_atom_total_size() helper. Make LV2_Atom_Literal definiton consistent with others. Rework forge API to support writing to an arbitrary sink function (e.g. ringbuffer). --- lv2/lv2plug.in/ns/ext/atom/atom-helpers.h | 7 + lv2/lv2plug.in/ns/ext/atom/atom.h | 9 +- lv2/lv2plug.in/ns/ext/atom/atom.ttl | 13 ++ lv2/lv2plug.in/ns/ext/atom/forge.h | 291 ++++++++++++++---------------- 4 files changed, 158 insertions(+), 162 deletions(-) diff --git a/lv2/lv2plug.in/ns/ext/atom/atom-helpers.h b/lv2/lv2plug.in/ns/ext/atom/atom-helpers.h index ae2eb43..3bfad57 100644 --- a/lv2/lv2plug.in/ns/ext/atom/atom-helpers.h +++ b/lv2/lv2plug.in/ns/ext/atom/atom-helpers.h @@ -45,6 +45,13 @@ lv2_atom_pad_size(uint32_t size) return (size + 7) & (~7); } +/** Return the total size of @p atom, including the header. */ +static inline uint32_t +lv2_atom_total_size(const LV2_Atom* atom) +{ + return sizeof(LV2_Atom) + atom->size; +} + /** Return true iff @p atom is null. */ static inline bool lv2_atom_is_null(const LV2_Atom* atom) diff --git a/lv2/lv2plug.in/ns/ext/atom/atom.h b/lv2/lv2plug.in/ns/ext/atom/atom.h index 5c0b3fd..fd0279c 100644 --- a/lv2/lv2plug.in/ns/ext/atom/atom.h +++ b/lv2/lv2plug.in/ns/ext/atom/atom.h @@ -96,16 +96,11 @@ typedef struct { /* Contents (a null-terminated UTF-8 string) follow here. */ } LV2_Atom_String; -/** The header of an atom:Literal body. */ +/** The complete header of an atom:Literal. */ typedef struct { + LV2_Atom atom; /**< Atom header. */ uint32_t datatype; /**< The ID of the datatype of this literal. */ uint32_t lang; /**< The ID of the language of this literal. */ -} LV2_Atom_Literal_Head; - -/** The complete header of an atom:Literal. */ -typedef struct { - LV2_Atom atom; /**< Atom header. */ - LV2_Atom_Literal_Head literal; /**< Literal body header. */ /* Contents (a null-terminated UTF-8 string) follow here. */ } LV2_Atom_Literal; diff --git a/lv2/lv2plug.in/ns/ext/atom/atom.ttl b/lv2/lv2plug.in/ns/ext/atom/atom.ttl index 4d87ce5..9a396bf 100644 --- a/lv2/lv2plug.in/ns/ext/atom/atom.ttl +++ b/lv2/lv2plug.in/ns/ext/atom/atom.ttl @@ -484,3 +484,16 @@ described like so:

] . """ . + +atom:eventTransfer + a ; + lv2:documentation """ +

Transfer of individual events. Useful as the +format for a LV2_UI_Write_Function, or the +port_protocol for LV2_PUI_Host_Descriptor::write_port().

+ +

This protocol applies to ports which contain events, usually in an +atom:Sequence. The host must transfer each individual event to the recipient. +The format of the received data is an LV2_Atom, there is no timestamp +header.

+""" . \ No newline at end of file diff --git a/lv2/lv2plug.in/ns/ext/atom/forge.h b/lv2/lv2plug.in/ns/ext/atom/forge.h index 78c7873..65ab352 100644 --- a/lv2/lv2plug.in/ns/ext/atom/forge.h +++ b/lv2/lv2plug.in/ns/ext/atom/forge.h @@ -47,13 +47,22 @@ extern "C" { # include #endif +typedef void* LV2_Atom_Forge_Sink_Handle; + +typedef uint32_t (*LV2_Atom_Forge_Sink)(LV2_Atom_Forge_Sink_Handle handle, + const void* buf, + uint32_t size); + /** A "forge" for creating atoms by appending to a buffer. */ typedef struct { uint8_t* buf; - size_t offset; - size_t size; + uint32_t offset; + uint32_t size; + + LV2_Atom_Forge_Sink sink; + LV2_Atom_Forge_Sink_Handle handle; LV2_URID Blank; LV2_URID Bool; @@ -80,6 +89,17 @@ lv2_atom_forge_set_buffer(LV2_Atom_Forge* forge, uint8_t* buf, size_t size) forge->offset = 0; } +static inline void +lv2_atom_forge_set_sink(LV2_Atom_Forge* forge, + LV2_Atom_Forge_Sink sink, + LV2_Atom_Forge_Sink_Handle handle) +{ + forge->buf = NULL; + forge->size = forge->offset = 0; + forge->sink = sink; + forge->handle = handle; +} + /** Initialise @c forge. @@ -106,43 +126,43 @@ lv2_atom_forge_init(LV2_Atom_Forge* forge, LV2_URID_Map* map) forge->Vector = map->map(map->handle, LV2_ATOM_URI "#Vector"); } -/** - Reserve @c size bytes in the output buffer (used internally). - @return The start of the reserved memory, or NULL if out of space. -*/ -static inline uint8_t* -lv2_atom_forge_reserve(LV2_Atom_Forge* forge, - LV2_Atom* parent, - uint32_t size) +static inline void* +lv2_atom_forge_write_nopad(LV2_Atom_Forge* forge, + LV2_Atom* parent, + const void* data, + uint32_t size) { - uint8_t* const out = forge->buf + forge->offset; - const uint32_t padded_size = lv2_atom_pad_size(size); - if (forge->offset + padded_size > forge->size) { + uint8_t* const out = forge->buf + forge->offset; + if (forge->offset + size > forge->size) { return NULL; } if (parent) { - parent->size += padded_size; + parent->size += size; } - forge->offset += padded_size; + forge->offset += size; + memcpy(out, data, size); return out; } -/** - Write the header of an atom:Atom. +static inline void +lv2_atom_forge_pad(LV2_Atom_Forge* forge, + LV2_Atom* parent, + uint32_t written) +{ + const uint64_t pad = 0; + const uint32_t pad_size = lv2_atom_pad_size(written) - written; + lv2_atom_forge_write_nopad(forge, parent, &pad, pad_size); +} - Space for the complete atom will be reserved, but uninitialised. -*/ -static inline LV2_Atom* -lv2_atom_forge_atom_head(LV2_Atom_Forge* forge, - LV2_Atom* parent, - uint32_t type, - uint32_t size) +static inline void* +lv2_atom_forge_write(LV2_Atom_Forge* forge, + LV2_Atom* parent, + const void* data, + uint32_t size) { - LV2_Atom* const out = (LV2_Atom*)lv2_atom_forge_reserve( - forge, parent, size); + void* out = lv2_atom_forge_write_nopad(forge, parent, data, size); if (out) { - out->type = type; - out->size = size - sizeof(LV2_Atom); + lv2_atom_forge_pad(forge, parent, size); } return out; } @@ -151,93 +171,71 @@ lv2_atom_forge_atom_head(LV2_Atom_Forge* forge, static inline LV2_Atom_Int32* lv2_atom_forge_int32(LV2_Atom_Forge* forge, LV2_Atom* parent, int32_t val) { - LV2_Atom_Int32* out = (LV2_Atom_Int32*)lv2_atom_forge_atom_head( - forge, parent, forge->Int32, sizeof(LV2_Atom_Int32)); - if (out) { - out->value = val; - } - return out; + const LV2_Atom_Int32 a = { { forge->Int32, sizeof(val) }, val }; + return (LV2_Atom_Int32*)lv2_atom_forge_write(forge, parent, &a, sizeof(a)); } /** Write an atom:Int64. */ static inline LV2_Atom_Int64* lv2_atom_forge_int64(LV2_Atom_Forge* forge, LV2_Atom* parent, int64_t val) { - LV2_Atom_Int64* out = (LV2_Atom_Int64*)lv2_atom_forge_atom_head( - forge, parent, forge->Int64, sizeof(LV2_Atom_Int64)); - if (out) { - out->value = val; - } - return out; + const LV2_Atom_Int64 a = { { forge->Int64, sizeof(val) }, val }; + return (LV2_Atom_Int64*)lv2_atom_forge_write(forge, parent, &a, sizeof(a)); } /** Write an atom:Float. */ static inline LV2_Atom_Float* lv2_atom_forge_float(LV2_Atom_Forge* forge, LV2_Atom* parent, float val) { - LV2_Atom_Float* out = (LV2_Atom_Float*)lv2_atom_forge_atom_head( - forge, parent, forge->Float, sizeof(LV2_Atom_Float)); - if (out) { - out->value = val; - } - return out; + const LV2_Atom_Float a = { { forge->Float, sizeof(val) }, val }; + return (LV2_Atom_Float*)lv2_atom_forge_write(forge, parent, &a, sizeof(a)); } /** Write an atom:Double. */ static inline LV2_Atom_Double* lv2_atom_forge_double(LV2_Atom_Forge* forge, LV2_Atom* parent, double val) { - LV2_Atom_Double* out = (LV2_Atom_Double*)lv2_atom_forge_atom_head( - forge, parent, forge->Double, sizeof(LV2_Atom_Double)); - if (out) { - out->value = val; - } - return out; + const LV2_Atom_Double a = { { forge->Double, sizeof(val) }, val }; + return (LV2_Atom_Double*)lv2_atom_forge_write( + forge, parent, &a, sizeof(a)); } /** Write an atom:Bool. */ static inline LV2_Atom_Bool* lv2_atom_forge_bool(LV2_Atom_Forge* forge, LV2_Atom* parent, bool val) { - LV2_Atom_Bool* out = (LV2_Atom_Bool*)lv2_atom_forge_atom_head( - forge, parent, forge->Bool, sizeof(LV2_Atom_Bool)); - if (out) { - out->value = val ? 1 : 0; - } - return out; + const LV2_Atom_Bool a = { { forge->Bool, sizeof(val) }, val }; + return (LV2_Atom_Bool*)lv2_atom_forge_write(forge, parent, &a, sizeof(a)); } /** Write an atom:URID. */ static inline LV2_Atom_URID* lv2_atom_forge_urid(LV2_Atom_Forge* forge, LV2_Atom* parent, LV2_URID id) { - LV2_Atom_URID* out = (LV2_Atom_URID*)lv2_atom_forge_reserve( - forge, parent, sizeof(LV2_Atom_URID)); - if (out) { - out->atom.type = forge->URID; - out->atom.size = sizeof(uint32_t); - out->id = id; - } - return out; + const LV2_Atom_URID a = { { forge->Int32, sizeof(id) }, id }; + return (LV2_Atom_URID*)lv2_atom_forge_write(forge, parent, &a, sizeof(a)); } -/** Write an atom:String. */ +/** Write an atom:String. Note that @p str need not be NULL terminated. */ static inline LV2_Atom_String* lv2_atom_forge_string(LV2_Atom_Forge* forge, LV2_Atom* parent, const uint8_t* str, size_t len) { - LV2_Atom_String* out = (LV2_Atom_String*)lv2_atom_forge_reserve( - forge, parent, sizeof(LV2_Atom_String) + len + 1); - if (out) { - out->atom.type = forge->String; - out->atom.size = len + 1; - assert(LV2_ATOM_CONTENTS(LV2_Atom_String, out) == LV2_ATOM_BODY(out)); - uint8_t* buf = LV2_ATOM_CONTENTS(LV2_Atom_String, out); - memcpy(buf, str, len); - buf[len] = '\0'; + const LV2_Atom_String a = { { forge->String, len + 1 } }; + LV2_Atom_String* out = (LV2_Atom_String*) + lv2_atom_forge_write_nopad(forge, parent, &a, sizeof(a)); + if (!out) { + return NULL; + } + if (!lv2_atom_forge_write_nopad(forge, parent, str, len) + || !lv2_atom_forge_write_nopad(forge, parent, "", 1)) { + out->atom.type = 0; + out->atom.size = 0; + return NULL; } + lv2_atom_forge_pad(forge, parent, len + 1); return out; } @@ -250,41 +248,46 @@ lv2_atom_forge_literal(LV2_Atom_Forge* forge, uint32_t datatype, uint32_t lang) { - LV2_Atom_Literal* out = (LV2_Atom_Literal*)lv2_atom_forge_reserve( - forge, parent, sizeof(LV2_Atom_Literal) + len + 1); - if (out) { - out->atom.type = forge->Literal; - out->atom.size = sizeof(LV2_Atom_Literal_Head) + len + 1; - out->literal.datatype = datatype; - out->literal.lang = lang; - uint8_t* buf = LV2_ATOM_CONTENTS(LV2_Atom_Literal, out); - memcpy(buf, str, len); - buf[len] = '\0'; + const LV2_Atom_Literal a = { + { forge->Literal, + sizeof(LV2_Atom_Literal) - sizeof(LV2_Atom) + len + 1 }, + datatype, + lang + }; + LV2_Atom_Literal* out = (LV2_Atom_Literal*) + lv2_atom_forge_write_nopad(forge, parent, &a, sizeof(a)); + if (!out) { + return NULL; + } + if (!lv2_atom_forge_write_nopad(forge, parent, str, len) + || !lv2_atom_forge_write_nopad(forge, parent, "", 1)) { + out->atom.type = 0; + out->atom.size = 0; + return NULL; } + lv2_atom_forge_pad(forge, parent, len + 1); return out; } -/** Write an atom:Vector header and reserve space for the body. */ +/** Write an atom:Vector header, but not the vector body. */ static inline LV2_Atom_Vector* -lv2_atom_forge_reserve_vector(LV2_Atom_Forge* forge, - LV2_Atom* parent, - uint32_t elem_count, - uint32_t elem_type, - uint32_t elem_size) +lv2_atom_forge_vector_head(LV2_Atom_Forge* forge, + LV2_Atom* parent, + uint32_t elem_count, + uint32_t elem_type, + uint32_t elem_size) { - const size_t size = sizeof(LV2_Atom_Vector) + (elem_size * elem_count); - LV2_Atom_Vector* out = (LV2_Atom_Vector*)lv2_atom_forge_reserve( - forge, parent, size); - if (out) { - out->atom.type = forge->Vector; - out->atom.size = size - sizeof(LV2_Atom); - out->elem_count = elem_count; - out->elem_type = elem_type; - } - return out; + const size_t size = sizeof(LV2_Atom_Vector) + (elem_size * elem_count); + const LV2_Atom_Vector a = { + { forge->Vector, size - sizeof(LV2_Atom) }, + elem_count, + elem_type + }; + return (LV2_Atom_Vector*)lv2_atom_forge_write( + forge, parent, &a, sizeof(a)); } -/** Write an atom:Vector. */ +/** Write a complete atom:Vector. */ static inline LV2_Atom_Vector* lv2_atom_forge_vector(LV2_Atom_Forge* forge, LV2_Atom* parent, @@ -293,11 +296,10 @@ lv2_atom_forge_vector(LV2_Atom_Forge* forge, uint32_t elem_size, void* elems) { - LV2_Atom_Vector* out = lv2_atom_forge_reserve_vector( + LV2_Atom_Vector* out = lv2_atom_forge_vector_head( forge, parent, elem_count, elem_type, elem_size); if (out) { - uint8_t* buf = LV2_ATOM_CONTENTS(LV2_Atom_Vector, out); - memcpy(buf, elems, elem_size * elem_count); + lv2_atom_forge_write(forge, parent, elems, elem_size * elem_count); } return out; } @@ -321,8 +323,8 @@ static inline LV2_Atom_Tuple* lv2_atom_forge_tuple(LV2_Atom_Forge* forge, LV2_Atom* parent) { - return (LV2_Atom_Tuple*)lv2_atom_forge_atom_head( - forge, parent, forge->Tuple, sizeof(LV2_Atom)); + const LV2_Atom_Tuple a = { { forge->Tuple, 0 } }; + return (LV2_Atom_Tuple*)lv2_atom_forge_write(forge, parent, &a, sizeof(a)); } /** @@ -351,15 +353,12 @@ lv2_atom_forge_resource(LV2_Atom_Forge* forge, LV2_URID id, LV2_URID otype) { - LV2_Atom_Object* out = (LV2_Atom_Object*)lv2_atom_forge_reserve( - forge, parent, sizeof(LV2_Atom_Object)); - if (out) { - out->atom.type = forge->Resource; - out->atom.size = sizeof(LV2_Atom_Object) - sizeof(LV2_Atom); - out->id = id; - out->type = otype; - } - return out; + const LV2_Atom_Object a = { + { forge->Resource, sizeof(LV2_Atom_Object) - sizeof(LV2_Atom) }, + id, + otype + }; + return (LV2_Atom_Object*)lv2_atom_forge_write(forge, parent, &a, sizeof(a)); } /** @@ -371,15 +370,12 @@ lv2_atom_forge_blank(LV2_Atom_Forge* forge, uint32_t id, LV2_URID otype) { - LV2_Atom_Object* out = (LV2_Atom_Object*)lv2_atom_forge_reserve( - forge, parent, sizeof(LV2_Atom_Object)); - if (out) { - out->atom.type = forge->Blank; - out->atom.size = sizeof(LV2_Atom_Object) - sizeof(LV2_Atom); - out->id = id; - out->type = otype; - } - return out; + const LV2_Atom_Object a = { + { forge->Blank, sizeof(LV2_Atom_Object) - sizeof(LV2_Atom) }, + id, + otype + }; + return (LV2_Atom_Object*)lv2_atom_forge_write(forge, parent, &a, sizeof(a)); } /** @@ -392,13 +388,9 @@ lv2_atom_forge_property_head(LV2_Atom_Forge* forge, LV2_URID key, LV2_URID context) { - LV2_Atom_Property_Body* out = (LV2_Atom_Property_Body*) - lv2_atom_forge_reserve(forge, parent, 2 * sizeof(uint32_t)); - if (out) { - out->key = key; - out->context = context; - } - return out; + const LV2_Atom_Property_Body a = { key, context, { 0, 0 } }; + return (LV2_Atom_Property_Body*)lv2_atom_forge_write( + forge, parent, &a, 2 * sizeof(uint32_t)); } /** @@ -412,15 +404,13 @@ lv2_atom_forge_sequence_head(LV2_Atom_Forge* forge, uint32_t capacity, uint32_t unit) { - LV2_Atom_Sequence* out = (LV2_Atom_Sequence*) - lv2_atom_forge_reserve(forge, parent, sizeof(LV2_Atom_Sequence)); - if (out) { - out->atom.type = forge->Sequence; - out->atom.size = sizeof(LV2_Atom_Sequence) - sizeof(LV2_Atom); - out->unit = unit; - out->pad = 0; - } - return out; + const LV2_Atom_Sequence a = { + { forge->Sequence, sizeof(LV2_Atom_Sequence) - sizeof(LV2_Atom) }, + unit, + 0 + }; + return (LV2_Atom_Sequence*)lv2_atom_forge_write( + forge, parent, &a, sizeof(a)); } /** @@ -434,13 +424,8 @@ lv2_atom_forge_audio_time(LV2_Atom_Forge* forge, uint32_t frames, uint32_t subframes) { - LV2_Atom_Event* out = (LV2_Atom_Event*) - lv2_atom_forge_reserve(forge, parent, 2 * sizeof(uint32_t)); - if (out) { - out->time.audio.frames = frames; - out->time.audio.subframes = subframes; - } - return out; + const LV2_Atom_Audio_Time a = { frames, subframes }; + return (LV2_Atom_Event*)lv2_atom_forge_write(forge, parent, &a, sizeof(a)); } /** @@ -453,12 +438,8 @@ lv2_atom_forge_beat_time(LV2_Atom_Forge* forge, LV2_Atom* parent, double beats) { - LV2_Atom_Event* out = (LV2_Atom_Event*) - lv2_atom_forge_reserve(forge, parent, sizeof(double)); - if (out) { - out->time.beats = beats; - } - return out; + return (LV2_Atom_Event*)lv2_atom_forge_write( + forge, parent, &beats, sizeof(beats)); } #ifdef __cplusplus -- cgit v1.2.1