<div dir="ltr">Hi all,<div><br><div>I just remembered i forgot to add some infos to that patch : </div><div><br><div>Here is a copy and paste of the bluez signal generated when the volume of the a2dp source is changed.</div><div><br></div><div><span style="font-family:monospace">signal sender=:1.2 -> dest=(null destination) serial=154 path=/org/bluez/hci0/dev_B4_18_D1_9C_2B_B6/fd3; interface=org.freede<br>sktop.DBus.Properties; member=PropertiesChanged
<br> string "org.bluez.MediaTransport1"
<br> array [
<br> dict entry(
<br> string "Volume"
<br> variant uint16 31
<br> )
<br> ]
<br> array [
<br> ]<br></span></div><div><span style="font-family:monospace"><br></span></div><div>I hope this attachment will make the review easier.</div><div><br></div><div>Thanks a lot and regards,</div><div>Mathieu Tournier</div></div><br><div class="gmail_quote"><div dir="ltr">On Fri, 11 Mar 2016 at 11:16 Mathieu Tournier <<a href="mailto:mathieutournier@gmail.com" target="_blank">mathieutournier@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Using A2DP and a bluetooth audio source, Pulseaudio doesn't take into account the volume modification (for device sending the event via AVRCP (ex:Apple devices))<br>
This work aims to integrate bluez event Volume (org.bluez.MediaTransport1) for A2DP source in pulseaudio.<br>
This permits to take into account A2DP source volume changes (sent using AVRCP protocol).<br>
<br>
Change has been tested with an iphone and an ipad and is fully working.<br>
---<br>
src/modules/bluetooth/bluez5-util.c | 15 ++++++++++++++<br>
src/modules/bluetooth/bluez5-util.h | 13 ++++++++----<br>
src/modules/bluetooth/module-bluez5-device.c | 30 ++++++++++++++++++++++++++++<br>
3 files changed, 54 insertions(+), 4 deletions(-)<br>
<br>
diff --git a/src/modules/bluetooth/bluez5-util.c b/src/modules/bluetooth/bluez5-util.c<br>
index 03c76bf..c216c6e 100644<br>
--- a/src/modules/bluetooth/bluez5-util.c<br>
+++ b/src/modules/bluetooth/bluez5-util.c<br>
@@ -185,6 +185,14 @@ void pa_bluetooth_transport_set_state(pa_bluetooth_transport *t, pa_bluetooth_tr<br>
pa_hook_fire(&t->device->discovery->hooks[PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED], t->device);<br>
}<br>
<br>
+void pa_bluetooth_transport_set_source_volume(pa_bluetooth_transport *t,uint16_t volume) {<br>
+<br>
+ pa_assert(t);<br>
+ t->source_volume = volume;<br>
+ pa_hook_fire(&t->device->discovery->hooks[PA_BLUETOOTH_HOOK_TRANSPORT_A2DP_SOURCE_VOLUME_CHANGED], t);<br>
+<br>
+}<br>
+<br>
void pa_bluetooth_transport_put(pa_bluetooth_transport *t) {<br>
pa_assert(t);<br>
<br>
@@ -340,6 +348,13 @@ static void parse_transport_property(pa_bluetooth_transport *t, DBusMessageIter<br>
<br>
pa_bluetooth_transport_set_state(t, state);<br>
}<br>
+ case DBUS_TYPE_UINT16: {<br>
+ uint16_t uintValue;<br>
+ dbus_message_iter_get_basic(&variant_i, &uintValue);<br>
+<br>
+ if (pa_streq(key, "Volume"))<br>
+ pa_bluetooth_transport_set_source_volume(t,uintValue);<br>
+ }<br>
<br>
break;<br>
}<br>
diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h<br>
index d66e8a3..3380074 100644<br>
--- a/src/modules/bluetooth/bluez5-util.h<br>
+++ b/src/modules/bluetooth/bluez5-util.h<br>
@@ -36,10 +36,11 @@ typedef struct pa_bluetooth_discovery pa_bluetooth_discovery;<br>
typedef struct pa_bluetooth_backend pa_bluetooth_backend;<br>
<br>
typedef enum pa_bluetooth_hook {<br>
- PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED, /* Call data: pa_bluetooth_device */<br>
- PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED, /* Call data: pa_bluetooth_transport */<br>
- PA_BLUETOOTH_HOOK_TRANSPORT_MICROPHONE_GAIN_CHANGED, /* Call data: pa_bluetooth_transport */<br>
- PA_BLUETOOTH_HOOK_TRANSPORT_SPEAKER_GAIN_CHANGED, /* Call data: pa_bluetooth_transport */<br>
+ PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED, /* Call data: pa_bluetooth_device */<br>
+ PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED, /* Call data: pa_bluetooth_transport */<br>
+ PA_BLUETOOTH_HOOK_TRANSPORT_MICROPHONE_GAIN_CHANGED, /* Call data: pa_bluetooth_transport */<br>
+ PA_BLUETOOTH_HOOK_TRANSPORT_SPEAKER_GAIN_CHANGED, /* Call data: pa_bluetooth_transport */<br>
+ PA_BLUETOOTH_HOOK_TRANSPORT_A2DP_SOURCE_VOLUME_CHANGED, /* Call data: pa_bluetooth_transport */<br>
PA_BLUETOOTH_HOOK_MAX<br>
} pa_bluetooth_hook_t;<br>
<br>
@@ -63,6 +64,7 @@ typedef void (*pa_bluetooth_transport_release_cb)(pa_bluetooth_transport *t);<br>
typedef void (*pa_bluetooth_transport_destroy_cb)(pa_bluetooth_transport *t);<br>
typedef void (*pa_bluetooth_transport_set_speaker_gain_cb)(pa_bluetooth_transport *t, uint16_t gain);<br>
typedef void (*pa_bluetooth_transport_set_microphone_gain_cb)(pa_bluetooth_transport *t, uint16_t gain);<br>
+typedef void (*pa_bluetooth_transport_set_a2dp_source_volume_cb)(pa_bluetooth_transport *t, uint16_t volume);<br>
<br>
struct pa_bluetooth_transport {<br>
pa_bluetooth_device *device;<br>
@@ -77,6 +79,7 @@ struct pa_bluetooth_transport {<br>
<br>
uint16_t microphone_gain;<br>
uint16_t speaker_gain;<br>
+ uint16_t source_volume;<br>
<br>
pa_bluetooth_transport_state_t state;<br>
<br>
@@ -85,6 +88,7 @@ struct pa_bluetooth_transport {<br>
pa_bluetooth_transport_destroy_cb destroy;<br>
pa_bluetooth_transport_set_speaker_gain_cb set_speaker_gain;<br>
pa_bluetooth_transport_set_microphone_gain_cb set_microphone_gain;<br>
+ pa_bluetooth_transport_set_a2dp_source_volume_cb set_source_volume;<br>
void *userdata;<br>
};<br>
<br>
@@ -139,6 +143,7 @@ pa_bluetooth_transport *pa_bluetooth_transport_new(pa_bluetooth_device *d, const<br>
pa_bluetooth_profile_t p, const uint8_t *config, size_t size);<br>
<br>
void pa_bluetooth_transport_set_state(pa_bluetooth_transport *t, pa_bluetooth_transport_state_t state);<br>
+void pa_bluetooth_transport_set_source_volume(pa_bluetooth_transport *t, uint16_t volume);<br>
void pa_bluetooth_transport_put(pa_bluetooth_transport *t);<br>
void pa_bluetooth_transport_unlink(pa_bluetooth_transport *t);<br>
void pa_bluetooth_transport_free(pa_bluetooth_transport *t);<br>
diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c<br>
index 84e6d55..2aa7277 100644<br>
--- a/src/modules/bluetooth/module-bluez5-device.c<br>
+++ b/src/modules/bluetooth/module-bluez5-device.c<br>
@@ -65,6 +65,7 @@ PA_MODULE_USAGE("path=<device object path>");<br>
#define BITPOOL_DEC_LIMIT 32<br>
#define BITPOOL_DEC_STEP 5<br>
#define HSP_MAX_GAIN 15<br>
+#define A2DP_MAX_VOLUME 127<br>
<br>
static const char* const valid_modargs[] = {<br>
"path",<br>
@@ -104,6 +105,7 @@ struct userdata {<br>
pa_hook_slot *transport_state_changed_slot;<br>
pa_hook_slot *transport_speaker_gain_changed_slot;<br>
pa_hook_slot *transport_microphone_gain_changed_slot;<br>
+ pa_hook_slot *transport_a2dp_source_volume_changed_slot;<br>
<br>
pa_bluetooth_discovery *discovery;<br>
pa_bluetooth_device *device;<br>
@@ -2102,6 +2104,29 @@ static pa_hook_result_t transport_microphone_gain_changed_cb(pa_bluetooth_discov<br>
return PA_HOOK_OK;<br>
}<br>
<br>
+static pa_hook_result_t transport_a2dp_source_volume_changed_cb(pa_bluetooth_discovery *y, pa_bluetooth_transport *t, struct userdata *u) {<br>
+ pa_volume_t volume;<br>
+ pa_cvolume v;<br>
+<br>
+ pa_assert(t);<br>
+ pa_assert(u);<br>
+<br>
+ if (t != u->transport)<br>
+ return PA_HOOK_OK;<br>
+<br>
+ volume = (pa_volume_t) (t->source_volume * PA_VOLUME_NORM / A2DP_MAX_VOLUME);<br>
+<br>
+ /* increment volume by one to correct rounding errors */<br>
+ if (volume < PA_VOLUME_NORM)<br>
+ volume++;<br>
+<br>
+ pa_cvolume_set(&v, u->sample_spec.channels, volume);<br>
+ pa_source_set_volume(u->source, &v, true, true);<br>
+ pa_source_volume_changed(u->source, &v);<br>
+<br>
+ return PA_HOOK_OK;<br>
+}<br>
+<br>
/* Run from main thread context */<br>
static int device_process_msg(pa_msgobject *obj, int code, void *data, int64_t offset, pa_memchunk *chunk) {<br>
struct bluetooth_msg *m = BLUETOOTH_MSG(obj);<br>
@@ -2172,6 +2197,8 @@ int pa__init(pa_module* m) {<br>
u->transport_microphone_gain_changed_slot =<br>
pa_hook_connect(pa_bluetooth_discovery_hook(u->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_MICROPHONE_GAIN_CHANGED), PA_HOOK_NORMAL, (pa_hook_cb_t) transport_microphone_gain_changed_cb, u);<br>
<br>
+ u->transport_a2dp_source_volume_changed_slot =<br>
+ pa_hook_connect(pa_bluetooth_discovery_hook(u->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_A2DP_SOURCE_VOLUME_CHANGED), PA_HOOK_NORMAL, (pa_hook_cb_t) transport_a2dp_source_volume_changed_cb, u);<br>
<br>
if (add_card(u) < 0)<br>
goto fail;<br>
@@ -2231,6 +2258,9 @@ void pa__done(pa_module *m) {<br>
if (u->transport_microphone_gain_changed_slot)<br>
pa_hook_slot_free(u->transport_microphone_gain_changed_slot);<br>
<br>
+ if (u->transport_a2dp_source_volume_changed_slot)<br>
+ pa_hook_slot_free(u->transport_a2dp_source_volume_changed_slot);<br>
+<br>
if (u->sbc_info.buffer)<br>
pa_xfree(u->sbc_info.buffer);<br>
<br>
--<br>
2.1.4<br>
<br>
</blockquote></div></div></div>