diff options
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | src/jalv.c | 51 | ||||
-rw-r--r-- | src/jalv_internal.h | 2 |
3 files changed, 56 insertions, 2 deletions
@@ -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; @@ -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 |