aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/atom_rdf.c2
-rw-r--r--src/jalv.c70
-rw-r--r--src/jalv_internal.h19
-rw-r--r--src/lv2_evbuf.c79
-rw-r--r--src/lv2_evbuf.h23
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"));
diff --git a/src/jalv.c b/src/jalv.c
index 5f89962..8e7d9ae 100644
--- a/src/jalv.c
+++ b/src/jalv.c
@@ -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.