diff options
author | David Robillard <d@drobilla.net> | 2012-02-29 03:18:26 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2012-02-29 03:18:26 +0000 |
commit | 045daf80b063d7f8ea560583e34d5cd8378fb4b1 (patch) | |
tree | 698c08acf704eda76fc30274834b97b5b27b9888 | |
parent | 574cb313ce5c2c60976fd243e212529ce86b566b (diff) | |
download | jalv-045daf80b063d7f8ea560583e34d5cd8378fb4b1.tar.gz jalv-045daf80b063d7f8ea560583e34d5cd8378fb4b1.tar.bz2 jalv-045daf80b063d7f8ea560583e34d5cd8378fb4b1.zip |
Update for latest atom extension.
Dump Jack transport information as an atom:Object.
git-svn-id: http://svn.drobilla.net/lad/trunk/jalv@4005 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r-- | src/atom_rdf.c | 2 | ||||
-rw-r--r-- | src/jalv.c | 70 | ||||
-rw-r--r-- | src/jalv_internal.h | 19 | ||||
-rw-r--r-- | src/lv2_evbuf.c | 79 | ||||
-rw-r--r-- | src/lv2_evbuf.h | 23 |
5 files changed, 134 insertions, 59 deletions
diff --git a/src/atom_rdf.c b/src/atom_rdf.c index 3db4cd3..8f0eb97 100644 --- a/src/atom_rdf.c +++ b/src/atom_rdf.c @@ -79,12 +79,10 @@ atom_to_rdf(SerdWriter* writer, object = serd_node_new_decimal(*(float*)LV2_ATOM_BODY(atom), 8); datatype = serd_node_from_string(SERD_URI, USTR(NS_XSD "decimal")); } else if (!strcmp(type, LV2_ATOM__Double)) { - new_node = true; object = serd_node_new_decimal(*(float*)LV2_ATOM_BODY(atom), 16); datatype = serd_node_from_string(SERD_URI, USTR(NS_XSD "decimal")); } else if (!strcmp(type, LV2_ATOM__Bool)) { const int32_t val = *(const int32_t*)LV2_ATOM_BODY(atom); - new_node = true; datatype = serd_node_from_string(SERD_URI, USTR(NS_XSD "boolean")); object = serd_node_from_string(SERD_LITERAL, USTR(val ? "true" : "false")); @@ -37,6 +37,7 @@ #endif #include "lv2/lv2plug.in/ns/ext/atom/atom.h" +#include "lv2/lv2plug.in/ns/ext/time/time.h" #include "lv2/lv2plug.in/ns/ext/uri-map/uri-map.h" #include "lv2/lv2plug.in/ns/ext/urid/urid.h" #ifdef HAVE_LV2_UI_RESIZE @@ -227,6 +228,8 @@ jalv_allocate_port_buffers(Jalv* jalv) jalv->midi_buf_size, port->old_api ? LV2_EVBUF_EVENT : LV2_EVBUF_ATOM, jalv->map.map(jalv->map.handle, + lilv_node_as_string(jalv->chunk_class)), + jalv->map.map(jalv->map.handle, lilv_node_as_string(jalv->seq_class))); lilv_instance_connect_port( jalv->instance, i, lv2_evbuf_get_buffer(port->evbuf)); @@ -324,6 +327,40 @@ jack_process_cb(jack_nframes_t nframes, void* data) { Jalv* const host = (Jalv*)data; + jack_position_t pos; + double speed = 0.0; + if (jack_transport_query(host->jack_client, &pos) == JackTransportRolling) { + speed = 1.0; + } + + if (pos.valid & JackPositionBBT) { + uint8_t buf[1024]; + lv2_atom_forge_set_buffer(&host->forge, buf, sizeof(buf)); + LV2_Atom_Forge* forge = &host->forge; + LV2_Atom_Forge_Frame frame; + lv2_atom_forge_blank(forge, &frame, 1, host->urids.time_Position); + lv2_atom_forge_property_head(forge, host->urids.time_barBeat, 0); + lv2_atom_forge_float(forge, pos.beat - 1 + (pos.tick / (float)pos.ticks_per_beat)); + lv2_atom_forge_property_head(forge, host->urids.time_bar, 0); + lv2_atom_forge_float(forge, pos.bar - 1); + lv2_atom_forge_property_head(forge, host->urids.time_beatUnit, 0); + lv2_atom_forge_float(forge, pos.beat_type); + lv2_atom_forge_property_head(forge, host->urids.time_beatsPerBar, 0); + lv2_atom_forge_float(forge, pos.beats_per_bar); + lv2_atom_forge_property_head(forge, host->urids.time_beatsPerMinute, 0); + lv2_atom_forge_float(forge, pos.beats_per_minute); + lv2_atom_forge_property_head(forge, host->urids.time_frame, 0); + lv2_atom_forge_int64(forge, pos.frame); + lv2_atom_forge_property_head(forge, host->urids.time_speed, 0); + lv2_atom_forge_float(forge, speed); + + SerdNode s = serd_node_from_string(SERD_BLANK, USTR("pos")); + SerdNode p = serd_node_from_string(SERD_URI, USTR(NS_RDF "value")); + char* str = atom_to_turtle(&host->unmap, &s, &p, frame.atom); + printf("\n## Position\n%s\n", str); + free(str); + } + switch (host->play_state) { case JALV_PAUSE_REQUESTED: host->play_state = JALV_PAUSED; @@ -358,10 +395,10 @@ jack_process_cb(jack_nframes_t nframes, void* data) jack_port_get_buffer(host->ports[p].jack_port, nframes)); } else if (host->ports[p].type == TYPE_EVENT) { - /* Clear Jack event port buffer. */ - lv2_evbuf_reset(host->ports[p].evbuf); - + /* Prepare event ports. */ if (host->ports[p].flow == FLOW_INPUT) { + lv2_evbuf_reset(host->ports[p].evbuf, true); + void* buf = jack_port_get_buffer(host->ports[p].jack_port, nframes); @@ -374,7 +411,9 @@ jack_process_cb(jack_nframes_t nframes, void* data) host->midi_event_id, ev.size, ev.buffer); } - } + } else { + lv2_evbuf_reset(host->ports[p].evbuf, false); + } } } @@ -390,7 +429,7 @@ jack_process_cb(jack_nframes_t nframes, void* data) if (ev.protocol == 0) { assert(ev.size == sizeof(float)); port->control = *(float*)body; - } else if (ev.protocol == host->atom_prot_id) { + } else if (ev.protocol == host->urids.atom_eventTransfer) { LV2_Evbuf_Iterator i = lv2_evbuf_end(port->evbuf); const LV2_Atom* const atom = (const LV2_Atom*)body; lv2_evbuf_write(&i, nframes, 0, @@ -437,7 +476,7 @@ jack_process_cb(jack_nframes_t nframes, void* data) char buf[sizeof(ControlChange) + sizeof(LV2_Atom)]; ControlChange* ev = (ControlChange*)buf; ev->index = p; - ev->protocol = host->atom_prot_id; + ev->protocol = host->urids.atom_eventTransfer; ev->size = sizeof(LV2_Atom) + size; LV2_Atom* atom = (LV2_Atom*)ev->body; atom->type = type; @@ -505,13 +544,13 @@ jalv_ui_write(SuilController controller, return; } - if (protocol != 0 && protocol != host->atom_prot_id) { + if (protocol != 0 && protocol != host->urids.atom_eventTransfer) { fprintf(stderr, "UI write with unsupported protocol %d (%s)\n", protocol, symap_unmap(host->symap, protocol)); return; } - if (protocol == host->atom_prot_id) { + if (protocol == host->urids.atom_eventTransfer) { SerdNode s = serd_node_from_string(SERD_BLANK, USTR("msg")); SerdNode p = serd_node_from_string(SERD_URI, USTR(NS_RDF "value")); char* str = atom_to_turtle(&host->unmap, &s, &p, (LV2_Atom*)buffer); @@ -538,7 +577,7 @@ jalv_emit_ui_events(Jalv* host) char buf[ev.size]; jack_ringbuffer_read(host->plugin_events, buf, ev.size); - if (ev.protocol == host->atom_prot_id) { + if (ev.protocol == host->urids.atom_eventTransfer) { SerdNode s = serd_node_from_string(SERD_BLANK, USTR("msg")); SerdNode p = serd_node_from_string(SERD_URI, USTR(NS_RDF "value")); char* str = atom_to_turtle(&host->unmap, &s, &p, (LV2_Atom*)buf); @@ -587,10 +626,20 @@ main(int argc, char** argv) host.unmap.unmap = unmap_uri; unmap_feature.data = &host.unmap; + lv2_atom_forge_init(&host.forge, &host.map); + host.midi_event_id = uri_to_id(&host, "http://lv2plug.in/ns/ext/event", NS_MIDI "MidiEvent"); - host.atom_prot_id = symap_map(host.symap, NS_ATOM "eventTransfer"); + host.urids.atom_eventTransfer = symap_map(host.symap, LV2_ATOM__eventTransfer); + host.urids.time_Position = symap_map(host.symap, LV2_TIME__Position); + host.urids.time_barBeat = symap_map(host.symap, LV2_TIME__barBeat); + host.urids.time_bar = symap_map(host.symap, LV2_TIME__bar); + host.urids.time_beatUnit = symap_map(host.symap, LV2_TIME__beatUnit); + host.urids.time_beatsPerBar = symap_map(host.symap, LV2_TIME__beatsPerBar); + host.urids.time_beatsPerMinute = symap_map(host.symap, LV2_TIME__beatsPerMinute); + host.urids.time_frame = symap_map(host.symap, LV2_TIME__frame); + host.urids.time_speed = symap_map(host.symap, LV2_TIME__speed); char* template = jalv_strdup("/tmp/jalv-XXXXXX"); host.temp_dir = jalv_strjoin(mkdtemp(template), "/"); @@ -625,6 +674,7 @@ main(int argc, char** argv) host.control_class = lilv_new_uri(world, LILV_URI_CONTROL_PORT); host.audio_class = lilv_new_uri(world, LILV_URI_AUDIO_PORT); host.event_class = lilv_new_uri(world, LILV_URI_EVENT_PORT); + host.chunk_class = lilv_new_uri(world, LV2_ATOM__Chunk); host.seq_class = lilv_new_uri(world, LV2_ATOM__Sequence); host.msg_port_class = lilv_new_uri(world, LV2_ATOM__MessagePort); host.midi_class = lilv_new_uri(world, LILV_URI_MIDI_EVENT); diff --git a/src/jalv_internal.h b/src/jalv_internal.h index 474da83..07c40b3 100644 --- a/src/jalv_internal.h +++ b/src/jalv_internal.h @@ -28,6 +28,7 @@ #include "suil/suil.h" #include "lv2/lv2plug.in/ns/ext/atom/atom.h" +#include "lv2/lv2plug.in/ns/ext/atom/forge.h" #include "lv2/lv2plug.in/ns/ext/urid/urid.h" #include "lv2/lv2plug.in/ns/ext/state/state.h" @@ -82,6 +83,18 @@ typedef struct { bool dump; } JalvOptions; +typedef struct { + LV2_URID atom_eventTransfer; + LV2_URID time_Position; + LV2_URID time_barBeat; + LV2_URID time_bar; + LV2_URID time_beatUnit; + LV2_URID time_beatsPerBar; + LV2_URID time_beatsPerMinute; + LV2_URID time_frame; + LV2_URID time_speed; +} JalvURIDs; + typedef enum { JALV_RUNNING, JALV_PAUSE_REQUESTED, @@ -90,6 +103,8 @@ typedef enum { typedef struct { JalvOptions opts; ///< Command-line options + JalvURIDs urids; ///< URIDs + LV2_Atom_Forge forge; ///< Atom forge const char* prog_name; ///< Program name (argv[0]) LilvWorld* world; ///< Lilv World int ui_width; ///< Requested UI width @@ -121,14 +136,14 @@ typedef struct { LilvNode* control_class; ///< Control port class (URI) LilvNode* audio_class; ///< Audio port class (URI) LilvNode* event_class; ///< Event port class (URI) + LilvNode* chunk_class; ///< Atom sequence class (URI) LilvNode* seq_class; ///< Atom sequence class (URI) LilvNode* msg_port_class; ///< Atom event port class (URI) LilvNode* midi_class; ///< MIDI event class (URI) LilvNode* preset_class; ///< Preset class (URI) LilvNode* label_pred; ///< rdfs:label LilvNode* optional; ///< lv2:connectionOptional port property - uint32_t midi_event_id; ///< MIDI event class ID - uint32_t atom_prot_id; ///< Atom protocol ID + uint32_t midi_event_id; ///< MIDI event class ID in event context bool buf_size_set; ///< True iff buffer size callback fired } Jalv; diff --git a/src/lv2_evbuf.c b/src/lv2_evbuf.c index 7877e07..f3aea8d 100644 --- a/src/lv2_evbuf.c +++ b/src/lv2_evbuf.c @@ -14,8 +14,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <stdint.h> -#include <stdbool.h> #include <string.h> #include <stdlib.h> @@ -27,9 +25,11 @@ struct LV2_Evbuf_Impl { LV2_Evbuf_Type type; uint32_t capacity; + uint32_t atom_Chunk; + uint32_t atom_Sequence; union { - LV2_Event_Buffer event; - LV2_Atom_Port_Buffer atom; + LV2_Event_Buffer event; + LV2_Atom_Sequence atom; } buf; }; @@ -40,14 +40,19 @@ lv2_evbuf_pad_size(uint32_t size) } LV2_Evbuf* -lv2_evbuf_new(uint32_t capacity, LV2_Evbuf_Type type, uint32_t atom_type) +lv2_evbuf_new(uint32_t capacity, + LV2_Evbuf_Type type, + uint32_t atom_Chunk, + uint32_t atom_Sequence) { // FIXME: memory must be 64-bit aligned LV2_Evbuf* evbuf = (LV2_Evbuf*)malloc( sizeof(LV2_Evbuf) + sizeof(LV2_Atom_Sequence) + capacity); - evbuf->capacity = capacity; - lv2_evbuf_set_type(evbuf, type, atom_type); - lv2_evbuf_reset(evbuf); + evbuf->capacity = capacity; + evbuf->atom_Chunk = atom_Chunk; + evbuf->atom_Sequence = atom_Sequence; + lv2_evbuf_set_type(evbuf, type); + lv2_evbuf_reset(evbuf, true); return evbuf; } @@ -58,7 +63,7 @@ lv2_evbuf_free(LV2_Evbuf* evbuf) } void -lv2_evbuf_set_type(LV2_Evbuf* evbuf, LV2_Evbuf_Type type, uint32_t atom_type) +lv2_evbuf_set_type(LV2_Evbuf* evbuf, LV2_Evbuf_Type type) { evbuf->type = type; switch (type) { @@ -67,18 +72,13 @@ lv2_evbuf_set_type(LV2_Evbuf* evbuf, LV2_Evbuf_Type type, uint32_t atom_type) evbuf->buf.event.capacity = evbuf->capacity; break; case LV2_EVBUF_ATOM: - evbuf->buf.atom.data = (LV2_Atom*)(evbuf + 1); - evbuf->buf.atom.size = sizeof(LV2_Atom_Port_Buffer); - evbuf->buf.atom.capacity = evbuf->capacity; - evbuf->buf.atom.data->type = atom_type; - evbuf->buf.atom.data->size = 0; break; } - lv2_evbuf_reset(evbuf); + lv2_evbuf_reset(evbuf, true); } void -lv2_evbuf_reset(LV2_Evbuf* evbuf) +lv2_evbuf_reset(LV2_Evbuf* evbuf, bool input) { switch (evbuf->type) { case LV2_EVBUF_EVENT: @@ -88,7 +88,13 @@ lv2_evbuf_reset(LV2_Evbuf* evbuf) evbuf->buf.event.size = 0; break; case LV2_EVBUF_ATOM: - evbuf->buf.atom.data->size = 0; + if (input) { + evbuf->buf.atom.atom.size = 0; + evbuf->buf.atom.atom.type = evbuf->atom_Sequence; + } else { + evbuf->buf.atom.atom.size = evbuf->capacity; + evbuf->buf.atom.atom.type = evbuf->atom_Chunk; + } } } @@ -99,7 +105,9 @@ lv2_evbuf_get_size(LV2_Evbuf* evbuf) case LV2_EVBUF_EVENT: return evbuf->buf.event.size; case LV2_EVBUF_ATOM: - return evbuf->buf.atom.data->size; + return evbuf->buf.atom.atom.type == evbuf->atom_Sequence + ? evbuf->buf.atom.atom.size + : 0; } return 0; } @@ -154,7 +162,7 @@ lv2_evbuf_next(LV2_Evbuf_Iterator iter) break; case LV2_EVBUF_ATOM: size = ((LV2_Atom_Event*) - ((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, evbuf->buf.atom.data) + ((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, &evbuf->buf.atom) + offset))->body.size; offset += lv2_evbuf_pad_size(sizeof(LV2_Atom_Event) + size); break; @@ -179,10 +187,10 @@ lv2_evbuf_get(LV2_Evbuf_Iterator iter, return false; } - LV2_Event_Buffer* ebuf; - LV2_Event* ev; - LV2_Atom_Port_Buffer* abuf; - LV2_Atom_Event* aev; + LV2_Event_Buffer* ebuf; + LV2_Event* ev; + LV2_Atom_Sequence* aseq; + LV2_Atom_Event* aev; switch (iter.evbuf->type) { case LV2_EVBUF_EVENT: ebuf = &iter.evbuf->buf.event; @@ -194,9 +202,9 @@ lv2_evbuf_get(LV2_Evbuf_Iterator iter, *data = (uint8_t*)ev + sizeof(LV2_Event); break; case LV2_EVBUF_ATOM: - abuf = &iter.evbuf->buf.atom; + aseq = (LV2_Atom_Sequence*)&iter.evbuf->buf.atom; aev = (LV2_Atom_Event*)( - (char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, abuf->data) + (char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, aseq) + iter.offset); *frames = aev->time.frames; *subframes = 0; @@ -217,10 +225,10 @@ lv2_evbuf_write(LV2_Evbuf_Iterator* iter, uint32_t size, const uint8_t* data) { - LV2_Event_Buffer* ebuf; - LV2_Event* ev; - LV2_Atom_Port_Buffer* abuf; - LV2_Atom_Event* aev; + LV2_Event_Buffer* ebuf; + LV2_Event* ev; + LV2_Atom_Sequence* aseq; + LV2_Atom_Event* aev; switch (iter->evbuf->type) { case LV2_EVBUF_EVENT: ebuf = &iter->evbuf->buf.event; @@ -241,22 +249,23 @@ lv2_evbuf_write(LV2_Evbuf_Iterator* iter, iter->offset += size; break; case LV2_EVBUF_ATOM: - abuf = &iter->evbuf->buf.atom; - if (abuf->capacity - abuf->data->size < sizeof(LV2_Atom_Event) + size) { + aseq = (LV2_Atom_Sequence*)&iter->evbuf->buf.atom; + if (iter->evbuf->capacity - sizeof(LV2_Atom) - aseq->atom.size + < sizeof(LV2_Atom_Event) + size) { return false; } aev = (LV2_Atom_Event*)( - (char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, abuf->data) + (char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, aseq) + iter->offset); aev->time.frames = frames; aev->body.type = type; aev->body.size = size; memcpy(LV2_ATOM_BODY(&aev->body), data, size); - size = lv2_evbuf_pad_size(sizeof(LV2_Atom_Event) + size); - abuf->data->size += size; - iter->offset += size; + size = lv2_evbuf_pad_size(sizeof(LV2_Atom_Event) + size); + aseq->atom.size += size; + iter->offset += size; break; } diff --git a/src/lv2_evbuf.h b/src/lv2_evbuf.h index b2caa12..fdb7766 100644 --- a/src/lv2_evbuf.h +++ b/src/lv2_evbuf.h @@ -18,10 +18,11 @@ #define LV2_EVBUF_H #include <stdint.h> -#include <stdbool.h> #ifdef __cplusplus extern "C" { +#else +#include <stdbool.h> #endif /** @@ -54,11 +55,13 @@ typedef struct { /** Allocate a new, empty event buffer. - The URID for atom:Sequence must be passed for atom_Sequence if type is - LV2_EVBUF_ATOM. + URIDs for atom:Chunk and atom:Sequence must be passed for LV2_EVBUF_ATOM. */ LV2_Evbuf* -lv2_evbuf_new(uint32_t capacity, LV2_Evbuf_Type type, uint32_t atom_type); +lv2_evbuf_new(uint32_t capacity, + LV2_Evbuf_Type type, + uint32_t atom_Chunk, + uint32_t atom_Sequence); /** Free an event buffer allocated with lv2_evbuf_new. @@ -67,21 +70,21 @@ void lv2_evbuf_free(LV2_Evbuf* evbuf); /** - Change the type of an existing event buffer. This will clear and reset the - buffer, it is not possible to change the type and preserve the buffer - contents since the formats differ. The URID for atom:Sequence must be - passed for atom_Sequence if type is LV2_EVBUF_ATOM. + Reset and change the type of an existing event buffer. + URIDs for atom:Chunk and atom:Sequence must be passed for LV2_EVBUF_ATOM. */ void -lv2_evbuf_set_type(LV2_Evbuf* evbuf, LV2_Evbuf_Type type, uint32_t atom_type); +lv2_evbuf_set_type(LV2_Evbuf* evbuf, LV2_Evbuf_Type type); /** Clear and initialize an existing event buffer. The contents of buf are ignored entirely and overwritten, except capacity which is unmodified. + If input is false and this is an atom buffer, the buffer will be prepared + for writing by the plugin. This MUST be called before every run cycle. */ void -lv2_evbuf_reset(LV2_Evbuf* evbuf); +lv2_evbuf_reset(LV2_Evbuf* evbuf, bool input); /** Return the total padded size of the events stored in the buffer. |