summaryrefslogtreecommitdiffstats
path: root/src/sratom.c
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 /src/sratom.c
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.
Diffstat (limited to 'src/sratom.c')
-rw-r--r--src/sratom.c83
1 files changed, 62 insertions, 21 deletions
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));
}