This will also change the internal backend name, so it will miss the
previous 'config' setting '<State backend="Pulseaudio" ...'` and the
session file's '<EngineHints backend="Pulseaudio" ...'. But that is no
big deal after upgrading. Especially after the backend has been broken
for some users for a while.
This is required to collect relevent undo/redo information, notably
automation-data changes from Playlist::update_after_tempo_map_change and
DiskReader::playlist_ranges_moved.
The realtime thread should not move regions to begin with, and debug
builds woudl also assert since no undo operation was started.
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
Now using a globally-scoped static variable which is updated by the
AudioEngine whenever an SR change occurs. Defaults to 48kHz and can
be used even before there is a backend.
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.
When bouncing Region or Range, Session::write_one_track()
blocks processing, but takes no process-lock.
It is possible that a latency-callback arrives at the same
time while Route::bounce_process is active and calls ::run.
This can trigger a delayline.cc Assertion `lm.locked ()' failed
in either thread.
Now latency-callbacks are postponed until the session can
process normally again
This fixes async callback from CoreAudio via
AudioDeviceAddPropertyListener. Apparently in rare cases it can
happen that the property listener calls back concurrently with
processing on M1 machines using Rosetta.
https://pastebin.com/upvc9LTc Thread 44 vs. Thread 32
May also be caused by plugin(s) taking a long time to
change buffersize. Processing continues even though the
buffersize callback has not yet completed.
PS. I have not been able to reproduce this on an Intel
machine, even with excessive buffersize changes. However
since buffersize changes cannot (usually) happen concurrently
with processing, taking the lock is reasonable.
Capture latency needs to be updated before playback latency,
various internal parts depend on this order (which is also
the default for libjack itself).
Portmanager uses "ports" as local variable in various places
(usually vector<string>). While the compiler is fine with that,
it is confusing when debugging or reading code.
"While 'atomic' has a volatile qualifier, this is a historical
artifact and the pointer passed to it should not be volatile."
Furthermore "It is very important that all accesses to a
particular integer or pointer be performed using only this API"
(from https://developer.gnome.org/glib/2.68/glib-Atomic-Operations.html)
Hence initialization of atomic variables is changed to also use
this API, instead of directly initializing the value.
This also fixes a few cases where atomic variables were
accessed directly.
see also libs/pbd/pbd/g_atomic_compat.h
TMM ports cannot exist without a backend.
This fixes crashes where the PortEngine is re-initialized
(backend change):
Previously, TMM ports were only dropped (and recreated)
in TMM::restart() called from ARDOUR::init_post_engine().
When starting a new backend the old one is already destroyed,
but TM still held reference to Ports owned by that backend.
Calling the port's d'tor caused a memory corruption trying to
acquire the backend's port_callback_mutex:
e.g. When creating new session with a different backend
from a running instance, or unit-test after call to
AudioEngine::destroy(): https://pastebin.com/4D6pLA5s
This is only relevant with JACK, where different implementations
use threads for the latency callback.
With jack 2, jack_port_register() blocks and the jack_latency_callback
arrives in a different thread: https://pastebin.com/mitGBwpq
with jack 1 the callback arrives in sync
In either case this usually happens while
_adding_routes_in_progress == true and Ardour holds the process-lock,
because jack2 can process in parallel with reconfiguring latency
See also 1983f56592
This can help when running with very low latency and the
initial process callback is [indirectly] expensive.
E.g. load a heavy session the a RPi4, initial setup can pull
in a lot of data, which blocks the bus.
In particular with the ALSA backend this can lead to poll timeout
which effectively stops the backend.
This allows for caches to warm up, background worker threads to
spin up and things settle down. This also prevents initial
audible artifacts of live input.
In almost all cases this completes before the GUI is brought up.
Substantive comments associated with code in Session::plan_master_strategy.
Known not to work for reverse TC. Also, the JACK related code has not yet been tested
This fixes an issue that after changing backends (::set_backend),
the session-transport was in inconsistent state. If it was rolling,
it continued to roll with "stop" being unavailable.
Session::process() can call split-cycle which offset the
buffer pointers. When vari-speeding at speed > 1.0, the
engine also splits the cycle every n_samples, to not exceed
the configured buffersize. This needs to take prior buffer
offsets into account.