As was noted in 88ee3af3ea it is unsafe/undefined behavior if two threads
sleep on the JACK request file descriptor, since there is no way to control
which one will wake and process the request. Since each thread may have
sent a different request, this can lead to a thread misinterpreting the
response because it is reading the wrong response.
This may (or may not) solve some subtle problems with JACK, but was
revealed by having a control surface (LaunchPad Pro) that registers
three ports from the butler thread at about the same as the GUI
thread is registering the auditioner. One thread read the wrong
response, and because of some slightly weird code/design, it attempts
to rename the port from within the response handler, which in JACK1
leads to deadlock (and later, zombification).
Without this, two threads can both sleep on the same communication channel, and the wake order
is non-determinate, so the wrong thread may process the response to the other thread's request.
MIDI playback used samples instead of usec.
MIDI capture used time-stamp from previous cycle.
buffer-size changes were not applied to MIDI port latency
On windows this is still limited by the timer resolution, but
it's a start. This is mainly intended to be used with NDI or
other external sources without actual audio hardware.
This correctly sets audio port I/O latency using the
portaudio API.
Per MIDI device port settings are not completely implemented.
En/disabling MIDI devices or setting custom MIDI port latency
is not functional as-is.
port-meta-data depends on the audioengine backend/device
settings. Those are only available after the engine is started,
not from within the backend's _start() method.
This is is only relevant for callback based backends.
Backends with a blocking process thread explicitly emit
port-manager callbacks there before entering the main loop.
Because we use the non-callback API, we can call our thread init callback
ourselves from ::process_thread(). In addition, the init_callback in JACK is
used by every thread JACK creates, including the messagebuffer thread, and this
confuses things from an Ardour POV where the callback was intended just for
realtime threads.
This is mostly a simple lexical search+replace but the absence of operator< for
std::weak_ptr<T> leads to some complications, particularly with Evoral::Sequence
and ExportPortChannel.
It can happen that the main AlsaAudioBackend::_device_reservation
is still busy while I/O devices are set. In this case a
dedicated AlsaDeviceReservation needs to be used which can fail
silently.
A common example is disconnecting a USB device while it is in
use. The Halted signal can show the session dialog, which calls
set_input_device_name before the device reservation of the
unplugged device terminated.
ALSA backend modified the internal state when different devices
were used, re-assigning one (usually input-device) to "None"
when it's resampled. This lead to EngineHints not matching the
EngineState, and autostart was disabled, and a dialog
"Engine I/O device has changed since you last opened this session."
These might be the values that PA would have chosen anyway, but make it
clear that Ardour is in control ... and will let the user control
"everything" with the buffer size.
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.
It adds some new strings to translate. These strings might be so rare
and technical that it is a bit pointless to translate them. But let's
stay consistent...
pa_threaded_mainloop_wait might wake up for several reasons. And there
is no point (but possibly harm) in moving on before we have verified
that PA actually is ready to receive our write without overflow.
ae3c8b19c6 and 03a17df68c reworked the transitions to and from
freewheeling. Some of it seems to have been experiments that tried
several things out, and generally it seems to have worked. It left some
commented out code. Clean that up.
The draining was introduced in ae3c8b19c6, apparently as an experiment
doing several changes. But the drain is outside the loop where
freewheeling changes, so the fix must have worked for other reasons.
There doesn't seem to be any benefit from draining at that point. The
stream is already empty. If not, we could have flushed it.
Draining right after uncorking will conceptualy create an intentional
underflow, even though it isn't reported as such. PipeWire seems to
(something like 6-12 months ago) have regressed in handling of that grey
area, causing that *underflow* to cause a request for too much data, and
thus causing constant *overflows* and unusable playback.
This change makes PulseAudio playback work for me again.