From 19c44fe814b8449ea9d19120a09699b17eb112b3 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Thu, 22 Jun 2023 13:21:45 +0200 Subject: [PATCH] Fix restoring metronome connections (duplicate IO set_state) When a session is loaded, click_io->set_state is called twice. setup_click() is called when the engine re/starts, and possibly again from Session::set_state. During session construction, Port connections are not directly made. Port::set_state just creates a list, which is later applied by Port::reconnect from Session::hookup_io. However, the second call to IO::set_state() calls IO::ensure_ports again. Since the port already exists, this calls Port::disconnect_all (while holding the process lock). Even though the port is not connected at this point in time, this triggers a ARDOUR::PortManager::connect_callback which is emitted from the Audioengine when the process-lock is released. While IO::set_state() continues to set Port::state, and fill the Port::_[ext_]connections lists, this data is invalidated moments later when the engine resumes and ::connect_callback calls ARDOUR::Port::port_connected_or_disconnected. The solution is to simply not call Port::disconnect_all if the connection is not yet made (Session::InitialConnecting) --- libs/ardour/io.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index b9e2a38c38..07682f28e1 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -635,6 +635,13 @@ IO::set_state (const XMLNode& node, int version) if (p) { p->set_state (**i, version); + + if (!_session.inital_connect_or_deletion_in_progress ()) { + /* re-apply connection if create_ports(), ensure_ports() + * disconnected the port + */ + p->reconnect (); + } } } } @@ -864,7 +871,7 @@ IO::create_ports (const XMLNode& node, int version) { Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ()); - if (ensure_ports (n, true, this)) { + if (ensure_ports (n, !_session.inital_connect_or_deletion_in_progress (), this)) { error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg; return -1; }