From 6a848b53ef158648a4dc25274afeb668c530abd9 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 2 Mar 2012 00:03:53 +0000 Subject: Add atom:childType. Rename vector fields for consistently with atom:childType. Change vector to have child type and size rather than num_elems, since that would require updating the body every time an element is added which ruins the usual atom construction pattern. Implement incremental/automatic vector building with forge. --- lv2/lv2plug.in/ns/ext/atom/atom-test.c | 24 ++++++++++- lv2/lv2plug.in/ns/ext/atom/atom.h | 5 ++- lv2/lv2plug.in/ns/ext/atom/atom.ttl | 21 +++++----- lv2/lv2plug.in/ns/ext/atom/forge.h | 74 ++++++++++++++++++++++------------ 4 files changed, 85 insertions(+), 39 deletions(-) (limited to 'lv2/lv2plug.in/ns') diff --git a/lv2/lv2plug.in/ns/ext/atom/atom-test.c b/lv2/lv2plug.in/ns/ext/atom/atom-test.c index addad81..c92a370 100644 --- a/lv2/lv2plug.in/ns/ext/atom/atom-test.c +++ b/lv2/lv2plug.in/ns/ext/atom/atom-test.c @@ -79,10 +79,11 @@ main() LV2_URID eg_literal = urid_map(NULL, "http://example.org/literal"); LV2_URID eg_tuple = urid_map(NULL, "http://example.org/tuple"); LV2_URID eg_vector = urid_map(NULL, "http://example.org/vector"); + LV2_URID eg_vector2 = urid_map(NULL, "http://example.org/vector2"); LV2_URID eg_seq = urid_map(NULL, "http://example.org/seq"); #define BUF_SIZE 1024 -#define NUM_PROPS 14 +#define NUM_PROPS 15 uint8_t buf[BUF_SIZE]; lv2_atom_forge_set_buffer(&forge, buf, BUF_SIZE); @@ -230,12 +231,26 @@ main() int32_t elems[] = { 1, 2, 3, 4 }; LV2_Atom_Vector* vector = (LV2_Atom_Vector*)lv2_atom_forge_deref( &forge, lv2_atom_forge_vector( - &forge, 4, forge.Int32, sizeof(int32_t), elems));; + &forge, sizeof(int32_t), forge.Int32, 4, elems)); void* vec_body = LV2_ATOM_CONTENTS(LV2_Atom_Vector, vector); if (memcmp(elems, vec_body, sizeof(elems))) { return test_fail("Corrupt vector\n"); } + // eg_vector2 = (Vector)1,2,3,4 + lv2_atom_forge_property_head(&forge, eg_vector2, 0); + LV2_Atom_Forge_Frame vec_frame; + LV2_Atom_Vector* vector2 = (LV2_Atom_Vector*)lv2_atom_forge_deref( + &forge, lv2_atom_forge_vector_head( + &forge, &vec_frame, sizeof(int32_t), forge.Int32)); + for (unsigned i = 0; i < sizeof(elems) / sizeof(int32_t); ++i) { + lv2_atom_forge_int32(&forge, elems[i]); + } + lv2_atom_forge_pop(&forge, &vec_frame); + if (!lv2_atom_equals(&vector->atom, &vector2->atom)) { + return test_fail("Vector != Vector2\n"); + } + // eg_seq = (Sequence)1, 2 lv2_atom_forge_property_head(&forge, eg_seq, 0); LV2_Atom_Forge_Frame seq_frame; @@ -302,6 +317,7 @@ main() const LV2_Atom* literal; const LV2_Atom* tuple; const LV2_Atom* vector; + const LV2_Atom* vector2; const LV2_Atom* seq; } matches; @@ -321,6 +337,7 @@ main() { eg_literal, &matches.literal }, { eg_tuple, &matches.tuple }, { eg_vector, &matches.vector }, + { eg_vector2, &matches.vector2 }, { eg_seq, &matches.seq }, LV2_OBJECT_QUERY_END }; @@ -354,6 +371,8 @@ main() return test_fail("Bad match tuple\n"); } else if (!lv2_atom_equals((LV2_Atom*)vector, matches.vector)) { return test_fail("Bad match vector\n"); + } else if (!lv2_atom_equals((LV2_Atom*)vector, matches.vector2)) { + return test_fail("Bad match vector2\n"); } else if (!lv2_atom_equals((LV2_Atom*)seq, matches.seq)) { return test_fail("Bad match sequence\n"); } @@ -372,6 +391,7 @@ main() eg_literal, &matches.literal, eg_tuple, &matches.tuple, eg_vector, &matches.vector, + eg_vector2, &matches.vector2, eg_seq, &matches.seq, 0); } diff --git a/lv2/lv2plug.in/ns/ext/atom/atom.h b/lv2/lv2plug.in/ns/ext/atom/atom.h index 2eed233..abb0eea 100644 --- a/lv2/lv2plug.in/ns/ext/atom/atom.h +++ b/lv2/lv2plug.in/ns/ext/atom/atom.h @@ -54,6 +54,7 @@ #define LV2_ATOM__URID LV2_ATOM_URI "#URID" #define LV2_ATOM__ValuePort LV2_ATOM_URI "#ValuePort" #define LV2_ATOM__Vector LV2_ATOM_URI "#Vector" +#define LV2_ATOM__childType LV2_ATOM_URI "#childType" #define LV2_ATOM__beatTime LV2_ATOM_URI "#beatTime" #define LV2_ATOM__bufferType LV2_ATOM_URI "#bufferType" #define LV2_ATOM__eventTransfer LV2_ATOM_URI "#eventTransfer" @@ -152,8 +153,8 @@ typedef struct { /** The body of an atom:Vector. */ typedef struct { - uint32_t elem_count; /**< The number of elements in the vector */ - uint32_t elem_type; /**< The type of each element in the vector */ + uint32_t child_size; /**< The size of each element in the vector. */ + uint32_t child_type; /**< The type of each element in the vector. */ /* Contents (a series of packed atom bodies) follow here. */ } LV2_Atom_Vector_Body; diff --git a/lv2/lv2plug.in/ns/ext/atom/atom.ttl b/lv2/lv2plug.in/ns/ext/atom/atom.ttl index 1a2b92a..1b2ed1d 100644 --- a/lv2/lv2plug.in/ns/ext/atom/atom.ttl +++ b/lv2/lv2plug.in/ns/ext/atom/atom.ttl @@ -262,26 +262,24 @@ atom:Vector lv2:documentation """

A homogeneous series of atom bodies with equivalent type and size.

-

An LV2_Atom_Vector is a 32-bit elem_count and -elem_type followed by elem_count atom bodies of type -elem_type. The element type must be a fixed size atom:Atom type, -i.e. the size of each element is the vector's size / -elem_count.

+

An LV2_Atom_Vector is a 32-bit child_size and +child_type followed by size / child_size atom +bodies.

For example, an atom:Vector containing 42 elements of type atom:Float:

 struct VectorOf42Floats {
+    uint32_t size;        // sizeof(LV2_Atom_Vector_Body) + (42 * sizeof(float);
     uint32_t type;        // map(expand("atom:Vector"))
-    uint32_t size;        // sizeof(LV2_Atom_Vector) + (42 * sizeof(float);
-    uint32_t elem_count;  // 42
-    uint32_t elem_type;   // map(expand("atom:Float"))
+    uint32_t child_size;  // sizeof(float)
+    uint32_t child_type;  // map(expand("atom:Float"))
     float    elems[42];
 };
 

Note that it is possible to construct a valid Atom for each element of the vector, even by an implementation which does not understand -elem_type.

+child_type.

""" . atom:Tuple @@ -497,6 +495,11 @@ connected to. It says nothing about the expected contents of containers. For that, use atom:supports.

""" . +atom:childType + a rdf:Property ; + rdfs:label "Child type" ; + rdfs:comment "The type of a container's children." . + atom:supports a rdf:Property ; rdfs:label "Supports" ; diff --git a/lv2/lv2plug.in/ns/ext/atom/forge.h b/lv2/lv2plug.in/ns/ext/atom/forge.h index b3a5e4d..c1b6d31 100644 --- a/lv2/lv2plug.in/ns/ext/atom/forge.h +++ b/lv2/lv2plug.in/ns/ext/atom/forge.h @@ -65,7 +65,7 @@ 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 void* (*LV2_Atom_Forge_Deref_Func)( +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. */ @@ -261,12 +261,31 @@ lv2_atom_forge_atom(LV2_Atom_Forge* forge, uint32_t size, uint32_t type) return lv2_atom_forge_raw(forge, &a, sizeof(a)); } +/** 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; +} + +/** 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:Int32. */ static inline LV2_Atom_Forge_Ref lv2_atom_forge_int32(LV2_Atom_Forge* forge, int32_t val) { const LV2_Atom_Int32 a = { { sizeof(val), forge->Int32 }, val }; - return lv2_atom_forge_write(forge, &a, sizeof(a)); + return lv2_atom_forge_primitive(forge, &a.atom); } /** Write an atom:Int64. */ @@ -274,7 +293,7 @@ static inline LV2_Atom_Forge_Ref lv2_atom_forge_int64(LV2_Atom_Forge* forge, int64_t val) { const LV2_Atom_Int64 a = { { sizeof(val), forge->Int64 }, val }; - return lv2_atom_forge_write(forge, &a, sizeof(a)); + return lv2_atom_forge_primitive(forge, &a.atom); } /** Write an atom:Float. */ @@ -282,7 +301,7 @@ 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_write(forge, &a, sizeof(a)); + return lv2_atom_forge_primitive(forge, &a.atom); } /** Write an atom:Double. */ @@ -290,7 +309,7 @@ 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_write(forge, &a, sizeof(a)); + return lv2_atom_forge_primitive(forge, &a.atom); } /** Write an atom:Bool. */ @@ -298,7 +317,7 @@ static inline LV2_Atom_Forge_Ref lv2_atom_forge_bool(LV2_Atom_Forge* forge, bool val) { const LV2_Atom_Bool a = { { sizeof(val), forge->Bool }, val }; - return lv2_atom_forge_write(forge, &a, sizeof(a)); + return lv2_atom_forge_primitive(forge, &a.atom); } /** Write an atom:URID. */ @@ -306,7 +325,7 @@ 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_write(forge, &a, sizeof(a)); + return lv2_atom_forge_primitive(forge, &a.atom); } /** Write a string body. Used internally. */ @@ -392,33 +411,36 @@ lv2_atom_forge_literal(LV2_Atom_Forge* forge, return out; } -/** Write an atom:Vector header, but not the vector body. */ +/** Start an atom:Vector. */ static inline LV2_Atom_Forge_Ref -lv2_atom_forge_vector_head(LV2_Atom_Forge* forge, - uint32_t elem_count, - uint32_t elem_type, - uint32_t elem_size) +lv2_atom_forge_vector_head(LV2_Atom_Forge* forge, + LV2_Atom_Forge_Frame* frame, + uint32_t child_size, + uint32_t child_type) { - const uint32_t size = sizeof(LV2_Atom_Vector) + (elem_size * elem_count); const LV2_Atom_Vector a = { - { size - sizeof(LV2_Atom), forge->Vector }, - { elem_count, elem_type } + { sizeof(LV2_Atom_Vector_Body), forge->Vector }, + { child_size, child_type } }; - return lv2_atom_forge_write(forge, &a, sizeof(a)); + 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 elem_count, - uint32_t elem_type, - uint32_t elem_size, + uint32_t child_size, + uint32_t child_type, + uint32_t n_elems, const void* elems) { - LV2_Atom_Forge_Ref out = lv2_atom_forge_vector_head( - forge, elem_count, elem_type, elem_size); + 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, elem_size * elem_count); + lv2_atom_forge_write(forge, elems, child_size * n_elems); } return out; } @@ -443,9 +465,9 @@ lv2_atom_forge_vector(LV2_Atom_Forge* forge, 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 } }; - LV2_Atom_Forge_Ref out = lv2_atom_forge_write(forge, &a, sizeof(a)); - return lv2_atom_forge_push(forge, frame, out); + const LV2_Atom_Tuple a = { { 0, forge->Tuple } }; + return lv2_atom_forge_push( + forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a))); } /** @@ -462,7 +484,7 @@ lv2_atom_forge_tuple(LV2_Atom_Forge* forge, LV2_Atom_Forge_Frame* frame) // Write object header LV2_Atom_Forge_Frame frame; - LV2_Atom* obj = (LV2_Atom*)lv2_atom_forge_resource(forge, &frame, 1, eg_Cat); + lv2_atom_forge_resource(forge, &frame, 1, eg_Cat); // Write property: eg:name = "Hobbes" lv2_atom_forge_property_head(forge, eg_name, 0); -- cgit v1.2.1