Re: [PATCH BlueZ] audio/transport: Only store volume when also emitting DBus prop change

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Marijn,

On Mon, Aug 9, 2021 at 1:26 PM Marijn Suijten
<marijn.suijten@xxxxxxxxxxxxxx> wrote:
>
> Hi Luiz,
>
> On 8/9/21 8:37 PM, Luiz Augusto von Dentz wrote:
> > Hi Marijn,
> >
> > On Sun, Aug 8, 2021 at 7:35 AM Marijn Suijten
> > <marijn.suijten@xxxxxxxxxxxxxx> wrote:
> >>
> >> By setting a2dp->volume early in set_volume() the resulting call to
> >> media_transport_update_volume() when an AVRCP reply is received will
> >> likely see the same volume received (unless the peer rounded it to
> >> another value) and bail on equality, before emitting a DBus property
> >> change.  This results in DBus clients not being made aware of the change
> >> unless the peer is an audio source (that receives a notification about
> >> changed volume, instead of a command to _set_ a new volume), where
> >> set_volume() immediately raises the DBus signal.
> >>
> >> This issue is observed when playing back audio to headphones through an
> >> AbsoluteVolume-enabled audio server like PulseAudio, which does not
> >> receive the "Volume" change (while the peer does change volume) when
> >> setting this property externally using ie. dbus-send.
> >
> > Have you confirmed this works with the likes of PulseAudio, afaik
> > there was some problem when introducing this because the event may
> > cause a double change on the volume so the server needs to be able to
> > handle the volume == local volume, anyway if the headset rounds and
> > the values doesn't match I guess the server will need to be smart
> > enough to not trigger another volume change otherwise it could cause a
> > loop where the server request x but the headset rounds to y over and
> > over.
>
>
> Thank you for your concerns.  I as the author of AVRCP Absolute Volume
> support in PulseAudio made sure to insert these equality checks against
> the last known Absolute Volume value (separate from user-visible volume
> managed by PA), both when Volume is received from the peer:
>
> https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/blob/1a575bb0a708bc455e977629cb99412551867982/src/modules/bluetooth/bluez5-util.c#L614-621
>
> And when sending a new Volume back:
>
> https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/blob/1a575bb0a708bc455e977629cb99412551867982/src/modules/bluetooth/bluez5-util.c#L554-557
>
> These together make it impossible to call ".Set" on a value that is
> identical to the last value received through the "PropertiesChanged"
> signal.  It was made this way to prevent round-trips in the first place,
> as receiving a Volume change and applying it to PA's sink/source would
> also trigger the "volume changed" handler.  Even if the peer decides to
> reply with Volume-1 for every request, there will still be no round-trip.
>
> > If the server never reacts if volume != local volume and instead
> > just updates the local volume, which is probably the behavior we want,
> > then I should be safe to apply this change.
> That is exactly what happens because PA cannot distinguish between
> replies to SetAbsoluteVolume and the ABSOLUTE_VOLUME_CHANGED
> notification caused by button presses, when just looking at the Volume
> property.
>
> Finally, I don't know what PipeWire does.  Someone will have to look
> through the codebase and confirm that it performs the same checks, or
> loop in one of the authors in cc to confirm.  Sonny from CrOS is already
> included to make sure this doesn't break anything on their end.
>
> >
> >> ---
> >>   profiles/audio/transport.c | 6 +++---
> >>   1 file changed, 3 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c
> >> index 8248014ae..d158fc97a 100644
> >> --- a/profiles/audio/transport.c
> >> +++ b/profiles/audio/transport.c
> >> @@ -659,14 +659,14 @@ static void set_volume(const GDBusPropertyTable *property,
> >>          if (a2dp->volume == volume)
> >>                  return;
> >>
> >> -       a2dp->volume = volume;
> >> -
> >>          notify = transport->source_watch ? true : false;
> >> -       if (notify)
> >> +       if (notify) {
> >> +               a2dp->volume = volume;
> >>                  g_dbus_emit_property_changed(btd_get_dbus_connection(),
> >>                                                  transport->path,
> >>                                                  MEDIA_TRANSPORT_INTERFACE,
> >>                                                  "Volume");
> >> +       }
> >>
> >>          avrcp_set_volume(transport->device, volume, notify);
> >>          return;
> >> --
> >> 2.32.0

Applied, thanks.

-- 
Luiz Augusto von Dentz



[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux