From fb192806333ca88d5acb53b849f268611773230d Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 15 Nov 2024 20:38:43 -0500 Subject: Fix Jack latency recomputation when plugin latency changes Paul Davis says "jack_recompute_total_latencies() is a server call. It is not legal to make server calls from within a server callback (like the process callback)." --- src/backend.h | 4 ++++ src/comm.h | 11 +++++++++++ src/jack.c | 27 +++++++++++++++++++++++---- src/jalv.c | 2 ++ src/portaudio.c | 5 +++++ 5 files changed, 45 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/backend.h b/src/backend.h index 2965378..f48287c 100644 --- a/src/backend.h +++ b/src/backend.h @@ -33,6 +33,10 @@ jalv_backend_close(Jalv* jalv); void jalv_backend_activate_port(Jalv* jalv, uint32_t port_index); +/// Recompute latencies based on plugin port latencies if necessary +void +jalv_backend_recompute_latencies(Jalv* jalv); + JALV_END_DECLS #endif // JALV_BACKEND_H diff --git a/src/comm.h b/src/comm.h index e4579eb..11d7dc3 100644 --- a/src/comm.h +++ b/src/comm.h @@ -22,6 +22,7 @@ typedef enum { NO_MESSAGE, ///< Sentinel type for uninitialized messages CONTROL_PORT_CHANGE, ///< Value change for a control port (float) EVENT_TRANSFER, ///< Event transfer for a sequence port (atom) + LATENCY_CHANGE, ///< Change to plugin latency } JalvMessageType; /** @@ -58,6 +59,16 @@ typedef struct { LV2_Atom atom; ///< Event payload header } JalvEventTransfer; +/** + The payload of a LATENCY_CHANGE message. + + This message has a fixed sized, and is described in its entirety by this + struct. +*/ +typedef struct { + float value; ///< Latency in frames at the current sample rate +} JalvLatencyChange; + /** Write a message in two parts to a ring. diff --git a/src/jack.c b/src/jack.c index cf633f9..ea37ac5 100644 --- a/src/jack.c +++ b/src/jack.c @@ -1,4 +1,4 @@ -// Copyright 2007-2022 David Robillard +// Copyright 2007-2024 David Robillard // SPDX-License-Identifier: ISC #include "backend.h" @@ -46,6 +46,9 @@ struct JalvBackendImpl { bool is_internal_client; ///< Running inside jackd }; +/// Maximum supported latency in frames (at most 2^24 so all integers work) +static const float max_latency = 16777216.0f; + /// Internal Jack client initialization entry point int jack_initialize(jack_client_t* client, const char* load_init); @@ -201,9 +204,19 @@ jack_process_cb(jack_nframes_t nframes, void* data) struct Port* const port = &jalv->ports[p]; if (port->flow == FLOW_OUTPUT && port->type == TYPE_CONTROL && port->reports_latency) { - if (jalv->plugin_latency != port->control) { - jalv->plugin_latency = port->control; - jack_recompute_total_latencies(client); + // Get the latency in frames from the control output truncated to integer + const float value = port->control; + const uint32_t frames = + (value >= 0.0f && value <= max_latency) ? (uint32_t)value : 0U; + + if (jalv->plugin_latency != frames) { + // Update the cached value and notify the UI if the latency changed + jalv->plugin_latency = frames; + + const JalvLatencyChange body = {frames}; + const JalvMessageHeader header = {LATENCY_CHANGE, sizeof(body)}; + jalv_write_split_message( + jalv->plugin_to_ui, &header, sizeof(header), &body, sizeof(body)); } } else if (port->flow == FLOW_OUTPUT && port->type == TYPE_EVENT) { void* buf = NULL; @@ -461,6 +474,12 @@ jalv_backend_activate_port(Jalv* jalv, uint32_t port_index) #endif } +void +jalv_backend_recompute_latencies(Jalv* const jalv) +{ + jack_recompute_total_latencies(jalv->backend->client); +} + int jack_initialize(jack_client_t* const client, const char* const load_init) { diff --git a/src/jalv.c b/src/jalv.c index ea0e13b..beb36ca 100644 --- a/src/jalv.c +++ b/src/jalv.c @@ -737,6 +737,8 @@ jalv_update(Jalv* jalv) sizeof(LV2_Atom) + msg->atom.size, jalv->urids.atom_eventTransfer, &msg->atom); + } else if (header.type == LATENCY_CHANGE) { + jalv_backend_recompute_latencies(jalv); } else { return ring_error("Unknown message type received from process ring\n"); } diff --git a/src/portaudio.c b/src/portaudio.c index 9e37d29..4760d48 100644 --- a/src/portaudio.c +++ b/src/portaudio.c @@ -11,6 +11,7 @@ #include "lilv/lilv.h" #include "lv2/atom/atom.h" +#include "zix/attributes.h" #include #include @@ -215,3 +216,7 @@ jalv_backend_activate_port(Jalv* jalv, uint32_t port_index) lilv_instance_connect_port(jalv->instance, port_index, &port->control); } } + +void +jalv_backend_recompute_latencies(Jalv* const ZIX_UNUSED(jalv)) +{} -- cgit v1.2.1