* don't create a new MixerScene if one already exists
* only resize the vector when necessary
* adding a new scene at position N should not shrink the vector size
No behavior should be changed by this modification; the argument has a default value of false, which
matches previous semantics, and every instance where the argument is specified, it is given as false.
Session::route_processors_changed accumulates signals emitted
in realtime and processing is delegated to a dedicated rt-safe
thread. Previously this resulted in any changed to be converted
to a `GeneralChange`, which unconditionally triggered a route-reorder.
Record-arming a track causes a MeterPointChange (meters change to "in"),
and this caused routes to be resorted and a latency-update.
While the former is reasonable (Ardour prefers to process
rec-armed routes first), the latter certainly is not.
This allows to pass any GraphChain to the Graph to process.
It removes the need to use a mutex to swap two dedicated
chains (setup-chain <> active-chain, pending-chain).
Also various special cases pertaining to graph interaction
while auditioning and route-deletion can be removed.
This also unconditionally creates a graph-thread for GraphChains
to be processed, even if the main callback uses a special-cased
sorted RouteList if there is only one process thread.
The process-graph should only be concerned with GraphNodes,
which may or may not be Routes.
This also removes intrinsic connection information from
the graph-node. Connection information is to be kept separate
from the nodes.
When the graph is re-calculated in the background, old information
has to be retained until the new graph becomes active.
Previously *new* information was already stored in the nodes
while the graph is sorted, even though the new graph was not
active.
This commit leaves two issues outstanding:
1. unclear/ugly semantics for drag operations that reset the GUI thread's tempo map to the writable copy
2. undo/redo for the tempo map
These will be addressed in future commits
This allows two reader threads to proceed without blocking each other, as can
happen when the butler renders a MIDI track into an RT-safe buffer while the
GUI reads the same MidiModel/Source for visual display.
We do not want a value as large as the previous one, which limits the time
range that can be represented in 62 bits unnecessarily. The new value is
9 times smaller than the previous value, and loses only 384000 as a significant
factor.
This commit also switches to using an (inline) accessor for superclock_ticks_per_second,
making it possible in debug/testing phases to spot early/illegal uses of the value.
In order to detect if route delaylines need to be updated,
aux-send delaylines need to be updated first. This was previously
done directly in the latency-callback, which may be concurrent
with processing.
Now only the information (pending_delay) is set, and the actual
change happens later at the end of process().
Due to _init_countdown when the engine starts, it is
extremely unlikely that Session::initialize_latencies(),
which is invoked by AudioEngine::Running runs concurrently
with Session::process, but at least in theory it would be possible.
block_processing() may hold the process-lock, waiting
for the latency-lock. at the same time audio-engine
may hold the latter, trying to acquire the former.
Just like PluginInsert::update_sidechain_name, the name is
implicitly set, using the owning route's name, suffixed with the
[i18n localized] Processor name.
This fixes an issue if a track is renamed and a new track with
the old name is created. This commonly happens during File Import:
For each ImportAsTrack a generic named track (e.g. "Audio") is created
before it is renamed.
Previously this lead to
Failed to register port "Audio 1-trig/midi_in 1", reason is unknown from here
This works around a race-condition, calling d'tors from
two threads concurrently.
The GUI thread destroys ctrl surfaces. ~~MIDIControllable()
calls ::drop_external_control() -> ::midi_forget()
This unsubscribes from signals (notably MIDI::Parser events)
by calling ScopedConnection::disconnect(), Connection::disconnect().
At the same time auto_connect_thread can call
PortManager::clear_pending_port_deletions() which removes
the MIDI port and destorys the MIDI::Parser.
~Parser() calls Connection::signal_going_away() to invalidate
connected signals.
This can deadlock if it is called concurrently with
Connection::disconnect() on the same signal.
see also
https://discourse.ardour.org/t/ardour-session-close-hangs/106523/10
When loading a session, we now just set up port state, which will
populate the Port::_connections member, and then once all ports have
been created, use PortManager::reconnect_ports() to get everything connected.