From 2ff659f882ba88825fd3a47c048725ea5989149b Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Wed, 20 Jan 2021 00:29:16 +0100 Subject: [PATCH] bluetooth: Keep track of the first codec to use in every endpoint --- src/modules/bluetooth/a2dp-codec-api.h | 3 +++ src/modules/bluetooth/a2dp-codec-util.c | 17 +++++++++++++++ src/modules/bluetooth/a2dp-codec-util.h | 3 +++ src/modules/bluetooth/bluez5-util.c | 6 ++++- src/modules/bluetooth/module-bluez5-device.c | 23 +++++--------------- 5 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/modules/bluetooth/a2dp-codec-api.h b/src/modules/bluetooth/a2dp-codec-api.h index a90664e17..ccf5466aa 100644 --- a/src/modules/bluetooth/a2dp-codec-api.h +++ b/src/modules/bluetooth/a2dp-codec-api.h @@ -25,7 +25,10 @@ #define MAX_A2DP_CAPS_SIZE 254 #define DEFAULT_OUTPUT_RATE_REFRESH_INTERVAL_MS 500 +typedef struct pa_a2dp_codec pa_a2dp_codec; + typedef struct pa_a2dp_codec_capabilities { + const pa_a2dp_codec *first_codec; /* First codec to use */ uint8_t size; uint8_t buffer[]; /* max size is 254 bytes */ } pa_a2dp_codec_capabilities; diff --git a/src/modules/bluetooth/a2dp-codec-util.c b/src/modules/bluetooth/a2dp-codec-util.c index 873c270cb..614ebaa7f 100644 --- a/src/modules/bluetooth/a2dp-codec-util.c +++ b/src/modules/bluetooth/a2dp-codec-util.c @@ -109,3 +109,20 @@ bool pa_bluetooth_a2dp_codec_is_available(const pa_a2dp_codec_id *id, bool is_a2 return false; } + +const pa_a2dp_codec *pa_bluetooth_a2dp_codec_find_with_capabilities(const pa_a2dp_codec_id *id, const uint8_t *capabilities, int capabilities_size, bool for_encoding) { + for (unsigned i = 0; i < pa_bluetooth_a2dp_codec_count(); ++i) { + const pa_a2dp_codec *a2dp_codec = pa_bluetooth_a2dp_codec_iter(i); + + if (!memcmp(id, &a2dp_codec->id, sizeof(pa_a2dp_codec_id)) == 0) + continue; + + if (!a2dp_codec->can_be_supported(for_encoding)) + continue; + + if (a2dp_codec->can_accept_capabilities(capabilities, capabilities_size, for_encoding)) + return a2dp_codec; + } + + return NULL; +} diff --git a/src/modules/bluetooth/a2dp-codec-util.h b/src/modules/bluetooth/a2dp-codec-util.h index 7b8d0cc87..e1e7c35c9 100644 --- a/src/modules/bluetooth/a2dp-codec-util.h +++ b/src/modules/bluetooth/a2dp-codec-util.h @@ -34,6 +34,9 @@ const pa_a2dp_codec *pa_bluetooth_get_a2dp_codec(const char *name); /* Check if the given codec can be supported in A2DP_SINK or A2DP_SOURCE */ bool pa_bluetooth_a2dp_codec_is_available(const pa_a2dp_codec_id *id, bool is_a2dp_sink); +/* Check if the given codec and capability pair can be supported in A2DP_SINK or A2DP_SOURCE */ +const pa_a2dp_codec *pa_bluetooth_a2dp_codec_find_with_capabilities(const pa_a2dp_codec_id *id, const uint8_t *capabilities, int capabilities_size, bool for_encoding); + /* Initialise GStreamer */ void pa_bluetooth_a2dp_codec_gst_init(void); diff --git a/src/modules/bluetooth/bluez5-util.c b/src/modules/bluetooth/bluez5-util.c index b1df0a977..b1d400db6 100644 --- a/src/modules/bluetooth/bluez5-util.c +++ b/src/modules/bluetooth/bluez5-util.c @@ -1357,12 +1357,16 @@ static void parse_remote_endpoint_properties(pa_bluetooth_discovery *y, const ch a2dp_codec_id->vendor_codec_id = 0; } - if (!pa_bluetooth_a2dp_codec_is_available(a2dp_codec_id, pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SINK))) { + const pa_a2dp_codec *codec = pa_bluetooth_a2dp_codec_find_with_capabilities(a2dp_codec_id, capabilities, capabilities_size, pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SINK)); + + if (!codec) { + // TODO: We should pretty-print `a2dp_codec_id` here! pa_xfree(a2dp_codec_id); return; } a2dp_codec_capabilities = pa_xmalloc0(sizeof(*a2dp_codec_capabilities) + capabilities_size); + a2dp_codec_capabilities->first_codec = codec; a2dp_codec_capabilities->size = capabilities_size; memcpy(a2dp_codec_capabilities->buffer, capabilities, capabilities_size); diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c index 041a23977..a06ad257a 100644 --- a/src/modules/bluetooth/module-bluez5-device.c +++ b/src/modules/bluetooth/module-bluez5-device.c @@ -2460,7 +2460,6 @@ static char *list_codecs(struct userdata *u) { pa_hashmap *a2dp_endpoints; pa_hashmap *a2dp_capabilities; pa_json_encoder *encoder; - unsigned int i; bool is_a2dp_sink; void *state, *state2; @@ -2473,25 +2472,15 @@ static char *list_codecs(struct userdata *u) { pa_json_encoder_begin_element_array(encoder); PA_HASHMAP_FOREACH_KV(key, a2dp_capabilities, a2dp_endpoints, state) { - for (i = 0; i < pa_bluetooth_a2dp_codec_count(); i++) { - const pa_a2dp_codec *a2dp_codec; + PA_HASHMAP_FOREACH(a2dp_capability, a2dp_capabilities, state2) { + const pa_a2dp_codec *a2dp_codec = a2dp_capability->first_codec; - a2dp_codec = pa_bluetooth_a2dp_codec_iter(i); + pa_json_encoder_begin_element_object(encoder); - if (memcmp(key, &a2dp_codec->id, sizeof(pa_a2dp_codec_id)) == 0) { - PA_HASHMAP_FOREACH(a2dp_capability, a2dp_capabilities, state2) { - if (a2dp_codec->can_accept_capabilities(a2dp_capability->buffer, a2dp_capability->size, /* For encoding */ is_a2dp_sink)) { - pa_json_encoder_begin_element_object(encoder); + pa_json_encoder_add_member_string(encoder, "name", a2dp_codec->name); + pa_json_encoder_add_member_string(encoder, "description", a2dp_codec->description); - pa_json_encoder_add_member_string(encoder, "name", a2dp_codec->name); - pa_json_encoder_add_member_string(encoder, "description", a2dp_codec->description); - - pa_json_encoder_end_object(encoder); - - break; - } - } - } + pa_json_encoder_end_object(encoder); } }