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 adding a note, use these criteria to choose the channel number:
* if the user has explicitly specified a note in the pulldown, use that
* if the user has AUTO selected and we are in a region, choose the nearest note's channel (consistent with velocity behavior)
* as a fallback, query the track for its channel-filter (old behavior)
Instead of just restarting it inside the same ::run() call, mark it as waiting,
so that it will restart at the next quantization point.
This isn't a final or even fully correct solution, but it's a useful test of
the idea.
The old code used the instantaneous tempo at T0 to compute where the next
quarter note would be. This is incorrect, since the tempo is
changing (continuously, for now) during the time represented by that quarter
note. Instead, we need to add a quarter note (or technically, whatever the
tempo note type is) to get a new position in beats, then compute the superclock
time at that location (which will use our equations for tempo, including the
use of omega, the ramp factor).
The objects referenced by markers point to the copy of the map held by the per-thread ptr. But
the edits must be done on a writable copy of the map. ::reassociate_metric_markers() fixes
the references to use the writable copy, so that when we pass references to the objects in the map
to the writable copy, it will find them and modify them (rather then ones in the previous
generation of the tempo map)
These comments should correct an impression left in the commit message for
6e9e28343bc3695d that there may be some sort of problem with synchronization
of TempoMap changes. The actual problem is that TempoMap edits are done using
RCU, so the modifications are performaned using a copy of the map, but with
map elements taken from the pre-copy version.
TempoMap::use() merely returns the current per-thread tempo map
pointer; if a change is signalled, we should force an update
of the per-thread ptr via TempoMap::fetch()
The correct algorithm is to traverse the type-specific list of points,
find the point (if any) whose time matches that of the argument (because
we do not allow multiple points of the same type at the same time), and
then use that discovered point from the _points list.
This approach is required because the actual argument may no longer be
in the tempo map (due to a change made by another thread). The lack of
sync, however, needs investigation.