From 5c9f5ae8950ddd3028ad1109063ea98315454b48 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Mon, 2 Aug 2021 23:12:15 +0300 Subject: [PATCH] Prevent DelayLine::set_delay() while processing It was possible that auto-connect-thread or GUI thread called DelayLine::set_delay without acquiring the process-lock. Changing the delay while processing is not supported and can cause glitches. backtrace: ``` DelayLine::set_delay Send::update_delaylines Send::set_delay_out InternalReturn::set_playback_offset Route::update_signal_latency Session::update_route_latency Session::update_latency_compensation Session::auto_connect_thread_run ``` --- libs/ardour/route.cc | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 1f20cae585..6026432380 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -4319,13 +4319,25 @@ Route::update_signal_latency (bool apply_to_delayline, bool* delayline_update_ne /* set capture latency */ snd->output ()->set_private_port_latencies (capt_lat_in + l_in, false); /* take send-target's playback latency into account */ - snd->set_delay_out (snd->output ()->connected_latency (true)); - /* InternalReturn::set_playback_offset() below, also calls set_delay_out() */ + const samplecnt_t snd_lat = snd->output ()->connected_latency (true); + if (apply_to_delayline) { + /* DelayLine::set_delay requires process-lock */ + snd->set_delay_out (snd_lat); + } else if (delayline_update_needed && snd->get_delay_out () != snd_lat) { + *delayline_update_needed = true; + } } + } else if (!apply_to_delayline && boost::dynamic_pointer_cast (*i)) { + /* InternalReturn::set_playback_offset() calls set_delay_out(), requires process lock */ + const samplecnt_t poff = _signal_latency + _output_latency; + if (delayline_update_needed && (*i)->playback_offset () != poff) { + *delayline_update_needed = true; + } + } else { + (*i)->set_playback_offset (_signal_latency + _output_latency); } (*i)->set_input_latency (l_in); - (*i)->set_playback_offset (_signal_latency + _output_latency); (*i)->set_capture_offset (in_latency); if ((*i)->active ()) { l_in += (*i)->effective_latency ();