If no packets have been received and spa_bt_decode_buffer_process is
called, this->packet_size.max == INT32_MIN, which can give overflows.
Guard against this condition, although it should be harmless.
React immediately to "bad" buffer level. Use smaller bitrate
increments/decrements. Fix ABR timer increment for fragmented packets.
Handle actual bitrate being smaller than target during silence.
Support Opus as A2DP vendor codec.
The specification for vendor A2DP codec is our Pipewire-specific one, so
it is compatible only with devices running Pipewire.
The device is not know at SelectConfiguration time, so the settings
argument in select_config is currently unused. Pass on a global settings
dict instead, so that codec parameters can be configured.
Also add settings argument to caps_preference_cmp.
Bump codec API version.
Add a flag A2DP_CODEC_FLAG_SINK to incidate a sink endpoint.
Also enum_config and caps_preference_cmp may need to know whether the
codec is being configured for SRC or SNK. Also add the flags argument to
init_props.
Bump codec API version.
a2dp-sink writing duplex data to the BT socket breaks a2dp-source source
polling, also in A2DP source role. Hence, use the timer-based polling
workaround always in duplex mode.
User changing volume via headset buttons should be treated on the same
level as changing from desktop UI. Also initial headset volume should
be considered saved (even though session managers currently ignore the
initial route values on route restore).
Mark route as saved on volume events.
When emitting node, get initial volumes from transport hardware volume,
if available.
The session manager usually overrides these immediately with saved
values, but it's better to show the HW volume when the node first
appears.
The A2DP and HFP profiles may have different volume curves, so trying to
convert volumes between the two can produce undesirable volume spikes.
For example, when one of them is using hardware volume and the other
software.
Fix by separating HFP and A2DP routes.
a2dp-source as driver does not produce regularly spaced graph cycles,
because A2DP is not isochronous. This causes e.g. crackling for alsa
etc. that expect regular timings. It also does not rate match.
Change a2dp-source to trigger graph on regular intervals. Change recv to
only accumulate data to a buffer, and put data to buffers in process().
Rate match with DLL, keeping average buffer level constant. Keep track
of jitter to determine a safe target value.
It causes some headsets behave strangely. See pipewire#2391,
pipewire#1853.
The BlueZ issue of AVRCP volume sometimes missing that this worked
around was fixed in recent versions. The issue of some headsets not
sending volume without AVRCP player remains, but it appears this breaks
more headsets than fixes.
Don't try to reconnect or wait for profiles, which cannot be connected
because the adapter doesn't have the counterpart sink/source profile.
E.g. we should not reconnect/wait for HFP HF on remote device, if
we don't have the corresponding HFP AG.
If A2DP remote does not acquire its pending transport within a timeout,
we won't get a write error in a2dp-sink, but instead the transport
becomes idle. Currently, we continue writing to the socket as if
everything was fine, even though the data won't be processed at the
remote end.
Handle this by stopping the node and emitting a node error event.
Pipewire may then restart the node to retry.