aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS5
-rw-r--r--src/jalv.c51
-rw-r--r--src/jalv_internal.h2
3 files changed, 56 insertions, 2 deletions
diff --git a/NEWS b/NEWS
index 48ba720..b9abcb1 100644
--- a/NEWS
+++ b/NEWS
@@ -1,10 +1,11 @@
jalv (1.4.7) unstable;
- * Exit on jack shutdown (Patch from Robin Gareus)
+ * Exit on Jack shutdown (Patch from Robin Gareus)
+ * Report Jack latency (Patch from Robin Gareus)
* Fix semaphore correctness issues
* Use moc-qt4 if present for systems with multiple Qt versions
- -- David Robillard <d@drobilla.net> Thu, 06 Nov 2014 21:49:59 -0500
+ -- David Robillard <d@drobilla.net> Fri, 13 Feb 2015 20:51:53 -0500
jalv (1.4.6) stable;
diff --git a/src/jalv.c b/src/jalv.c
index d3da181..c523e98 100644
--- a/src/jalv.c
+++ b/src/jalv.c
@@ -590,6 +590,15 @@ jack_process_cb(jack_nframes_t nframes, void* data)
/* Deliver MIDI output and UI events */
for (uint32_t p = 0; p < jalv->num_ports; ++p) {
struct Port* const port = &jalv->ports[p];
+ if (port->flow == FLOW_OUTPUT && port->type == TYPE_CONTROL &&
+ lilv_port_has_property(jalv->plugin, port->lilv_port,
+ jalv->nodes.lv2_reportsLatency)) {
+ if (jalv->plugin_latency != port->control) {
+ jalv->plugin_latency = port->control;
+ jack_recompute_total_latencies(jalv->jack_client);
+ }
+ }
+
if (port->flow == FLOW_OUTPUT && port->type == TYPE_EVENT) {
void* buf = NULL;
if (port->jack_port) {
@@ -646,6 +655,45 @@ jack_process_cb(jack_nframes_t nframes, void* data)
return 0;
}
+/** Calculate latency assuming all ports depend on each other. */
+static void
+jack_latency_cb(jack_latency_callback_mode_t mode, void* data)
+{
+ Jalv* const jalv = (Jalv*)data;
+ const enum PortFlow flow = ((mode == JackCaptureLatency)
+ ? FLOW_INPUT : FLOW_OUTPUT);
+
+ /* First calculate the min/max latency of all feeding ports */
+ uint32_t ports_found = 0;
+ jack_latency_range_t range = { UINT32_MAX, 0 };
+ for (uint32_t p = 0; p < jalv->num_ports; ++p) {
+ struct Port* port = &jalv->ports[p];
+ if (port->jack_port && port->flow == flow) {
+ jack_latency_range_t r;
+ jack_port_get_latency_range(port->jack_port, mode, &r);
+ if (r.min < range.min) { range.min = r.min; }
+ if (r.max > range.max) { range.max = r.max; }
+ ++ports_found;
+ }
+ }
+
+ if (ports_found == 0) {
+ range.min = 0;
+ }
+
+ /* Add the plugin's own latency */
+ range.min += jalv->plugin_latency;
+ range.max += jalv->plugin_latency;
+
+ /* Tell Jack about it */
+ for (uint32_t p = 0; p < jalv->num_ports; ++p) {
+ struct Port* port = &jalv->ports[p];
+ if (port->jack_port && port->flow == flow) {
+ jack_port_set_latency_range(port->jack_port, mode, &range);
+ }
+ }
+}
+
#ifdef JALV_JACK_SESSION
static void
jack_session_cb(jack_session_event_t* event, void* arg)
@@ -976,6 +1024,7 @@ main(int argc, char** argv)
jalv.nodes.lv2_connectionOptional = lilv_new_uri(world, LV2_CORE__connectionOptional);
jalv.nodes.lv2_control = lilv_new_uri(world, LV2_CORE__control);
jalv.nodes.lv2_name = lilv_new_uri(world, LV2_CORE__name);
+ jalv.nodes.lv2_reportsLatency = lilv_new_uri(world, LV2_CORE__reportsLatency);
jalv.nodes.midi_MidiEvent = lilv_new_uri(world, LV2_MIDI__MidiEvent);
jalv.nodes.pg_group = lilv_new_uri(world, LV2_PORT_GROUPS__group);
jalv.nodes.pset_Preset = lilv_new_uri(world, LV2_PRESETS__Preset);
@@ -1206,6 +1255,8 @@ main(int argc, char** argv)
&jack_buffer_size_cb, (void*)(&jalv));
jack_on_shutdown(jalv.jack_client,
&jack_shutdown_cb, (void*)(&jalv));
+ jack_set_latency_callback(jalv.jack_client,
+ &jack_latency_cb, (void*)(&jalv));
#ifdef JALV_JACK_SESSION
jack_set_session_callback(jalv.jack_client,
&jack_session_cb, (void*)(&jalv));
diff --git a/src/jalv_internal.h b/src/jalv_internal.h
index 31eb69b..9700f1f 100644
--- a/src/jalv_internal.h
+++ b/src/jalv_internal.h
@@ -134,6 +134,7 @@ typedef struct {
LilvNode* lv2_connectionOptional;
LilvNode* lv2_control;
LilvNode* lv2_name;
+ LilvNode* lv2_reportsLatency;
LilvNode* midi_MidiEvent;
LilvNode* pg_group;
LilvNode* pset_Preset;
@@ -196,6 +197,7 @@ typedef struct {
uint32_t control_in; ///< Index of control input port
uint32_t num_ports; ///< Size of the two following arrays:
uint32_t longest_sym; ///< Longest port symbol
+ uint32_t plugin_latency; ///< Latency reported by plugin (if any)
float ui_update_hz; ///< Frequency of UI updates
jack_nframes_t sample_rate; ///< Sample rate
jack_nframes_t event_delta_t; ///< Frames since last update sent to UI