Codec switching does not currently work properly for source/duplex.
With BAP it's also possible only when we're BAP client.
When we can't codec switch, emit the "codecless" BAP profile.
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.
Add new spa_debugc_ funnctions that take a context. The user should also
redefine the spa_debugc macro to handle the context.
Use this to let some plugins log the pod and format to the log without
using the global logger.
Also use this to remove our custom pod logger function by reusing the
spa one with a custom context.
For backward compatibility with old Wireplumber releases, support the
old api.bluez5.a2dp.sink/source names, and use them in object events
instead of the media.sink/source names.
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.
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.
Codec switch flag should be cleared on device connection status change,
to deal with codec_switched() callback not being called if device is
suddenly disconnected.
The PropInfo either has a registered id (and then also a name from the
type-info) or a custom name as a string.
In all cases, the description contains a free form text that clarifies
the property.
Use the description in the stream controls name.
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).
Higher priority for A2DP over HFP/HSP. Prefer mSBC over CVSD for HFP,
and put A2DP codecs in the order we tell BlueZ to use.
Ensures that picking highest-priority profile gives sensible results
(e.g. does not pick HFP unless input route is required, and prefers A2DP
duplex codecs over HFP).
In one we can duplicate the spa_asprintf call without real drawbacks.
The second one can be split up without losing details. Note that there
is another one in backend-native.c where splitting it up will make the
code harder to understand. The warning for that one remains.
Make easier to package A2DP codecs separately, by splitting each to a
separate SPA plugin. Adjust the code to not use a global variable for
the codec list.
The A2DP SPA interface API is in the bluez5 private headers, and not
exposed in installed SPA headers, as it's too close to the
implementation.
There doesn't seem to be a way to control the A2DP duplex microphone
HW volume gain, and devices sometimes have very low mic volumes.
Work around this by boosting the software volume scale by +20 dB. If it
causes clipping, the user can just reduce the volume to bring SW gain
below 1.0.
Some non-standard A2DP codecs (FastStream/aptX-LL) have "voice duplex
channel" that can be used to provide an A2DP duplex mode.
Add support for duplex channels, accounting for the fact that the two
directions may be encoded with different actual codecs.
The codec IDs are user-visible properties.
Some codecs can have multiple endpoints (e.g. different caps struct, or
multiple possible vendor ids), so this detail should not leak to the
user.
Mark some structures, arrays static/const at various places.
In some cases this prevents unnecessary initialization
when a function is entered.
All in all, the text segments across all shared
libraries are reduced by about 2 KiB. However,
the total size increases by about 2 KiB as well.
impl_add_listener() could be called more than one time, ensure that we always emit node info
so that session manager(bluez-monitor) can receives it.
Fixes#1308
bluez5 nodes will always be removed & created again during profile changing, hence
node volume & mute will always be reset. This is OK if profile did changed, because
session manager would carries volume & mute to bluez5 route param. But if profile
was not changed after setting profile (a2dp-sink-sbc -> a2dp-sink -> a2dp-sink-sbc),
session manager would think node volume & mute are not changed and no route
setting is performed, causing route volume out of sync with node volume.
To fix this, we emit node volume and mute right after bluez5 node is created.
Fixes#1254
When we add a new listener to an object, it will emit the full state
of the object. For this it temporarily sets the change_mask to all
changes. Restore the previous state after this or else we might not
emit the right change_mask for the next listener.
Consider the case where one there are two listeners on an object.
The object emits a change and the first listener wants to enumerate the
changed params. For this is adds a new listener and then triggers the
enumeration. If we set the change_mask to 0 after adding the listener,
the second listener would get a 0 change_mask and fail to update
its state.
Make a new softVolume property that contains only the soft volume
to apply.
In the case of HW/SW volume, we pass the real volume in the
channelVolume and the leftover volume in softVolume. We don't
use the monitorVolume for this anymore because it is a completely
separate volume handled by the merger node.
This way, channelVolume always represents the effective volume
set on routes, channelmix and merger and only the softVolume (when
available) is applied as software volume by channelmix.
This makes things map a bit better to what is actually happening with
the real volume and leftover software volumes after applying the
hardware volumes in the device.
With this change, the volume on the monitor is not affected by the
sink volume anymore and we can use the monitorVolume for this later.
This also means that the monitor volume in pavucontrol of the sinks
does not change when the sink volume changes. PulseAudio is inconsistent
here: If the volume is HW, the monitor volume is not affected, if the
volume is SW, it is. In PipeWire there is an option in merger to
let the volume affect the monitor with monitor.channel-volumes = true.