BAP Clients do not have endpoints associated with them, and we only know
that codecs on currently configured transports are supported.
Handle this case in spa_bt_device_supports_media_codec
BlueZ fails registering object managers containing A2DP endpoints if
controller is in LE-only mode.
Make the A2DP and BAP object managers separate, so that failure to
register one does not prevent registering the other.
Also rename some functions to indicate which ones deal with the legacy
BlueZ API.
Make a real debug context with a log function and move it to a new file.
This way we don't need to redefine a macro.
Make a new context for debugging to a log file. Make new functions to
debug to a log file.
Move the stringbuffer to string utils.
Integrate file/line/func and topics into the debug log.
We can remove some more things from the pipewire log_object function and
also add support for topics.
BlueZ may send multiple PACs in the capabilities delimited by zero LTV.
Handle this case by selecting the "best" one.
The configuration size may also for BAP generally be different from PAC
size.
AVDTP in principle allows 62 endpoints, but in practice it appears some
devices (Samsung Galaxy Buds2 Pro, Redmi Buds 3 Lite, probably others)
fail to connect A2DP when the number is somewhere above 24. A2DP
connection works when initiated from the Central, but not when the
device itself does it, so these devices are not fully broken. We should
reduce the number of registered A2DP endpoints to avoid running into
problems with such broken devices.
Some of our source codecs are the same actual codec with the same
configuration, and don't need separate source endpoints.
Allow codecs to not have a registered endpoint (fill_caps == NULL), and
tolerate codecs with the same endpoint name. In codec switch, keep
track separately which of the codecs with the same endpoint name the
local endpoint is currently associated with.
Introduce `unregister_media_endpoint()` to unregister the specified
media endpoint object from dbus. Moreover, move the logic that decides
whether or not a particular codec should be registered for a given
direction into `endpoint_should_be_registered()` and use that in
both `(un)register_media_endpoint()`.
The codec may need to take into account endpoint preferred QoS values,
so parse this information and pass it to the codec's get_qos.
All the QoS struct values need to be set, as otherwise BlueZ may pass
uninitialized zero values over the air, which devices can reject. This
does not apply to CIG/CIS ids, which are automatically allocated by
default.
Fixes connecting to nrf5340 devkit, which requires a valid TargetLatency
value.
Commit 947ee152d3 ("bluez: check dbus service before enumerating objects")
introduced a check that would esure that GetManagedObjects()
is not called if the "org.bluez" name has no owner. This
was done to avoid auto-starting the bluez daemon.
However, this is not needed because it is possible to set on
a per-message basis whether or not the destination service
should be automatically started by the dbus daemon.
BlueZ adds the Endpoint property to the Properties dictionary of
SelectProperties.
This allows to know which remote Endpoint is an acceptor, and so which
local transport should be used as an initiator.
Multiple transport from the same device may share the same stream (CIS)
and group (CIG) but for different direction, e.g. a speaker and a
microphone. In this case they are linked.
In this case:
- On acquire, if another transport has already been acquired, the new
transport should not call Acquire or TryAcquire but re-use values from
the previously acquired transport,
- on release, the closing of transport fd and call to Release should be
done only for the last transport.
We can't determine which remote endpoint or device the
SelectConfiguration() call is associated with. For LE Audio BAP, as this
method is called only for the Initiator we set the whole instance as a
Central/Initiator.
This flag is unset on BAP media endpoint removal.
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.
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.
Endpoints without decode/encode capability are skipped in the object
manager, but we should also skip them in the registration calls (even
though in practice this doesn't appear to matter).
AVDTP (v1.3 Sec 5.3) has a limitation that a local SEP (on the same
adapter) can be connected to at most one remote SEP. Trying to do have
it connected to multiple remotes either fails or causes misbehavior
later on.
Skip SetConfigure the same local endpoint for multiple remote ones in
codec switch. BlueZ observes this restriction in SelectConfiguration,
so also it won't try to do invalid configurations.
In BlueZ 5.64, the SetConfiguration calls succeed, but subsequent
transport acquires will fail. (Likely already the SetConfiguration DBus
call should fail.)
This all has the consequence, with the current approach to the
codec=endpoint correspondence, that if multiple devices are connected to
the same adapter, they currently have to use different codecs.
When device is disconnected, running codec switches are not meaningful,
and should be stopped.
The codec switch callback may also trigger A2DP profile switch, which
may reconnect the device. Fix it so this does not happen.
See #2334
Codec probe connections can trigger bad behavior from oFono if done when
device is busy (e.g. at connect), and they might be done at the same
time as A2DP transport is acquired which cannot work.
Also, oFono will not reply to DBus Acquire, if device does not complete
codec negotiation correctly. This is most likely to happen just after
device connect, when it is busy with other stuff (eg A2DP).
Remove codec probe connections altogether: instead, we guess mSBC if
mSBC is enabled and otherwise CVSD. If the guess turns out to be wrong,
which is unlikely (almost all devices have mSBC), we recreate the
transport with correct codec (from main loop, must not be done in
*_acquire because that can destroy nodes + unload the spa libs while
we're being called from there).
To avoid oFono DBus hangs at startup, add delay before marking the
profile connected, enforcing a time difference to A2DP operations.
This allows BT device to connect instantly instead of waiting for profile
timeout when hsp/hfp backend is none, because all available profiles are
connected.
When acting as SCO AG / A2DP sink, the remote end should decide when to
close the connection. This does not work currently properly, because
stopping sources/sinks releases the transport, which causes it to go
idle, and which then destroys dynamic nodes. The sources/sinks should
not cause the transport to be released.
Implement keepalive flag for spa_bt_transport, such that
spa_bt_transport_release does not actually release the transport when
the refcount reaches zero. Set the flag for dynamic nodes when the
transport becomes pending (remote end connects) and unset the flag when
idle (remote end disconnected, or dynamic node removed).
Devices may appear before or after their adapter does on BlueZ DBus
interface.
When an adapter appears, search the device list, and associated its
devices with it.