summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2016-03-15 18:01:14 -0400
committerDavid Robillard <d@drobilla.net>2016-03-15 18:01:14 -0400
commitf205d626e0fbcd98f3c0459b739d6688b19b157a (patch)
tree7f5fdca6a9f7a89983c539fdf6a32e91cec90f7a
parent2d66c5e98f1bbc8244d61e6f328e2a7b5671fab2 (diff)
downloadsratom-f205d626e0fbcd98f3c0459b739d6688b19b157a.tar.gz
sratom-f205d626e0fbcd98f3c0459b739d6688b19b157a.tar.bz2
sratom-f205d626e0fbcd98f3c0459b739d6688b19b157a.zip
Support sequences with beat time stamps
Based on a patch from Hanspeter Portner.
-rw-r--r--NEWS5
-rw-r--r--src/sratom.c83
-rw-r--r--tests/sratom_test.c32
-rw-r--r--wscript2
4 files changed, 92 insertions, 30 deletions
diff --git a/NEWS b/NEWS
index 4cf5c78..6e2af0c 100644
--- a/NEWS
+++ b/NEWS
@@ -1,9 +1,10 @@
-sratom (0.4.7) unstable;
+sratom (0.4.9) unstable;
+ * Support sequences with beat time stamps
* Fix warnings when building with ISO C++ compilers
* Upgrade to waf 1.8.14
- -- David Robillard <d@drobilla.net> Fri, 02 Oct 2015 21:03:46 -0400
+ -- David Robillard <d@drobilla.net> Tue, 15 Mar 2016 17:57:49 -0400
sratom (0.4.6) stable;
diff --git a/src/sratom.c b/src/sratom.c
index e0996c4..6231d4a 100644
--- a/src/sratom.c
+++ b/src/sratom.c
@@ -41,6 +41,8 @@ struct SratomImpl {
LV2_URID_Map* map;
LV2_Atom_Forge forge;
LV2_URID atom_Event;
+ LV2_URID atom_frameTime;
+ LV2_URID atom_beatTime;
LV2_URID midi_MidiEvent;
unsigned next_id;
SerdNode base_uri;
@@ -49,9 +51,11 @@ struct SratomImpl {
void* handle;
SratomObjectMode object_mode;
bool pretty_numbers;
+ uint32_t seq_unit;
struct {
SordNode* atom_childType;
SordNode* atom_frameTime;
+ SordNode* atom_beatTime;
SordNode* rdf_first;
SordNode* rdf_rest;
SordNode* rdf_type;
@@ -75,6 +79,8 @@ sratom_new(LV2_URID_Map* map)
Sratom* sratom = (Sratom*)malloc(sizeof(Sratom));
sratom->map = map;
sratom->atom_Event = map->map(map->handle, LV2_ATOM__Event);
+ sratom->atom_frameTime = map->map(map->handle, LV2_ATOM__frameTime);
+ sratom->atom_beatTime = map->map(map->handle, LV2_ATOM__beatTime);
sratom->midi_MidiEvent = map->map(map->handle, LV2_MIDI__MidiEvent);
sratom->next_id = 0;
sratom->base_uri = SERD_NODE_NULL;
@@ -206,6 +212,22 @@ path_is_absolute(const char* path)
&& (path[2] == '/' || path[2] == '\\')));
}
+static SerdNode
+number_type(const Sratom* sratom, const uint8_t* type)
+{
+ if (sratom->pretty_numbers &&
+ (!strcmp((const char*)type, (const char*)NS_XSD "int") ||
+ !strcmp((const char*)type, (const char*)NS_XSD "long"))) {
+ return serd_node_from_string(SERD_URI, NS_XSD "integer");
+ } else if (sratom->pretty_numbers &&
+ (!strcmp((const char*)type, (const char*)NS_XSD "float") ||
+ !strcmp((const char*)type, (const char*)NS_XSD "double"))) {
+ return serd_node_from_string(SERD_URI, NS_XSD "decimal");
+ } else {
+ return serd_node_from_string(SERD_URI, (const uint8_t*)type);
+ }
+}
+
SRATOM_API
int
sratom_write(Sratom* sratom,
@@ -285,23 +307,19 @@ sratom_write(Sratom* sratom,
} else if (type_urid == sratom->forge.Int) {
new_node = true;
object = serd_node_new_integer(*(const int32_t*)body);
- datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers)
- ? NS_XSD "integer" : NS_XSD "int");
+ datatype = number_type(sratom, NS_XSD "int");
} else if (type_urid == sratom->forge.Long) {
new_node = true;
object = serd_node_new_integer(*(const int64_t*)body);
- datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers)
- ? NS_XSD "integer" : NS_XSD "long");
+ datatype = number_type(sratom, NS_XSD "long");
} else if (type_urid == sratom->forge.Float) {
new_node = true;
object = serd_node_new_decimal(*(const float*)body, 8);
- datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers)
- ? NS_XSD "decimal" : NS_XSD "float");
+ datatype = number_type(sratom, NS_XSD "float");
} else if (type_urid == sratom->forge.Double) {
new_node = true;
object = serd_node_new_decimal(*(const double*)body, 16);
- datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers)
- ? NS_XSD "decimal" : NS_XSD "double");
+ datatype = number_type(sratom, NS_XSD "double");
} else if (type_urid == sratom->forge.Bool) {
const int32_t val = *(const int32_t*)body;
datatype = serd_node_from_string(SERD_URI, NS_XSD "boolean");
@@ -320,11 +338,17 @@ sratom_write(Sratom* sratom,
const LV2_Atom_Event* ev = (const LV2_Atom_Event*)body;
gensym(&id, 'e', sratom->next_id++);
start_object(sratom, &flags, subject, predicate, &id, NULL);
- // TODO: beat time
- SerdNode time = serd_node_new_integer(ev->time.frames);
- SerdNode p = serd_node_from_string(SERD_URI,
- USTR(LV2_ATOM__frameTime));
- datatype = serd_node_from_string(SERD_URI, NS_XSD "decimal");
+ SerdNode time;
+ SerdNode p;
+ if (sratom->seq_unit == sratom->atom_beatTime) {
+ time = serd_node_new_decimal(ev->time.beats, 16);
+ p = serd_node_from_string(SERD_URI, USTR(LV2_ATOM__beatTime));
+ datatype = number_type(sratom, NS_XSD "double");
+ } else {
+ time = serd_node_new_integer(ev->time.frames);
+ p = serd_node_from_string(SERD_URI, USTR(LV2_ATOM__frameTime));
+ datatype = number_type(sratom, NS_XSD "long");
+ }
sratom->write_statement(sratom->handle, SERD_ANON_CONT, NULL,
&id, &p, &time, &datatype, &language);
serd_node_free(&time);
@@ -399,6 +423,7 @@ sratom_write(Sratom* sratom,
SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "value");
flags |= SERD_LIST_O_BEGIN;
LV2_ATOM_SEQUENCE_BODY_FOREACH(seq, size, ev) {
+ sratom->seq_unit = seq->unit;
list_append(sratom, unmap, &flags, &id, &p, &node,
sizeof(LV2_Atom_Event) + ev->body.size,
sratom->atom_Event,
@@ -646,20 +671,34 @@ read_node(Sratom* sratom,
LV2_Atom_Forge_Frame frame = { 0, 0 };
if (mode == MODE_SEQUENCE) {
- SordNode* frame_time = sord_get(
- model, node, sratom->nodes.atom_frameTime, NULL, NULL);
- const char* frame_time_str = frame_time
- ? (const char*)sord_node_get_string(frame_time)
- : "";
- lv2_atom_forge_frame_time(forge, serd_strtod(frame_time_str, NULL));
+ SordNode* time = sord_get(
+ model, node, sratom->nodes.atom_beatTime, NULL, NULL);
+ uint32_t seq_unit;
+ if (time) {
+ const char* time_str = (const char*)sord_node_get_string(time);
+ lv2_atom_forge_beat_time(forge, serd_strtod(time_str, NULL));
+ seq_unit = sratom->atom_beatTime;
+ } else {
+ time = sord_get(model, node, sratom->nodes.atom_frameTime, NULL, NULL);
+ const char* time_str = time
+ ? (const char*)sord_node_get_string(time)
+ : "";
+ lv2_atom_forge_frame_time(forge, serd_strtod(time_str, NULL));
+ seq_unit = sratom->atom_frameTime;
+ }
read_node(sratom, forge, world, model, value, MODE_BODY);
- sord_node_free(world, frame_time);
+ sord_node_free(world, time);
+ sratom->seq_unit = seq_unit;
} else if (type_urid == sratom->forge.Tuple) {
lv2_atom_forge_tuple(forge, &frame);
read_list_value(sratom, forge, world, model, value, MODE_BODY);
} else if (type_urid == sratom->forge.Sequence) {
- lv2_atom_forge_sequence_head(forge, &frame, 0);
+ const LV2_Atom_Forge_Ref ref = lv2_atom_forge_sequence_head(forge, &frame, 0);
+ sratom->seq_unit = 0;
read_list_value(sratom, forge, world, model, value, MODE_SEQUENCE);
+
+ LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)lv2_atom_forge_deref(forge, ref);
+ seq->body.unit = (sratom->seq_unit == sratom->atom_frameTime) ? 0 : sratom->seq_unit;
} else if (type_urid == sratom->forge.Vector) {
SordNode* child_type_node = sord_get(
model, node, sratom->nodes.atom_childType, NULL, NULL);
@@ -706,6 +745,7 @@ sratom_read(Sratom* sratom,
{
sratom->nodes.atom_childType = sord_new_uri(world, USTR(LV2_ATOM__childType));
sratom->nodes.atom_frameTime = sord_new_uri(world, USTR(LV2_ATOM__frameTime));
+ sratom->nodes.atom_beatTime = sord_new_uri(world, USTR(LV2_ATOM__beatTime));
sratom->nodes.rdf_first = sord_new_uri(world, NS_RDF "first");
sratom->nodes.rdf_rest = sord_new_uri(world, NS_RDF "rest");
sratom->nodes.rdf_type = sord_new_uri(world, NS_RDF "type");
@@ -721,6 +761,7 @@ sratom_read(Sratom* sratom,
sord_node_free(world, sratom->nodes.rdf_rest);
sord_node_free(world, sratom->nodes.rdf_first);
sord_node_free(world, sratom->nodes.atom_frameTime);
+ sord_node_free(world, sratom->nodes.atom_beatTime);
sord_node_free(world, sratom->nodes.atom_childType);
memset(&sratom->nodes, 0, sizeof(sratom->nodes));
}
diff --git a/tests/sratom_test.c b/tests/sratom_test.c
index 49b9357..90a81cd 100644
--- a/tests/sratom_test.c
+++ b/tests/sratom_test.c
@@ -112,7 +112,8 @@ test(bool top_level, bool pretty_numbers)
LV2_URID eg_fvector = urid_map(NULL, "http://example.org/t-fvector");
LV2_URID eg_dvector = urid_map(NULL, "http://example.org/u-dvector");
LV2_URID eg_bvector = urid_map(NULL, "http://example.org/v-bvector");
- LV2_URID eg_seq = urid_map(NULL, "http://example.org/x-seq");
+ LV2_URID eg_fseq = urid_map(NULL, "http://example.org/w-fseq");
+ LV2_URID eg_bseq = urid_map(NULL, "http://example.org/x-bseq");
uint8_t buf[1024];
lv2_atom_forge_set_buffer(&forge, buf, sizeof(buf));
@@ -248,11 +249,11 @@ test(bool top_level, bool pretty_numbers)
int32_t belems[] = { true, false };
lv2_atom_forge_vector(&forge, sizeof(int32_t), forge.Bool, 2, belems);
- // eg_seq = (Sequence)1, 2
+ // eg_fseq = (Sequence)1, 2
LV2_URID midi_midiEvent = map.map(map.handle, LV2_MIDI__MidiEvent);
- lv2_atom_forge_key(&forge, eg_seq);
- LV2_Atom_Forge_Frame seq_frame;
- lv2_atom_forge_sequence_head(&forge, &seq_frame, 0);
+ lv2_atom_forge_key(&forge, eg_fseq);
+ LV2_Atom_Forge_Frame fseq_frame;
+ lv2_atom_forge_sequence_head(&forge, &fseq_frame, 0);
const uint8_t ev1[3] = { 0x90, 0x1A, 0x1 };
lv2_atom_forge_frame_time(&forge, 1);
@@ -266,7 +267,26 @@ test(bool top_level, bool pretty_numbers)
lv2_atom_forge_raw(&forge, ev2, sizeof(ev2));
lv2_atom_forge_pad(&forge, sizeof(ev2));
- lv2_atom_forge_pop(&forge, &seq_frame);
+ lv2_atom_forge_pop(&forge, &fseq_frame);
+
+ // eg_bseq = (Sequence)1.1, 2.2
+ LV2_URID atom_beatTime = map.map(map.handle, LV2_ATOM__beatTime);
+ lv2_atom_forge_key(&forge, eg_bseq);
+ LV2_Atom_Forge_Frame bseq_frame;
+ lv2_atom_forge_sequence_head(&forge, &bseq_frame, atom_beatTime);
+
+ lv2_atom_forge_beat_time(&forge, 1.0);
+ lv2_atom_forge_atom(&forge, sizeof(ev1), midi_midiEvent);
+ lv2_atom_forge_raw(&forge, ev1, sizeof(ev1));
+ lv2_atom_forge_pad(&forge, sizeof(ev1));
+
+ lv2_atom_forge_beat_time(&forge, 2.0);
+ lv2_atom_forge_atom(&forge, sizeof(ev2), midi_midiEvent);
+ lv2_atom_forge_raw(&forge, ev2, sizeof(ev2));
+ lv2_atom_forge_pad(&forge, sizeof(ev2));
+
+ lv2_atom_forge_pop(&forge, &bseq_frame);
+
lv2_atom_forge_pop(&forge, &obj_frame);
const char* base_uri = "file:///tmp/base/";
diff --git a/wscript b/wscript
index 8fd2a5c..b661f34 100644
--- a/wscript
+++ b/wscript
@@ -8,7 +8,7 @@ import waflib.extras.autowaf as autowaf
# major increment <=> incompatible changes
# minor increment <=> compatible changes (additions)
# micro increment <=> no interface changes
-SRATOM_VERSION = '0.4.7'
+SRATOM_VERSION = '0.4.9'
SRATOM_MAJOR_VERSION = '0'
# Mandatory waf variables