aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-03-02 00:03:53 +0000
committerDavid Robillard <d@drobilla.net>2012-03-02 00:03:53 +0000
commit6a848b53ef158648a4dc25274afeb668c530abd9 (patch)
treeac346e53c87f379a1e6ca082b0963b6394b7498f
parent88135c7bb27557e214928918ca46ecb86c790a0b (diff)
downloadlv2-6a848b53ef158648a4dc25274afeb668c530abd9.tar.xz
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.
-rw-r--r--lv2/lv2plug.in/ns/ext/atom/atom-test.c24
-rw-r--r--lv2/lv2plug.in/ns/ext/atom/atom.h5
-rw-r--r--lv2/lv2plug.in/ns/ext/atom/atom.ttl21
-rw-r--r--lv2/lv2plug.in/ns/ext/atom/forge.h74
4 files changed, 85 insertions, 39 deletions
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<Int32>)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 """
<p>A homogeneous series of atom bodies with equivalent type and size.</p>
-<p>An LV2_Atom_Vector is a 32-bit <code>elem_count</code> and
-<code>elem_type</code> followed by <code>elem_count</code> atom bodies of type
-<code>elem_type</code>. The element type must be a fixed size atom:Atom type,
-i.e. the size of each element is the vector's <code>size /
-elem_count</code>.</p>
+<p>An LV2_Atom_Vector is a 32-bit <code>child_size</code> and
+<code>child_type</code> followed by <code>size / child_size</code> atom
+bodies.</p>
<p>For example, an atom:Vector containing 42 elements of type atom:Float:</p>
<pre class="c-code">
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];
};
</pre>
<p>Note that it is possible to construct a valid Atom for each element
of the vector, even by an implementation which does not understand
-<code>elem_type</code>.</p>
+<code>child_type</code>.</p>
""" .
atom:Tuple
@@ -497,6 +495,11 @@ connected to. It says nothing about the expected contents of containers. For
that, use atom:supports.</p>
""" .
+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);