mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-02 09:01:46 -05:00
bluetooth: Update source software volume on AVRCP SetAbsoluteVolume
The A2DP spec mandates that the audio rendering device - the device
receiving audio, in our case a `pa_source` - is responsible for
performing attenuation:
AVRCP v1.6.2, §5.8:
The SetAbsoluteVolume command is used to set an absolute volume to be used by the rendering device.
BlueZ models this call as a change of the `Volume` property on the
`org.bluez.MediaTransport1` interface. Supporting Absolute Volume is
optional but BlueZ unconditionally reports feature category 2 in its
profile, mandating support. Hence remote devices (ie. a phone) playing
back audio to a machine running PulseAudio assume volume is to be
changed through SetAbsoluteVolume, without performing any local
attenuation.
Future changes will implement this feature the other way around: setting
an initial value for the `Volume` property as well as propagating
`pa_source` volume changes back to the peer.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/239>
This commit is contained in:
parent
c098a75d10
commit
710a35cdc3
2 changed files with 45 additions and 0 deletions
|
|
@ -101,6 +101,19 @@
|
|||
" </interface>" \
|
||||
"</node>"
|
||||
|
||||
static pa_volume_t a2dp_gain_to_volume(uint16_t gain) {
|
||||
pa_volume_t volume = (pa_volume_t) ((
|
||||
gain * PA_VOLUME_NORM
|
||||
/* Round to closest by adding half the denominator */
|
||||
+ A2DP_MAX_GAIN / 2
|
||||
) / A2DP_MAX_GAIN);
|
||||
|
||||
if (volume > PA_VOLUME_NORM)
|
||||
volume = PA_VOLUME_NORM;
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
struct pa_bluetooth_discovery {
|
||||
PA_REFCNT_DECLARE;
|
||||
|
||||
|
|
@ -496,6 +509,24 @@ void pa_bluetooth_transport_set_state(pa_bluetooth_transport *t, pa_bluetooth_tr
|
|||
}
|
||||
}
|
||||
|
||||
static void pa_bluetooth_transport_remote_volume_changed(pa_bluetooth_transport *t, uint16_t gain) {
|
||||
pa_volume_t volume;
|
||||
|
||||
pa_assert(t);
|
||||
|
||||
volume = a2dp_gain_to_volume(gain);
|
||||
|
||||
/* increment volume by one to correct rounding errors */
|
||||
if (volume < PA_VOLUME_NORM)
|
||||
volume++;
|
||||
|
||||
if (t->source_volume == volume)
|
||||
return;
|
||||
|
||||
t->source_volume = volume;
|
||||
pa_hook_fire(pa_bluetooth_discovery_hook(t->device->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_SOURCE_VOLUME_CHANGED), t);
|
||||
}
|
||||
|
||||
void pa_bluetooth_transport_put(pa_bluetooth_transport *t) {
|
||||
pa_assert(t);
|
||||
|
||||
|
|
@ -679,6 +710,8 @@ static void parse_transport_property(pa_bluetooth_transport *t, DBusMessageIter
|
|||
if (key == NULL)
|
||||
return;
|
||||
|
||||
pa_log_debug("Transport property %s changed", key);
|
||||
|
||||
dbus_message_iter_recurse(i, &variant_i);
|
||||
|
||||
switch (dbus_message_iter_get_arg_type(&variant_i)) {
|
||||
|
|
@ -701,6 +734,17 @@ static void parse_transport_property(pa_bluetooth_transport *t, DBusMessageIter
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
case DBUS_TYPE_UINT16: {
|
||||
uint16_t value;
|
||||
dbus_message_iter_get_basic(&variant_i, &value);
|
||||
|
||||
if (pa_streq(key, "Volume")) {
|
||||
if (t->profile == PA_BLUETOOTH_PROFILE_A2DP_SOURCE)
|
||||
pa_bluetooth_transport_remote_volume_changed(t, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue