bluetooth: Support A2DP codec switching via messaging API

This uses the messaging API to initiate a codec switch.

While a particular codec might be applicable only for a particular
profile, for eg. aptX can only be applicable for A2DP sink or source
and not for let's say HSP, the codec switching logic has not been
tied to the logic for switching profiles.

Codec can be switched by running the following on the command line.

pacmd send-message /card/bluez_card.XX_XX_XX_XX_XX_XX/bluez switch-codec{"ldac_hq"}
pacmd send-message /card/bluez_card.XX_XX_XX_XX_XX_XX/bluez switch-codec {"ldac_mq"}
pacmd send-message /card/bluez_card.XX_XX_XX_XX_XX_XX/bluez switch-codec {"ldac_sq"}
pacmd send-message /card/bluez_card.XX_XX_XX_XX_XX_XX/bluez switch-codec {"aptx_hd"}
pacmd send-message /card/bluez_card.XX_XX_XX_XX_XX_XX/bluez switch-codec {"aptx"}
pacmd send-message /card/bluez_card.XX_XX_XX_XX_XX_XX/bluez switch-codec {"sbc"}

Codec name passed above is matched against pa_a2dp_codec->name. Note that
the match is case sensitive. XX_XX_XX_XX_XX_XX needs to be substituted with
the actual bluetooth device id.

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/440>
This commit is contained in:
Sanchayan Maity 2020-12-18 17:05:44 +05:30
parent 5284b450e7
commit 3447335da9
4 changed files with 500 additions and 4 deletions

View file

@ -109,6 +109,7 @@ struct pa_bluetooth_device {
bool tried_to_link_with_adapter;
bool valid;
bool autodetect_mtu;
bool codec_switching_in_progress;
/* Device information */
char *path;
@ -117,6 +118,9 @@ struct pa_bluetooth_device {
char *address;
uint32_t class_of_device;
pa_hashmap *uuids; /* char* -> char* (hashmap-as-a-set) */
/* pa_a2dp_codec_id* -> pa_hashmap ( char* (remote endpoint) -> struct a2dp_codec_capabilities* ) */
pa_hashmap *a2dp_sink_endpoints;
pa_hashmap *a2dp_source_endpoints;
pa_bluetooth_transport *transports[PA_BLUETOOTH_PROFILE_COUNT];
@ -170,6 +174,7 @@ pa_bluetooth_device* pa_bluetooth_discovery_get_device_by_address(pa_bluetooth_d
pa_hook* pa_bluetooth_discovery_hook(pa_bluetooth_discovery *y, pa_bluetooth_hook_t hook);
const char *pa_bluetooth_profile_to_string(pa_bluetooth_profile_t profile);
bool pa_bluetooth_switch_codec(pa_bluetooth_device *device, pa_bluetooth_profile_t profile, pa_hashmap *capabilities_hashmap, const pa_a2dp_codec *a2dp_codec, void (*codec_switch_cb)(bool, pa_bluetooth_profile_t profile, void *), void *userdata);
static inline bool pa_bluetooth_uuid_is_hsp_hs(const char *uuid) {
return pa_streq(uuid, PA_BLUETOOTH_UUID_HSP_HS) || pa_streq(uuid, PA_BLUETOOTH_UUID_HSP_HS_ALT);