Only schedule nodes together when there is just 1 capture and 1 playback
device. Devices might be mutually exclusive or require special setup
that would break otherwise.
See #3556
Add an option to automatically use snd_pcm_link when the follower clock
is matching the driver. Only set this to true in pro-audio and when
nodes are scheduled together.
See #3556
When we are operating in passthrough, let the Start command pass through
to the follower in all cases. Only do the negotiate/buffers when not in
passthrough.
This fixes a case where the buffers are cleared on the alsa node and it
Pauses but then never resumes in a Start because the node is already
started. The real problem is probably somewhere else (in PipeWire) but
for now this will improve things in passthrough.
We only start the ALSA pcm after we get our first buffer.
We still need to do the sync through (and get the number of prefilled
samples) to make sure we set our new timeout and don't keep on waking
up quickly while the graph fetches the first buffer.
If remote supports both HFP HF and AG, both may get connected, which
occurs with Pipewire<->Pipewire connection. In this case, Pipewire on
both sides may pick the audio-gateway profile.
To avoid both sides being audio-gateway, if remote is both A2DP sink and
HF, use lower priority for the audio-gateway profile. Generally, BlueZ
won't connect both A2DP Source and Sink between same devices at the same
time, so we use that to determine which side should be the receiver.
It may occur that we have RFCOMM connected as both HF and AG. The codec
switching and support checks should in this case always use the remote
HF RFCOMM.
Fix by finding the RFCOMM with the correct profile, remote as HF.
Make sure that the position only advances in the running state.
When we are not following a clock we can simply increment the position
with the duration every time we run.
If we are following a clock. Take the elapsed time of the clock into
account when aligning to the position.
Fixes#3189
Rename some variables to make it clear that we are dealing with the rate
and duration of the driver.
Set the driver rate in the clock instead of the target_rate, which we
might have rejected.
When we are using the same clock (!matching) try to link the two PCM
devices together. This starts and stops the devices at the same time and
gives better latency.
Keep track or the follower state and do the sync from the driver
wakeup.
This improves sync between devices because the sync no longer
depends on when the node was woken up in the graph and scheduled. We
would have been able to handle this difference by using the htimestamp
but that doesn't seen to work reliably on some hardware.
This is also essential for the interrupt based scheduling.
Split the spa_alsa_start() in a prepare and start function. Prepare
will then also reset state and prefill the playback buffer with silence.
This makes it possible to reuse the prepare function in recover().
The threshold depends on the samplerate and even when the graph rate or
quantum didn't change, the driver could be opened in a different
samplerate, which would cause the timeouts to be wrong and cause xruns.