bluez5: select BAP audio locations in SelectProperties

Do BAP audio location selection properly in SelectProperties, now that
BlueZ provides the supported locations there. Remove a previous
workaround.

The audio location in SelectProperties determines the audio channel
allocation, which determines the channel positions.
This commit is contained in:
Pauli Virtanen 2023-04-22 19:32:59 +03:00
parent 815501cc1f
commit 420f7cb48e
3 changed files with 97 additions and 117 deletions

View file

@ -39,8 +39,6 @@
#include "iso-io.h"
#include "defs.h"
#include "bap-codec-caps.h"
static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.bluez5");
#undef SPA_LOG_TOPIC_DEFAULT
#define SPA_LOG_TOPIC_DEFAULT &log_topic
@ -632,10 +630,14 @@ static DBusHandlerResult endpoint_select_properties(DBusConnection *conn, DBusMe
const struct media_codec *codec;
bool sink;
const char *err_msg = "Unknown error";
struct spa_dict settings;
struct spa_dict_item setting_items[SPA_N_ELEMENTS(monitor->global_setting_items) + 1];
int i;
const char *endpoint_path = NULL;
uint8_t caps[A2DP_MAX_CAPS_SIZE];
uint8_t config[A2DP_MAX_CAPS_SIZE];
char locations[64] = {0};
int caps_size = 0;
int conf_size;
DBusMessageIter dict;
@ -751,6 +753,8 @@ static DBusHandlerResult endpoint_select_properties(DBusConnection *conn, DBusMe
endpoint_qos.preferred_delay_min = v;
else if (spa_streq(key, "PreferredMaximumDelay"))
endpoint_qos.preferred_delay_max = v;
else if (spa_streq(key, "Location"))
spa_scnprintf(locations, sizeof(locations), "%"PRIu32, v);
else
spa_log_info(monitor->log, "Unknown property %s", key);
} else {
@ -775,10 +779,12 @@ static DBusHandlerResult endpoint_select_properties(DBusConnection *conn, DBusMe
ep->acceptor = true;
}
/* TODO: determine which device the SelectConfiguration() call is associated
* with; it's known here based on the remote endpoint.
*/
conf_size = codec->select_config(codec, 0, caps, caps_size, &monitor->default_audio_info, NULL, config);
for (i = 0; i < (int)monitor->global_settings.n_items; ++i)
setting_items[i] = monitor->global_settings.items[i];
setting_items[i] = SPA_DICT_ITEM_INIT("bluez5.bap.locations", locations);
settings = SPA_DICT_INIT(setting_items, monitor->global_settings.n_items + 1);
conf_size = codec->select_config(codec, 0, caps, caps_size, &monitor->default_audio_info, &settings, config);
if (conf_size < 0) {
spa_log_error(monitor->log, "can't select config: %d (%s)",
conf_size, spa_strerror(conf_size));
@ -3189,16 +3195,6 @@ static int transport_update_props(struct spa_bt_transport *transport,
else
transport->bap_cis = value;
}
else if (spa_streq(key, "Location")) {
uint32_t value;
if (type != DBUS_TYPE_UINT32)
goto next;
dbus_message_iter_get_basic(&it[1], &value);
spa_log_debug(monitor->log, "transport %p: %s=%d", transport, key, (int)value);
transport->bap_location = value;
}
next:
dbus_message_iter_next(props_iter);
}
@ -4187,64 +4183,6 @@ int spa_bt_device_supports_hfp_codec(struct spa_bt_device *device, unsigned int
return spa_bt_backend_supports_codec(monitor->backend, device, codec);
}
static void bap_update_codec_location(struct spa_bt_transport *t)
{
uint8_t *data = t->configuration;
size_t size = t->configuration_len;
struct ltv *ltv;
uint32_t location;
int i;
if (!t->bap_location)
return;
/*
* Append channel location from BAP transport location, if no channel
* configuration is present in the configuration.
*
* XXX: The codec select_configuration should set the location
* XXX: for mono channels from the device location. We have to do
* XXX: this here because transport location is not know
* XXX: in SelectProperties (TODO: should be fixed in bluez).
*/
while (size > 0) {
ltv = (struct ltv *)data;
if (ltv->len < sizeof(struct ltv) || ltv->len >= size)
return;
if (ltv->type == LC3_TYPE_CHAN)
return; /* already has the channel info */
size -= ltv->len + 1;
data += ltv->len + 1;
}
/* Pick the first location bit set */
location = t->bap_location;
for (i = 0; i < 32; ++i) {
if (location & (1 << i)) {
location = (1 << i);
break;
}
}
/* Append LTV value to transport configuration */
size = t->configuration_len + sizeof(struct ltv) + sizeof(uint32_t);
data = realloc(t->configuration, size);
if (!data)
return;
ltv = SPA_PTROFF(data, t->configuration_len, struct ltv);
ltv->len = 5;
ltv->type = LC3_TYPE_CHAN;
memcpy(ltv->value, &location, sizeof(uint32_t));
t->configuration = data;
t->configuration_len = size;
}
static DBusHandlerResult endpoint_set_configuration(DBusConnection *conn,
const char *path, DBusMessage *m, void *userdata)
{
@ -4329,9 +4267,6 @@ static DBusHandlerResult endpoint_set_configuration(DBusConnection *conn,
|= transport->device->a2dp_volume_active[SPA_BT_VOLUME_ID_TX];
}
if (codec->bap)
bap_update_codec_location(transport);
if (codec->validate_config) {
struct spa_audio_info info;
if (codec->validate_config(codec, sink ? MEDIA_CODEC_FLAG_SINK : 0,