From 7b90f2dac53b7cd17fb9499c4cedf2b301d90129 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Wed, 9 Nov 2011 01:08:14 +0000 Subject: Define types as complete objects, not just atom bodies. Improve helper API. --- ext/atom.lv2/atom-buffer.h | 21 +++---- ext/atom.lv2/atom-helpers.h | 72 ++++++----------------- ext/atom.lv2/atom.h | 138 ++++++++++++++++++++++---------------------- ext/atom.lv2/forge.h | 75 ++++++++++++++++++++++++ 4 files changed, 170 insertions(+), 136 deletions(-) create mode 100644 ext/atom.lv2/forge.h diff --git a/ext/atom.lv2/atom-buffer.h b/ext/atom.lv2/atom-buffer.h index 2ac71e3..f4b90dd 100644 --- a/ext/atom.lv2/atom-buffer.h +++ b/ext/atom.lv2/atom-buffer.h @@ -28,19 +28,9 @@ #include #include #include -#include #include "lv2/lv2plug.in/ns/ext/atom/atom.h" -/** - Pad a size to 64 bits. -*/ -static inline uint32_t -lv2_atom_pad_size(uint32_t size) -{ - return (size + 7) & (~7); -} - /** Initialize an existing atom buffer. All fields of @c buf are reset, except capacity which is unmodified. @@ -111,9 +101,10 @@ lv2_atom_buffer_is_valid(LV2_Atom_Buffer_Iterator i) static inline LV2_Atom_Buffer_Iterator lv2_atom_buffer_next(LV2_Atom_Buffer_Iterator i) { - assert(lv2_atom_buffer_is_valid(i)); - const LV2_Atom_Event* const ev = (LV2_Atom_Event*)( - i.buf->data + i.offset); + if (!lv2_atom_buffer_is_valid(i)) { + return i; + } + const LV2_Atom_Event* const ev = (LV2_Atom_Event*)(i.buf->data + i.offset); i.offset += lv2_atom_pad_size(sizeof(LV2_Atom_Event) + ev->body.size); return i; } @@ -124,7 +115,9 @@ lv2_atom_buffer_next(LV2_Atom_Buffer_Iterator i) static inline LV2_Atom_Event* lv2_atom_buffer_get(LV2_Atom_Buffer_Iterator i) { - assert(lv2_event_is_valid(i)); + if (!lv2_atom_buffer_is_valid(i)) { + return NULL; + } return (LV2_Atom_Event*)(i.buf->data + i.offset); } diff --git a/ext/atom.lv2/atom-helpers.h b/ext/atom.lv2/atom-helpers.h index ae4bc6f..9d48a29 100644 --- a/ext/atom.lv2/atom-helpers.h +++ b/ext/atom.lv2/atom-helpers.h @@ -34,27 +34,20 @@ #include "lv2/lv2plug.in/ns/ext/atom/atom.h" -/** Pad a size to 4 bytes (32 bits) */ -static inline uint16_t -lv2_atom_pad_size(uint16_t size) -{ - return (size + 3) & (~3); -} - typedef LV2_Atom_Property* LV2_Object_Iter; /** Get an iterator pointing to @c prop in some LV2_Object */ static inline LV2_Object_Iter -lv2_object_begin(const LV2_Atom* obj) +lv2_object_begin(const LV2_Object* obj) { - return (LV2_Object_Iter)(((const LV2_Object*)obj->body)->properties); + return (LV2_Object_Iter)(obj->properties); } /** Return true iff @c iter has reached the end of @c object */ static inline bool -lv2_object_iter_is_end(const LV2_Atom* object, LV2_Object_Iter iter) +lv2_object_iter_is_end(const LV2_Object* obj, LV2_Object_Iter iter) { - return (uint8_t*)iter >= ((uint8_t*)object->body + object->size); + return (uint8_t*)iter >= ((uint8_t*)obj + sizeof(LV2_Atom) + obj->size); } /** Return true iff @c l points to the same property as @c r */ @@ -113,14 +106,15 @@ lv2_object_iter_get(LV2_Object_Iter iter) Atom type that contains headerless 32-bit aligned properties. */ static inline LV2_Atom_Property* -lv2_atom_append_property(LV2_Atom* object, - uint32_t key, - uint16_t value_type, - uint16_t value_size, - const uint8_t* value_body) +lv2_object_append(LV2_Object* object, + uint32_t key, + uint32_t value_type, + uint32_t value_size, + const void* value_body) { object->size = lv2_atom_pad_size(object->size); - LV2_Atom_Property* prop = (LV2_Atom_Property*)(object->body + object->size); + LV2_Atom_Property* prop = (LV2_Atom_Property*)( + (uint8_t*)object + sizeof(LV2_Atom) + object->size); prop->key = key; prop->value.type = value_type; prop->value.size = value_size; @@ -136,44 +130,14 @@ lv2_atom_is_null(LV2_Atom* atom) return !atom || (atom->type == 0 && atom->size == 0); } -/** Return true iff @c object has rdf:type @c type */ -static inline bool -lv2_atom_is_a(LV2_Atom* object, - uint32_t rdf_type, - uint32_t atom_URIInt, - uint32_t atom_Object, - uint32_t type) -{ - if (lv2_atom_is_null(object)) - return false; - - if (object->type == type) - return true; - - if (object->type == atom_Object) { - LV2_OBJECT_FOREACH(object, o) { - LV2_Atom_Property* prop = lv2_object_iter_get(o); - if (prop->key == rdf_type) { - if (prop->value.type == atom_URIInt) { - const uint32_t object_type = *(uint32_t*)prop->value.body; - if (object_type == type) - return true; - } else { - fprintf(stderr, "error: rdf:type is not a URIInt\n"); - } - } - } - } - - return false; -} - /** A single entry in an Object query. */ typedef struct { - uint32_t key; /**< Key to query (input set by user) */ - const LV2_Atom* value; /**< Found value (output set by query function) */ + uint32_t key; /**< Key to query (input set by user) */ + const LV2_Atom** value; /**< Found value (output set by query function) */ } LV2_Object_Query; +static const LV2_Object_Query LV2_OBJECT_QUERY_END = { 0, NULL }; + /** "Query" an object, getting a pointer to the values for various keys. @@ -184,7 +148,7 @@ typedef struct { quickly without allocating any memory. This function is realtime safe. */ static inline int -lv2_object_query(const LV2_Atom* object, LV2_Object_Query* query) +lv2_object_query(const LV2_Object* object, LV2_Object_Query* query) { int matches = 0; int n_queries = 0; @@ -196,8 +160,8 @@ lv2_object_query(const LV2_Atom* object, LV2_Object_Query* query) LV2_OBJECT_FOREACH(object, o) { const LV2_Atom_Property* prop = lv2_object_iter_get(o); for (LV2_Object_Query* q = query; q->key; ++q) { - if (q->key == prop->key && !q->value) { - q->value = &prop->value; + if (q->key == prop->key && !*q->value) { + *q->value = &prop->value; if (++matches == n_queries) return matches; break; diff --git a/ext/atom.lv2/atom.h b/ext/atom.lv2/atom.h index 61482c7..d617435 100644 --- a/ext/atom.lv2/atom.h +++ b/ext/atom.lv2/atom.h @@ -18,11 +18,8 @@ @file atom.h C header for the LV2 Atom extension . - This extension defines convenience structs that should match the definition - of the built-in types of the atom extension. The layout of atoms in this - header must match the description in RDF. The RDF description of an atom - type should be considered normative. This header is a non-normative (but - hopefully accurate) implementation of that specification. + This header describes the binary layout of various types defined in the + atom extension. */ #ifndef LV2_ATOM_H @@ -35,6 +32,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /** An LV2 Atom. @@ -45,70 +46,76 @@ (e.g. with memcpy) using the size field, except atoms with type 0. An atom with type 0 is a reference, and may only be used via the functions provided in LV2_Blob_Support (e.g. it MUST NOT be manually copied). - - Note that an LV2_Atom is the latter two fields of an LV2_Event as defined by - the LV2 events extension. The - host MAY marshal an LV2_Event to an LV2_Atom by simply pointing to the - offset of type. The macro LV2_ATOM_FROM_EVENT is provided in - this header for this purpose. */ typedef struct { - - /** - The type of this atom. - - This number is mapped from a URI using the extension - with 'map' = - "http://lv2plug.in/ns/ext/atom". Type 0 is a special case which - indicates this atom is a reference and MUST NOT be copied manually. - */ - uint16_t type; - - /** - The size of this atom, not including this header, in bytes. - */ - uint16_t size; - - /** - Size bytes of data follow here. - */ - uint8_t body[]; - + uint32_t type; /**< Type of this atom (mapped URI). */ + uint32_t size; /**< Size in bytes, not including type and size. */ + uint8_t body[]; /**< Body of length @ref size bytes. */ } LV2_Atom; /** - The body of an atom:Literal. + An atom:String. + This type may safely be cast to LV2_Atom. */ typedef struct { - uint32_t datatype; /**< The ID of the datatype of this literal */ - uint32_t lang; /**< The ID of the language of this literal */ - uint8_t str[]; /**< Null-terminated string data in UTF-8 encoding */ + uint32_t type; /**< Type of this atom (mapped URI). */ + uint32_t size; /**< Size in bytes, not including type and size. */ + uint8_t str[]; /**< Null-terminated string data in UTF-8 encoding. */ +} LV2_Atom_String; + +/** + An atom:Literal. + This type may safely be cast to LV2_Atom. +*/ +typedef struct { + uint32_t type; /**< Type of this atom (mapped URI). */ + uint32_t size; /**< Size in bytes, not including type and size. */ + uint32_t datatype; /**< The ID of the datatype of this literal. */ + uint32_t lang; /**< The ID of the language of this literal. */ + uint8_t str[]; /**< Null-terminated string data in UTF-8 encoding. */ } LV2_Atom_Literal; /** - The body of an atom:Vector. + An atom:ID. + This type may safely be cast to LV2_Atom. */ typedef struct { - uint16_t elem_count; /**< The number of elements in the vector */ - uint16_t elem_type; /**< The type of each element in the vector */ - uint8_t elems[]; /**< Sequence of element bodies */ + uint32_t type; /**< Type of this atom (mapped URI). */ + uint32_t size; /**< Size in bytes, not including type and size. */ + uint32_t id; /**< Value, a URI mapped to an integer. */ +} LV2_Atom_ID; + +/** + An atom:Vector. + This type may safely be cast to LV2_Atom. +*/ +typedef struct { + uint32_t type; /**< Type of this atom (mapped URI). */ + uint32_t size; /**< Size in bytes, not including type and size. */ + uint32_t elem_count; /**< The number of elements in the vector */ + uint32_t elem_type; /**< The type of each element in the vector */ + uint8_t elems[]; /**< Sequence of element bodies */ } LV2_Atom_Vector; /** The body of an atom:Property. + Note this type is not an LV2_Atom. */ typedef struct _LV2_Atom_Property { - uint32_t key; /**< ID of key (predicate) */ - LV2_Atom value; /**< Value (object) */ + uint32_t key; /**< Key (predicate) (mapped URI). */ + LV2_Atom value; /**< Value (object) */ } LV2_Atom_Property; /** - The body of an atom:Resource or atom:Blank. + An atom:Object (atom:Resource or atom:Blank). + This type may safely be cast to LV2_Atom. */ typedef struct { - uint32_t context; /**< ID of context graph, or 0 for default */ - uint32_t id; /**< URID (for Resource) or blank ID (for Blank) */ - uint8_t properties[]; /**< Sequence of LV2_Atom_Property */ + uint32_t type; /**< Type of this atom (mapped URI). */ + uint32_t size; /**< Size in bytes, not including type and size. */ + uint32_t context; /**< ID of context graph, or 0 for default */ + uint32_t id; /**< URID (for Resource) or blank ID (for Blank) */ + uint8_t properties[]; /**< Sequence of LV2_Atom_Property */ } LV2_Object; /** @@ -121,27 +128,9 @@ typedef struct { the @ref body field of the Event. */ typedef struct { - - /** - The frames portion of timestamp. The unit of this value may depend on - context, but for events processed by LV2_Descriptor::run() the unit is - audio frames relative to this block (e.g. frame 0 is the first frame in - this call to run()) - */ - uint32_t frames; - - /** - The sub-frames portion of timestamp. The unit of this value may depend - on context, but for events processed by LV2_Descriptor::run() the unit - is 1/(2^32) of an audio frame. - */ - uint32_t subframes; - - /** - The body of this event. - */ - LV2_Atom body; - + uint32_t frames; /**< Time in frames relative to this block. */ + uint32_t subframes; /**< Fractional time in 1/(2^32)ths of a frame. */ + LV2_Atom body; /**< Event body. */ } LV2_Atom_Event; /** @@ -208,4 +197,17 @@ typedef struct { } LV2_Atom_Buffer; -#endif /* LV2_ATOM_H */ +/** + Pad a size to 64 bits. +*/ +static inline uint32_t +lv2_atom_pad_size(uint32_t size) +{ + return (size + 7) & (~7); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_ATOM_H */ diff --git a/ext/atom.lv2/forge.h b/ext/atom.lv2/forge.h new file mode 100644 index 0000000..f1ffb03 --- /dev/null +++ b/ext/atom.lv2/forge.h @@ -0,0 +1,75 @@ +/* + Copyright 2008-2011 David Robillard + + 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 Helper constructor functions for LV2 atoms. +*/ + +#ifndef LV2_ATOM_FORGE_H +#define LV2_ATOM_FORGE_H + +#include "lv2/lv2plug.in/ns/ext/atom/atom.h" +#include "lv2/lv2plug.in/ns/ext/urid/urid.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint32_t ID; + uint32_t Message; + uint32_t Property; +} LV2_Atom_Forge; + +static inline LV2_Atom_Forge* +lv2_atom_forge_new(LV2_URID_Mapper* mapper) +{ + LV2_Atom_Forge* forge = (LV2_Atom_Forge*)malloc(sizeof(LV2_Atom_Forge)); + forge->ID = mapper->map_uri(mapper->handle, LV2_ATOM_URI "#ID"); + forge->Message = mapper->map_uri(mapper->handle, LV2_ATOM_URI "#Message"); + forge->Property = mapper->map_uri(mapper->handle, LV2_ATOM_URI "#Property"); + return forge; +} + +static inline void +lv2_atom_forge_free(LV2_Atom_Forge* forge) +{ + free(forge); +} + +static inline LV2_Atom_ID +lv2_atom_forge_make_id(LV2_Atom_Forge* forge, uint32_t id) +{ + const LV2_Atom_ID atom = { forge->ID, sizeof(uint32_t), id }; + return atom; +} + +static inline void +lv2_atom_forge_set_message(LV2_Atom_Forge* forge, + LV2_Object* msg, + uint32_t id) +{ + msg->type = forge->Message; + msg->size = sizeof(LV2_Object) - sizeof(LV2_Atom); + msg->context = 0; + msg->id = id; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_ATOM_FORGE_H */ -- cgit v1.2.1