Browse Source

Support sequences with beat time stamps

Based on a patch from Hanspeter Portner.
zrythm_meson
David Robillard 7 years ago
parent
commit
f205d626e0
  1. 5
      NEWS
  2. 83
      src/sratom.c
  3. 32
      tests/sratom_test.c
  4. 2
      wscript

5
NEWS

@ -1,9 +1,10 @@ @@ -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;

83
src/sratom.c

@ -41,6 +41,8 @@ struct SratomImpl { @@ -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 { @@ -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) @@ -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) @@ -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, @@ -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, @@ -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, @@ -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, @@ -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, @@ -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, @@ -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));
}

32
tests/sratom_test.c

@ -112,7 +112,8 @@ test(bool top_level, bool pretty_numbers) @@ -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) @@ -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) @@ -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/";

2
wscript

@ -8,7 +8,7 @@ import waflib.extras.autowaf as autowaf @@ -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

Loading…
Cancel
Save