aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-02-23 01:53:15 +0000
committerDavid Robillard <d@drobilla.net>2012-02-23 01:53:15 +0000
commitc2cc2607f8d5b9eea933a18abd91b2ce708fc90c (patch)
tree9923ca1257024897eccad5aae61c74cd37ce6609
parentc69ce6e891824fc64022a3615542fc30edc89cd7 (diff)
downloadlv2-c2cc2607f8d5b9eea933a18abd91b2ce708fc90c.tar.xz
Separately define body types for atoms with non-trivial bodies so the type definitions are useful when only the body is available (e.g. state API).
Use a single int64_t stamp for frame times since range is more important now and subframes was never really used anyway. Add atom:frameTime and atom:beatTime for serialising events. Consistently use name "body" for all types of atom bodies. Add lv2_atom_forge_atom() and lv2_atom_forge_raw() for constructing arbitrary atoms. Merge similar string-like forge methods. Update language URI requirements to match current (and hopefully permanent, geeze) http://lexvo.org reality.
-rw-r--r--lv2/lv2plug.in/ns/ext/atom/atom-test.c39
-rw-r--r--lv2/lv2plug.in/ns/ext/atom/atom.h128
-rw-r--r--lv2/lv2plug.in/ns/ext/atom/atom.ttl40
-rw-r--r--lv2/lv2plug.in/ns/ext/atom/forge.h122
-rw-r--r--lv2/lv2plug.in/ns/ext/atom/manifest.ttl2
-rw-r--r--lv2/lv2plug.in/ns/ext/atom/util.h82
-rw-r--r--plugins/eg-sampler.lv2/sampler.c8
-rw-r--r--plugins/eg-sampler.lv2/uris.h4
8 files changed, 245 insertions, 180 deletions
diff --git a/lv2/lv2plug.in/ns/ext/atom/atom-test.c b/lv2/lv2plug.in/ns/ext/atom/atom-test.c
index 8e56c79..7e90c15 100644
--- a/lv2/lv2plug.in/ns/ext/atom/atom-test.c
+++ b/lv2/lv2plug.in/ns/ext/atom/atom-test.c
@@ -94,43 +94,43 @@ main()
// eg_one = (Int32)1
lv2_atom_forge_property_head(&forge, eg_one, 0);
LV2_Atom_Int32* one = lv2_atom_forge_int32(&forge, 1);
- if (one->value != 1) {
- return test_fail("%d != 1\n", one->value);
+ if (one->body != 1) {
+ return test_fail("%d != 1\n", one->body);
}
// eg_two = (Int64)2
lv2_atom_forge_property_head(&forge, eg_two, 0);
LV2_Atom_Int64* two = lv2_atom_forge_int64(&forge, 2);
- if (two->value != 2) {
- return test_fail("%ld != 2\n", two->value);
+ if (two->body != 2) {
+ return test_fail("%ld != 2\n", two->body);
}
// eg_three = (Float)3.0
lv2_atom_forge_property_head(&forge, eg_three, 0);
LV2_Atom_Float* three = lv2_atom_forge_float(&forge, 3.0f);
- if (three->value != 3) {
- return test_fail("%f != 3\n", three->value);
+ if (three->body != 3) {
+ return test_fail("%f != 3\n", three->body);
}
// eg_four = (Double)4.0
lv2_atom_forge_property_head(&forge, eg_four, 0);
LV2_Atom_Double* four = lv2_atom_forge_double(&forge, 4.0);
- if (four->value != 4) {
- return test_fail("%ld != 4\n", four->value);
+ if (four->body != 4) {
+ return test_fail("%ld != 4\n", four->body);
}
// eg_true = (Bool)1
lv2_atom_forge_property_head(&forge, eg_true, 0);
LV2_Atom_Bool* t = lv2_atom_forge_bool(&forge, true);
- if (t->value != 1) {
- return test_fail("%ld != 1 (true)\n", t->value);
+ if (t->body != 1) {
+ return test_fail("%ld != 1 (true)\n", t->body);
}
// eg_false = (Bool)0
lv2_atom_forge_property_head(&forge, eg_false, 0);
LV2_Atom_Bool* f = lv2_atom_forge_bool(&forge, false);
- if (f->value != 0) {
- return test_fail("%ld != 0 (false)\n", f->value);
+ if (f->body != 0) {
+ return test_fail("%ld != 0 (false)\n", f->body);
}
// eg_path = (Path)"/foo/bar"
@@ -159,8 +159,8 @@ main()
LV2_URID eg_value = urid_map(NULL, "http://example.org/value");
lv2_atom_forge_property_head(&forge, eg_urid, 0);
LV2_Atom_URID* urid = lv2_atom_forge_urid(&forge, eg_value);
- if (urid->id != eg_value) {
- return test_fail("%u != %u\n", urid->id, eg_value);
+ if (urid->body != eg_value) {
+ return test_fail("%u != %u\n", urid->body, eg_value);
}
// eg_string = (String)"hello"
@@ -226,9 +226,9 @@ main()
lv2_atom_forge_property_head(&forge, eg_seq, 0);
LV2_Atom_Forge_Frame seq_frame;
LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)lv2_atom_forge_sequence_head(&forge, &seq_frame, 0);
- lv2_atom_forge_audio_time(&forge, 0, 0);
+ lv2_atom_forge_frame_time(&forge, 0);
lv2_atom_forge_int32(&forge, 1);
- lv2_atom_forge_audio_time(&forge, 1, 0);
+ lv2_atom_forge_frame_time(&forge, 1);
lv2_atom_forge_int32(&forge, 2);
lv2_atom_forge_pop(&forge, &seq_frame);
@@ -240,17 +240,18 @@ main()
return test_fail("1 == 2.0\n");
} else if (lv2_atom_equals((LV2_Atom*)one, (LV2_Atom*)&itwo)) {
return test_fail("1 == 2\n");
+ } else if (!lv2_atom_equals((LV2_Atom*)one, (LV2_Atom*)one)) {
+ return test_fail("1 != 1\n");
}
unsigned n_events = 0;
LV2_SEQUENCE_FOREACH(seq, i) {
LV2_Atom_Event* ev = lv2_sequence_iter_get(i);
- if (ev->time.audio.frames != n_events
- || ev->time.audio.subframes != 0) {
+ if (ev->time.frames != n_events) {
return test_fail("Corrupt event %u has bad time\n", n_events);
} else if (ev->body.type != forge.Int32) {
return test_fail("Corrupt event %u has bad type\n", n_events);
- } else if (((LV2_Atom_Int32*)&ev->body)->value != (int)n_events + 1) {
+ } else if (((LV2_Atom_Int32*)&ev->body)->body != (int)n_events + 1) {
return test_fail("Event %u != %d\n", n_events, n_events + 1);
}
++n_events;
diff --git a/lv2/lv2plug.in/ns/ext/atom/atom.h b/lv2/lv2plug.in/ns/ext/atom/atom.h
index 3609cc9..6f104e2 100644
--- a/lv2/lv2plug.in/ns/ext/atom/atom.h
+++ b/lv2/lv2plug.in/ns/ext/atom/atom.h
@@ -28,34 +28,37 @@
#define LV2_ATOM_URI "http://lv2plug.in/ns/ext/atom"
#define LV2_ATOM__Atom LV2_ATOM_URI "#Atom"
-#define LV2_ATOM__Number LV2_ATOM_URI "#Number"
+#define LV2_ATOM__AtomPort LV2_ATOM_URI "#AtomPort"
+#define LV2_ATOM__AudioFrames LV2_ATOM_URI "#AudioFrames"
+#define LV2_ATOM__Beats LV2_ATOM_URI "#Beats"
+#define LV2_ATOM__Blank LV2_ATOM_URI "#Blank"
+#define LV2_ATOM__Bool LV2_ATOM_URI "#Bool"
+#define LV2_ATOM__Double LV2_ATOM_URI "#Double"
+#define LV2_ATOM__Event LV2_ATOM_URI "#Event"
+#define LV2_ATOM__Float LV2_ATOM_URI "#Float"
#define LV2_ATOM__Int32 LV2_ATOM_URI "#Int32"
#define LV2_ATOM__Int64 LV2_ATOM_URI "#Int64"
-#define LV2_ATOM__Float LV2_ATOM_URI "#Float"
-#define LV2_ATOM__Double LV2_ATOM_URI "#Double"
-#define LV2_ATOM__Bool LV2_ATOM_URI "#Bool"
-#define LV2_ATOM__String LV2_ATOM_URI "#String"
#define LV2_ATOM__Literal LV2_ATOM_URI "#Literal"
+#define LV2_ATOM__MessagePort LV2_ATOM_URI "#MessagePort"
+#define LV2_ATOM__Number LV2_ATOM_URI "#Number"
+#define LV2_ATOM__Object LV2_ATOM_URI "#Object"
#define LV2_ATOM__Path LV2_ATOM_URI "#Path"
-#define LV2_ATOM__URI LV2_ATOM_URI "#URI"
-#define LV2_ATOM__URID LV2_ATOM_URI "#URID"
-#define LV2_ATOM__Vector LV2_ATOM_URI "#Vector"
-#define LV2_ATOM__Tuple LV2_ATOM_URI "#Tuple"
#define LV2_ATOM__Property LV2_ATOM_URI "#Property"
-#define LV2_ATOM__Object LV2_ATOM_URI "#Object"
#define LV2_ATOM__Resource LV2_ATOM_URI "#Resource"
-#define LV2_ATOM__Blank LV2_ATOM_URI "#Blank"
-#define LV2_ATOM__TimeUnit LV2_ATOM_URI "#TimeUnit"
-#define LV2_ATOM__AudioFrames LV2_ATOM_URI "#AudioFrames"
-#define LV2_ATOM__Beats LV2_ATOM_URI "#Beats"
-#define LV2_ATOM__Event LV2_ATOM_URI "#Event"
#define LV2_ATOM__Sequence LV2_ATOM_URI "#Sequence"
-#define LV2_ATOM__AtomPort LV2_ATOM_URI "#AtomPort"
+#define LV2_ATOM__String LV2_ATOM_URI "#String"
+#define LV2_ATOM__TimeUnit LV2_ATOM_URI "#TimeUnit"
+#define LV2_ATOM__Tuple LV2_ATOM_URI "#Tuple"
+#define LV2_ATOM__URI LV2_ATOM_URI "#URI"
+#define LV2_ATOM__URID LV2_ATOM_URI "#URID"
#define LV2_ATOM__ValuePort LV2_ATOM_URI "#ValuePort"
-#define LV2_ATOM__MessagePort LV2_ATOM_URI "#MessagePort"
+#define LV2_ATOM__Vector LV2_ATOM_URI "#Vector"
+#define LV2_ATOM__beatTime LV2_ATOM_URI "#beatTime"
#define LV2_ATOM__bufferType LV2_ATOM_URI "#bufferType"
-#define LV2_ATOM__supports LV2_ATOM_URI "#supports"
#define LV2_ATOM__eventTransfer LV2_ATOM_URI "#eventTransfer"
+#define LV2_ATOM__frameTime LV2_ATOM_URI "#frameTime"
+#define LV2_ATOM__supports LV2_ATOM_URI "#supports"
+#define LV2_ATOM__timeUnit LV2_ATOM_URI "#timeUnit"
#define LV2_ATOM_REFERENCE_TYPE 0
@@ -68,14 +71,18 @@ typedef char lv2_atom_assert_double_fits_in_64_bits[
((sizeof(double) <= sizeof(uint64_t)) * 2) - 1];
/**
- Return a pointer to the contents of an Atom.
+ Return a pointer to the contents of an Atom. The "contents" of an atom
+ is the data past the complete type-specific header.
@param type The type of the atom, e.g. LV2_Atom_String.
@param atom A variable-sized atom.
*/
#define LV2_ATOM_CONTENTS(type, atom) \
((void*)((uint8_t*)(atom) + sizeof(type)))
-/** Return a pointer to the body of @p atom (just past the LV2_Atom head). */
+/**
+ Return a pointer to the body of an Atom. The "body" of an atom is the
+ data just past the LV2_Atom head (i.e. the same offset for all types).
+*/
#define LV2_ATOM_BODY(atom) LV2_ATOM_CONTENTS(LV2_Atom, atom)
/** The header of an atom:Atom. */
@@ -86,26 +93,26 @@ typedef struct {
/** An atom:Int32 or atom:Bool. May be cast to LV2_Atom. */
typedef struct {
- LV2_Atom atom; /**< Atom header. */
- int32_t value; /**< Integer value. */
+ LV2_Atom atom; /**< Atom header. */
+ int32_t body; /**< Integer value. */
} LV2_Atom_Int32;
/** An atom:Int64. May be cast to LV2_Atom. */
typedef struct {
- LV2_Atom atom; /**< Atom header. */
- int64_t value; /**< Integer value. */
+ LV2_Atom atom; /**< Atom header. */
+ int64_t body; /**< Integer value. */
} LV2_Atom_Int64;
/** An atom:Float. May be cast to LV2_Atom. */
typedef struct {
- LV2_Atom atom; /**< Atom header. */
- float value; /**< Floating point value. */
+ LV2_Atom atom; /**< Atom header. */
+ float body; /**< Floating point value. */
} LV2_Atom_Float;
/** An atom:Double. May be cast to LV2_Atom. */
typedef struct {
- LV2_Atom atom; /**< Atom header. */
- double value; /**< Floating point value. */
+ LV2_Atom atom; /**< Atom header. */
+ double body; /**< Floating point value. */
} LV2_Atom_Double;
/** An atom:Bool. May be cast to LV2_Atom. */
@@ -114,83 +121,87 @@ typedef LV2_Atom_Int32 LV2_Atom_Bool;
/** An atom:URID. May be cast to LV2_Atom. */
typedef struct {
LV2_Atom atom; /**< Atom header. */
- uint32_t id; /**< URID. */
+ uint32_t body; /**< URID. */
} LV2_Atom_URID;
-/** The complete header of an atom:String. */
+/** An atom:String. May be cast to LV2_Atom. */
typedef struct {
LV2_Atom atom; /**< Atom header. */
/* Contents (a null-terminated UTF-8 string) follow here. */
} LV2_Atom_String;
-/** The complete header of an atom:Literal. */
+/** The body of an atom:Literal. */
typedef struct {
- LV2_Atom atom; /**< Atom header. */
uint32_t datatype; /**< Datatype URID. */
uint32_t lang; /**< Language URID. */
/* Contents (a null-terminated UTF-8 string) follow here. */
+} LV2_Atom_Literal_Body;
+
+/** An atom:Literal. May be cast to LV2_Atom. */
+typedef struct {
+ LV2_Atom atom; /**< Atom header. */
+ LV2_Atom_Literal_Body body; /**< Body. */
} LV2_Atom_Literal;
-/** The complete header of an atom:Tuple. */
+/** An atom:Tuple. May be cast to LV2_Atom. */
typedef struct {
LV2_Atom atom; /**< Atom header. */
/* Contents (a series of complete atoms) follow here. */
} LV2_Atom_Tuple;
-/** The complete header of an atom:Vector. */
+/** The body of an atom:Vector. */
typedef struct {
- LV2_Atom atom; /**< Atom header. */
uint32_t elem_count; /**< The number of elements in the vector */
uint32_t elem_type; /**< The type of each element in the vector */
/* Contents (a series of packed atom bodies) follow here. */
+} LV2_Atom_Vector_Body;
+
+/** An atom:Vector. May be cast to LV2_Atom. */
+typedef struct {
+ LV2_Atom atom; /**< Atom header. */
+ LV2_Atom_Vector_Body body; /**< Body. */
} LV2_Atom_Vector;
-/** The header of an atom:Property body (e.g. in an atom:Object). */
+/** The body of an atom:Property (e.g. in an atom:Object). */
typedef struct {
uint32_t key; /**< Key (predicate) (mapped URI). */
uint32_t context; /**< Context URID (may be, and generally is, 0). */
LV2_Atom value; /**< Value atom header. */
+ /* Value atom body follows here. */
} LV2_Atom_Property_Body;
-/** The complete header of an atom:Property. */
+/** An atom:Property. May be cast to LV2_Atom. */
typedef struct {
- LV2_Atom atom; /**< Atom header. */
- uint32_t key; /**< Key (predicate) (mapped URI). */
- uint32_t context; /**< Context URID (may be, and generally is, 0). */
- LV2_Atom value; /**< Value atom header. */
- /* Value atom body follows here. */
+ LV2_Atom atom; /**< Atom header. */
+ LV2_Atom_Property_Body body; /**< Body. */
} LV2_Atom_Property;
-/** The complete header of an atom:Object. */
+/** The body of an atom:Object. May be cast to LV2_Atom. */
typedef struct {
- LV2_Atom atom; /**< Atom header. */
uint32_t id; /**< URID (atom:Resource) or blank ID (atom:Blank). */
uint32_t otype; /**< Type URID (same as rdf:type, for fast dispatch). */
/* Contents (a series of property bodies) follow here. */
-} LV2_Atom_Object;
+} LV2_Atom_Object_Body;
-/** A time stamp in frames. Note this type is NOT an LV2_Atom. */
+/** An atom:Object. May be cast to LV2_Atom. */
typedef struct {
- 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_Audio_Time;
+ LV2_Atom atom; /**< Atom header. */
+ LV2_Atom_Object_Body body; /**< Body. */
+} LV2_Atom_Object;
/** The header of an atom:Event. Note this type is NOT an LV2_Atom. */
typedef struct {
/** Time stamp. Which type is valid is determined by context. */
union {
- LV2_Atom_Audio_Time audio; /**< Time in audio frames. */
- double beats; /**< Time in beats. */
+ int64_t frames; /**< Time in audio frames. */
+ double beats; /**< Time in beats. */
} time;
LV2_Atom body; /**< Event body atom header. */
/* Body atom contents follow here. */
} LV2_Atom_Event;
/**
- A sequence of events (time-stamped atoms).
-
- This is used as the contents of an atom:EventPort, but is a generic Atom
- type which can be used anywhere.
+ The body of an atom:Sequence (a sequence of events).
The unit field is either a URID that described an appropriate time stamp
type, or may be 0 where a default stamp type is known. For
@@ -207,10 +218,15 @@ typedef struct {
</pre>
*/
typedef struct {
- LV2_Atom atom; /**< Atom header. */
uint32_t unit; /**< URID of unit of event time stamps. */
uint32_t pad; /**< Currently unused. */
/* Contents (a series of events) follow here. */
+} LV2_Atom_Sequence_Body;
+
+/** An atom:Sequence. */
+typedef struct {
+ LV2_Atom atom; /**< Atom header. */
+ LV2_Atom_Literal_Body body; /**< Body. */
} LV2_Atom_Sequence;
/**
diff --git a/lv2/lv2plug.in/ns/ext/atom/atom.ttl b/lv2/lv2plug.in/ns/ext/atom/atom.ttl
index e6b5207..b939f33 100644
--- a/lv2/lv2plug.in/ns/ext/atom/atom.ttl
+++ b/lv2/lv2plug.in/ns/ext/atom/atom.ttl
@@ -30,14 +30,14 @@
rdfs:seeAlso <util.h> ,
<forge.h> ;
doap:release [
- doap:revision "0.5" ;
- doap:created "2012-02-18"
+ doap:revision "0.6" ;
+ doap:created "2012-02-22" ;
] ;
doap:maintainer [
a foaf:Person ;
foaf:name "David Robillard" ;
foaf:homepage <http://drobilla.net/> ;
- rdfs:seeAlso <http://drobilla.net/drobilla.rdf>
+ rdfs:seeAlso <http://drobilla.net/drobilla.rdf> ;
] ;
lv2:documentation """
<p>This extension defines a generic container for data, called an <q>Atom</q>,
@@ -177,9 +177,8 @@ string in any language or a value of any type. A Literal has a
encoding. The length of the string data in bytes is <code>size -
sizeof(LV2_Atom_Literal)</code>, including the terminating NULL character. The
<code>lang</code> field SHOULD be a URI of the form
-&lt;http://lexvo.org/id/term/LANG&gt; where LANG is an <a
-href="http://www.loc.gov/standards/iso639-2/">ISO 693-2</a> or <a
-href="http://www.loc.gov/standards/iso639-2/">ISO 693-3</a> language code.</p>
+&lt;http://lexvo.org/id/iso639-3/LANG&gt; where LANG is an <a
+href="http://www.loc.gov/standards/iso639-3/">ISO 693-3</a> language code.</p>
<p>A Literal may have a <code>datatype</code> OR a <code>lang</code>, but never
both.</p>
@@ -190,7 +189,7 @@ void set_to_hello_in_english(LV2_Atom_Literal* lit) {
lit->atom.type = map(expand("atom:Literal"));
lit->atom.size = 14;
lit->datatype = 0;
- lit->lang = map("http://lexvo.org/id/term/en");
+ lit->lang = map("http://lexvo.org/id/iso639-3/eng");
memcpy(LV2_ATOM_CONTENTS(LV2_Atom_Literal, lit),
"Hello",
sizeof("Hello")); // Assumes enough space
@@ -265,7 +264,7 @@ struct VectorOf42Floats {
uint32_t size; // sizeof(LV2_Atom_Vector) + (42 * sizeof(float);
uint32_t elem_count; // 42
uint32_t elem_type; // map(expand("atom:Float"))
- float elems[32];
+ float elems[42];
};
</pre>
@@ -347,14 +346,31 @@ atom:TimeUnit
rdfs:label "Time Unit" ;
lv2:documentation "<p>A unit for atom:Event time stamps.</p>" .
-atom:AudioFrames
+atom:frameTime
+ a rdfs:Property ;
+ rdfs:range xsd:decimal ;
+ rdfs:label "Frame time" ;
+ lv2:documentation """
+<p>Time stamp in audio frames. Typically used for events.</p>
+""" .
+
+atom:beatTime
+ a rdfs:Property ;
+ rdfs:range xsd:decimal ;
+ rdfs:label "Beat time" ;
+ lv2:documentation """
+<p>Time stamp in beats. Typically used for events.</p>
+""" .
+
+atom:Frames
a rdfs:Class ;
rdfs:subClassOf atom:TimeUnit ;
- rdfs:label "Audio frames" ;
+ rdfs:label "Frames" ;
lv2:documentation """
<p>Time in audio frames. Converting this to absolute time depends on the
-sample rate. When this is the stamp unit for an atom:Sequence, the events in
-that sequence have LV2_Atom_Audio_Time stamps (<code>event.time.audio</code>)</p>""" .
+sample rate. When this is the stamp unit for an atom:Sequence, its events have
+int64_t time stamps (<code>event.time.frames</code>)</p>
+""" .
atom:Beats
a rdfs:Class ;
diff --git a/lv2/lv2plug.in/ns/ext/atom/forge.h b/lv2/lv2plug.in/ns/ext/atom/forge.h
index 9c553d2..5ad6d1d 100644
--- a/lv2/lv2plug.in/ns/ext/atom/forge.h
+++ b/lv2/lv2plug.in/ns/ext/atom/forge.h
@@ -185,10 +185,13 @@ lv2_atom_forge_init(LV2_Atom_Forge* forge, LV2_URID_Map* map)
forge->Vector = map->map(map->handle, LV2_ATOM_URI "#Vector");
}
+/**
+ 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 void*
-lv2_atom_forge_write_nopad(LV2_Atom_Forge* forge,
- const void* data,
- uint32_t size)
+lv2_atom_forge_raw(LV2_Atom_Forge* forge, const void* data, uint32_t size)
{
uint8_t* out = NULL;
if (forge->sink) {
@@ -209,27 +212,34 @@ lv2_atom_forge_write_nopad(LV2_Atom_Forge* forge,
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)
+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_write_nopad(forge, &pad, pad_size);
+ lv2_atom_forge_raw(forge, &pad, pad_size);
}
+/** Write raw output, padding to 64-bits as necessary. */
static inline void*
-lv2_atom_forge_write(LV2_Atom_Forge* forge,
- const void* data,
- uint32_t size)
+lv2_atom_forge_write(LV2_Atom_Forge* forge, const void* data, uint32_t size)
{
- void* out = lv2_atom_forge_write_nopad(forge, data, size);
+ void* out = lv2_atom_forge_raw(forge, data, size);
if (out) {
lv2_atom_forge_pad(forge, size);
}
return out;
}
+/** Write an atom:Atom header. */
+static inline LV2_Atom*
+lv2_atom_forge_atom(LV2_Atom_Forge* forge, uint32_t type, uint32_t size)
+{
+ const LV2_Atom a = { type, size };
+ return (LV2_Atom*)lv2_atom_forge_raw(forge, &a, sizeof(a));
+}
+
/** Write an atom:Int32. */
static inline LV2_Atom_Int32*
lv2_atom_forge_int32(LV2_Atom_Forge* forge, int32_t val)
@@ -283,25 +293,26 @@ lv2_atom_forge_urid(LV2_Atom_Forge* forge, LV2_URID id)
static inline uint8_t*
lv2_atom_forge_string_body(LV2_Atom_Forge* forge,
const uint8_t* str,
- size_t len)
+ uint32_t len)
{
uint8_t* out = NULL;
- if ((out = lv2_atom_forge_write_nopad(forge, str, len))
- && (out = lv2_atom_forge_write_nopad(forge, "", 1))) {
+ if ( (out = lv2_atom_forge_raw(forge, str, len))
+ && (out = lv2_atom_forge_raw(forge, "", 1))) {
lv2_atom_forge_pad(forge, len + 1);
}
return out;
}
-/** Write an atom:String. Note that @p str need not be NULL terminated. */
+/** Write an atom compatible with atom:String. Used internally. */
static inline LV2_Atom_String*
-lv2_atom_forge_string(LV2_Atom_Forge* forge,
- const uint8_t* str,
- size_t len)
+lv2_atom_forge_typed_string(LV2_Atom_Forge* forge,
+ uint32_t type,
+ const uint8_t* str,
+ uint32_t len)
{
- const LV2_Atom_String a = { { forge->String, len + 1 } };
+ const LV2_Atom_String a = { { type, len + 1 } };
LV2_Atom_String* out = (LV2_Atom_String*)
- lv2_atom_forge_write_nopad(forge, &a, sizeof(a));
+ lv2_atom_forge_raw(forge, &a, sizeof(a));
if (out) {
if (!lv2_atom_forge_string_body(forge, str, len)) {
out->atom.type = 0;
@@ -312,64 +323,47 @@ lv2_atom_forge_string(LV2_Atom_Forge* forge,
return out;
}
+/** 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, const uint8_t* 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_String*
-lv2_atom_forge_uri(LV2_Atom_Forge* forge,
- const uint8_t* uri,
- size_t len)
+lv2_atom_forge_uri(LV2_Atom_Forge* forge, const uint8_t* uri, uint32_t len)
{
- const LV2_Atom_String a = { { forge->URI, len + 1 } };
- LV2_Atom_String* out = (LV2_Atom_String*)
- lv2_atom_forge_write_nopad(forge, &a, sizeof(a));
- if (out) {
- if (!lv2_atom_forge_string_body(forge, uri, len)) {
- out->atom.type = 0;
- out->atom.size = 0;
- out = NULL;
- }
- }
- return out;
+ 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_String*
-lv2_atom_forge_path(LV2_Atom_Forge* forge,
- const uint8_t* path,
- size_t len)
+lv2_atom_forge_path(LV2_Atom_Forge* forge, const uint8_t* path, uint32_t len)
{
- const LV2_Atom_String a = { { forge->Path, len + 1 } };
- LV2_Atom_String* out = (LV2_Atom_String*)
- lv2_atom_forge_write_nopad(forge, &a, sizeof(a));
- if (out) {
- if (!lv2_atom_forge_string_body(forge, path, len)) {
- out->atom.type = 0;
- out->atom.size = 0;
- out = NULL;
- }
- }
- return out;
+ return lv2_atom_forge_typed_string(forge, forge->Path, path, len);
}
/** Write an atom:Literal. */
static inline LV2_Atom_Literal*
lv2_atom_forge_literal(LV2_Atom_Forge* forge,
const uint8_t* str,
- size_t len,
+ uint32_t len,
uint32_t datatype,
uint32_t lang)
{
const LV2_Atom_Literal a = {
{ forge->Literal,
sizeof(LV2_Atom_Literal) - sizeof(LV2_Atom) + len + 1 },
- datatype,
- lang
+ { datatype,
+ lang }
};
LV2_Atom_Literal* out = (LV2_Atom_Literal*)
- lv2_atom_forge_write_nopad(forge, &a, sizeof(a));
+ lv2_atom_forge_raw(forge, &a, sizeof(a));
if (out) {
if (!lv2_atom_forge_string_body(forge, str, len)) {
out->atom.type = 0;
@@ -387,11 +381,10 @@ lv2_atom_forge_vector_head(LV2_Atom_Forge* forge,
uint32_t elem_type,
uint32_t elem_size)
{
- const size_t size = sizeof(LV2_Atom_Vector) + (elem_size * elem_count);
+ const uint32_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
+ { elem_count, elem_type }
};
return (LV2_Atom_Vector*)lv2_atom_forge_write(forge, &a, sizeof(a));
}
@@ -469,8 +462,7 @@ lv2_atom_forge_resource(LV2_Atom_Forge* forge,
{
const LV2_Atom_Object a = {
{ forge->Resource, sizeof(LV2_Atom_Object) - sizeof(LV2_Atom) },
- id,
- otype
+ { id, otype }
};
LV2_Atom* atom = (LV2_Atom*)lv2_atom_forge_write(forge, &a, sizeof(a));
return (LV2_Atom_Object*)lv2_atom_forge_push(forge, frame, atom);
@@ -487,8 +479,7 @@ lv2_atom_forge_blank(LV2_Atom_Forge* forge,
{
const LV2_Atom_Object a = {
{ forge->Blank, sizeof(LV2_Atom_Object) - sizeof(LV2_Atom) },
- id,
- otype
+ { id, otype }
};
LV2_Atom* atom = (LV2_Atom*)lv2_atom_forge_write(forge, &a, sizeof(a));
return (LV2_Atom_Object*)lv2_atom_forge_push(forge, frame, atom);
@@ -520,8 +511,7 @@ lv2_atom_forge_sequence_head(LV2_Atom_Forge* forge,
{
const LV2_Atom_Sequence a = {
{ forge->Sequence, sizeof(LV2_Atom_Sequence) - sizeof(LV2_Atom) },
- unit,
- 0
+ { unit, 0 }
};
LV2_Atom* atom = (LV2_Atom*)lv2_atom_forge_write(forge, &a, sizeof(a));
return (LV2_Atom_Sequence*)lv2_atom_forge_push(forge, frame, atom);
@@ -532,13 +522,10 @@ lv2_atom_forge_sequence_head(LV2_Atom_Forge* forge,
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_Audio_Time*
-lv2_atom_forge_audio_time(LV2_Atom_Forge* forge,
- uint32_t frames,
- uint32_t subframes)
+static inline int64_t*
+lv2_atom_forge_frame_time(LV2_Atom_Forge* forge, int64_t frames)
{
- const LV2_Atom_Audio_Time a = { frames, subframes };
- return (LV2_Atom_Audio_Time*)lv2_atom_forge_write(forge, &a, sizeof(a));
+ return (int64_t*)lv2_atom_forge_write(forge, &frames, sizeof(frames));
}
/**
@@ -547,8 +534,7 @@ lv2_atom_forge_audio_time(LV2_Atom_Forge* forge,
the same @p parent parameter. Note the returned LV2_Event is NOT an Atom.
*/
static inline double*
-lv2_atom_forge_beat_time(LV2_Atom_Forge* forge,
- double beats)
+lv2_atom_forge_beat_time(LV2_Atom_Forge* forge, double beats)
{
return (double*)lv2_atom_forge_write(forge, &beats, sizeof(beats));
}
diff --git a/lv2/lv2plug.in/ns/ext/atom/manifest.ttl b/lv2/lv2plug.in/ns/ext/atom/manifest.ttl
index 9730981..6af1973 100644
--- a/lv2/lv2plug.in/ns/ext/atom/manifest.ttl
+++ b/lv2/lv2plug.in/ns/ext/atom/manifest.ttl
@@ -4,5 +4,5 @@
<http://lv2plug.in/ns/ext/atom>
a lv2:Specification ;
lv2:minorVersion 0 ;
- lv2:microVersion 5 ;
+ lv2:microVersion 6 ;
rdfs:seeAlso <atom.ttl> .
diff --git a/lv2/lv2plug.in/ns/ext/atom/util.h b/lv2/lv2plug.in/ns/ext/atom/util.h
index 9015a01..8ca3795 100644
--- a/lv2/lv2plug.in/ns/ext/atom/util.h
+++ b/lv2/lv2plug.in/ns/ext/atom/util.h
@@ -62,12 +62,9 @@ lv2_atom_is_null(const LV2_Atom* atom)
static inline bool
lv2_atom_equals(const LV2_Atom* a, const LV2_Atom* b)
{
- return (a == b) || (
- (a->type == b->type) &&
- (a->size == b->size) &&
- !memcmp(LV2_ATOM_CONTENTS(LV2_Atom, a),
- LV2_ATOM_CONTENTS(LV2_Atom, b),
- a->size));
+ return (a == b) || ((a->type == b->type) &&
+ (a->size == b->size) &&
+ !memcmp(a + 1, b + 1, a->size));
}
/**
@@ -78,14 +75,30 @@ lv2_atom_equals(const LV2_Atom* a, const LV2_Atom* b)
/** An iterator over the elements of an LV2_Atom_Sequence. */
typedef LV2_Atom_Event* LV2_Atom_Sequence_Iter;
-/** Get an iterator pointing to the first element in @p tup. */
+/** Get an iterator pointing to the first element in a Sequence body. */
+static inline LV2_Atom_Sequence_Iter
+lv2_sequence_body_begin(const LV2_Atom_Sequence_Body* body)
+{
+ return (LV2_Atom_Sequence_Iter)(body + 1);
+}
+
+/** Get an iterator pointing to the first element in a Sequence. */
static inline LV2_Atom_Sequence_Iter
lv2_sequence_begin(const LV2_Atom_Sequence* seq)
{
- return (LV2_Atom_Sequence_Iter)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, seq));
+ return (LV2_Atom_Sequence_Iter)(seq + 1);
}
-/** Return true iff @p i has reached the end of @p tup. */
+/** Return true iff @p i has reached the end of @p body. */
+static inline bool
+lv2_sequence_body_is_end(const LV2_Atom_Sequence_Body* body,
+ uint32_t size,
+ LV2_Atom_Sequence_Iter i)
+{
+ return (uint8_t*)i >= ((uint8_t*)body + size);
+}
+
+/** Return true iff @p i has reached the end of @p seq. */
static inline bool
lv2_sequence_is_end(const LV2_Atom_Sequence* seq, LV2_Atom_Sequence_Iter i)
{
@@ -126,6 +139,12 @@ lv2_sequence_iter_get(LV2_Atom_Sequence_Iter i)
!lv2_sequence_is_end(sequence, (iter)); \
(iter) = lv2_sequence_iter_next(iter))
+/** A version of LV2_SEQUENCE_FOREACH for when only the body is available. */
+#define LV2_SEQUENCE_BODY_FOREACH(body, size, iter) \
+ for (LV2_Atom_Sequence_Iter (iter) = lv2_sequence_body_begin(body); \
+ !lv2_sequence_body_is_end(body, size, (iter)); \
+ (iter) = lv2_sequence_iter_next(iter))
+
/**
@}
@name Tuple Iterator
@@ -142,11 +161,20 @@ lv2_tuple_begin(const LV2_Atom_Tuple* tup)
return (LV2_Atom_Tuple_Iter)(LV2_ATOM_BODY(tup));
}
+/** Return true iff @p i has reached the end of @p body. */
+static inline bool
+lv2_atom_tuple_body_is_end(const void* body,
+ uint32_t size,
+ LV2_Atom_Tuple_Iter i)
+{
+ return (uint8_t*)i >= ((uint8_t*)body + size);
+}
+
/** Return true iff @p i has reached the end of @p tup. */
static inline bool
lv2_tuple_is_end(const LV2_Atom_Tuple* tup, LV2_Atom_Tuple_Iter i)
{
- return (uint8_t*)i >= ((uint8_t*)tup + sizeof(LV2_Atom) + tup->atom.size);
+ return lv2_atom_tuple_body_is_end(LV2_ATOM_BODY(tup), tup->atom.size, i);
}
/** Return an iterator to the element following @p i. */
@@ -182,6 +210,12 @@ lv2_tuple_iter_get(LV2_Atom_Tuple_Iter i)
!lv2_tuple_is_end(tuple, (iter)); \
(iter) = lv2_tuple_iter_next(iter))
+/** A version of LV2_TUPLE_FOREACH for when only the body is available. */
+#define LV2_TUPLE_BODY_FOREACH(body, size, iter) \
+ for (LV2_Atom_Tuple_Iter (iter) = (LV2_Atom_Tuple_Iter)body; \
+ !lv2_atom_tuple_body_is_end(body, size, (iter)); \
+ (iter) = lv2_tuple_iter_next(iter))
+
/**
@}
@name Object Iterator
@@ -191,26 +225,32 @@ lv2_tuple_iter_get(LV2_Atom_Tuple_Iter i)
/** An iterator over the properties of an LV2_Atom_Object. */
typedef LV2_Atom_Property_Body* LV2_Atom_Object_Iter;
+static inline LV2_Atom_Object_Iter
+lv2_object_body_begin(const LV2_Atom_Object_Body* body)
+{
+ return (LV2_Atom_Object_Iter)(body + 1);
+}
+
/** Get an iterator pointing to the first property in @p obj. */
static inline LV2_Atom_Object_Iter
lv2_object_begin(const LV2_Atom_Object* obj)
{
- return (LV2_Atom_Object_Iter)(LV2_ATOM_CONTENTS(LV2_Atom_Object, obj));
+ return (LV2_Atom_Object_Iter)(obj + 1);
}
-/** Return true iff @p i has reached the end of @p obj. */
static inline bool
-lv2_object_is_end(const LV2_Atom_Object* obj, LV2_Atom_Object_Iter i)
+lv2_atom_object_body_is_end(const LV2_Atom_Object_Body* body,
+ uint32_t size,
+ LV2_Atom_Object_Iter i)
{
- return (uint8_t*)i >= ((uint8_t*)obj + sizeof(LV2_Atom) + obj->atom.size);
+ return (uint8_t*)i >= ((uint8_t*)body + size);
}
-/** Return true iff @p l points to the same property as @p r. */
+/** Return true iff @p i has reached the end of @p obj. */
static inline bool
-lv2_object_iter_equals(const LV2_Atom_Object_Iter l,
- const LV2_Atom_Object_Iter r)
+lv2_object_is_end(const LV2_Atom_Object* obj, LV2_Atom_Object_Iter i)
{
- return l == r;
+ return (uint8_t*)i >= ((uint8_t*)obj + sizeof(LV2_Atom) + obj->atom.size);
}
/** Return an iterator to the property following @p i. */
@@ -248,6 +288,12 @@ lv2_object_iter_get(LV2_Atom_Object_Iter i)
!lv2_object_is_end(object, (iter)); \
(iter) = lv2_object_iter_next(iter))
+/** A version of LV2_OBJECT_FOREACH for when only the body is available. */
+#define LV2_OBJECT_BODY_FOREACH(body, size, iter) \
+ for (LV2_Atom_Object_Iter (iter) = lv2_object_body_begin(body); \
+ !lv2_atom_object_body_is_end(body, size, (iter)); \
+ (iter) = lv2_object_iter_next(iter))
+
/**
@}
@name Object Query
diff --git a/plugins/eg-sampler.lv2/sampler.c b/plugins/eg-sampler.lv2/sampler.c
index 6ac5a38..fd450c6 100644
--- a/plugins/eg-sampler.lv2/sampler.c
+++ b/plugins/eg-sampler.lv2/sampler.c
@@ -335,13 +335,13 @@ run(LV2_Handle instance,
if (ev->body.type == uris->midi_Event) {
uint8_t* const data = (uint8_t* const)(ev + 1);
if ((data[0] & 0xF0) == 0x90) {
- start_frame = ev->time.audio.frames;
+ start_frame = ev->time.frames;
plugin->frame = 0;
plugin->play = true;
}
} else if (is_object_type(uris, ev->body.type)) {
const LV2_Atom_Object* obj = (LV2_Atom_Object*)&ev->body;
- if (obj->otype == uris->msg_Set) {
+ if (obj->body.otype == uris->msg_Set) {
/* Received a set message, send it to the worker thread. */
fprintf(stderr, "Queueing set message\n");
zix_ring_write(plugin->to_worker,
@@ -350,7 +350,7 @@ run(LV2_Handle instance,
lv2_atom_total_size(&obj->atom)));
zix_sem_post(&plugin->signal);
} else {
- fprintf(stderr, "Unknown object type %d\n", obj->otype);
+ fprintf(stderr, "Unknown object type %d\n", obj->body.otype);
}
} else {
fprintf(stderr, "Unknown event type %d\n", ev->body.type);
@@ -410,7 +410,7 @@ run(LV2_Handle instance,
plugin->sample = m.sample;
/* Send a notification that we're using a new sample. */
- lv2_atom_forge_audio_time(&plugin->forge, 0, 0);
+ lv2_atom_forge_frame_time(&plugin->forge, 0);
write_set_file(&plugin->forge, uris,
plugin->sample->path,
plugin->sample->path_len);
diff --git a/plugins/eg-sampler.lv2/uris.h b/plugins/eg-sampler.lv2/uris.h
index de1cbd3..8d0a983 100644
--- a/plugins/eg-sampler.lv2/uris.h
+++ b/plugins/eg-sampler.lv2/uris.h
@@ -107,8 +107,8 @@ static inline const LV2_Atom*
read_set_file(const SamplerURIs* uris,
const LV2_Atom_Object* obj)
{
- if (obj->otype != uris->msg_Set) {
- fprintf(stderr, "Ignoring unknown message type %d\n", obj->otype);
+ if (obj->body.otype != uris->msg_Set) {
+ fprintf(stderr, "Ignoring unknown message type %d\n", obj->body.otype);
return NULL;
}