client/player: Add support to enter alternative preset

This adds support for alternative preset to be entered so when auto
accepting configuration a different preset can be selected following the
order given to endpoint.presets.
This commit is contained in:
Luiz Augusto von Dentz 2024-07-19 15:52:29 -04:00
parent 4c9d4ed059
commit c2312ebe31

View File

@ -1230,7 +1230,10 @@ struct codec_preset {
const struct iovec data;
struct bt_bap_qos qos;
uint8_t target_latency;
uint32_t chan_alloc;
bool custom;
bool alt;
struct codec_preset *alt_preset;
};
#define SBC_PRESET(_name, _data) \
@ -1969,12 +1972,31 @@ static int parse_chan_alloc(DBusMessageIter *iter, uint32_t *location,
if (*channels)
*channels = __builtin_popcount(*location);
return 0;
} else if (!strcasecmp(key, "Locations")) {
uint32_t tmp;
if (var != DBUS_TYPE_UINT32)
return -EINVAL;
dbus_message_iter_get_basic(&value, &tmp);
*location &= tmp;
if (*channels)
*channels = __builtin_popcount(*location);
}
dbus_message_iter_next(iter);
}
return -EINVAL;
return *location ? 0 : -EINVAL;
}
static void ltv_find(size_t i, uint8_t l, uint8_t t, uint8_t *v,
void *user_data)
{
bool *found = user_data;
*found = true;
}
static DBusMessage *endpoint_select_properties_reply(struct endpoint *ep,
@ -1985,7 +2007,7 @@ static DBusMessage *endpoint_select_properties_reply(struct endpoint *ep,
DBusMessageIter iter, props;
struct endpoint_config *cfg;
struct bt_bap_io_qos *qos;
uint32_t location = 0;
uint32_t location = ep->locations;
uint8_t channels = 1;
if (!preset)
@ -2006,14 +2028,45 @@ static DBusMessage *endpoint_select_properties_reply(struct endpoint *ep,
dbus_message_iter_recurse(&iter, &props);
if (!parse_chan_alloc(&props, &location, &channels)) {
uint32_t chan_alloc = 0;
uint8_t type = LC3_CONFIG_CHAN_ALLOC;
bool found = false;
if (preset->chan_alloc & location)
chan_alloc = preset->chan_alloc & location;
else if (preset->alt_preset &&
preset->alt_preset->chan_alloc &
location) {
chan_alloc = preset->alt_preset->chan_alloc & location;
preset = preset->alt_preset;
/* Copy alternate capabilities */
util_iov_free(cfg->caps, 1);
cfg->caps = util_iov_dup(&preset->data, 1);
cfg->target_latency = preset->target_latency;
} else
chan_alloc = location;
/* Check if Channel Allocation is present in caps */
util_ltv_foreach(cfg->caps->iov_base, cfg->caps->iov_len,
&type, ltv_find, &found);
/* If Channel Allocation has not been set directly via
* preset->data then attempt to set it if chan_alloc has been
* set.
*/
if (!found && chan_alloc) {
uint8_t chan_alloc_ltv[] = {
0x05, LC3_CONFIG_CHAN_ALLOC, location & 0xff,
location >> 8, location >> 16, location >> 24
0x05, LC3_CONFIG_CHAN_ALLOC, chan_alloc & 0xff,
chan_alloc >> 8, chan_alloc >> 16,
chan_alloc >> 24
};
put_le32(chan_alloc, &chan_alloc_ltv[2]);
util_iov_append(cfg->caps, &chan_alloc_ltv,
sizeof(chan_alloc_ltv));
}
}
/* Copy metadata */
cfg->meta = util_iov_dup(ep->meta, 1);
@ -2035,6 +2088,8 @@ static DBusMessage *endpoint_select_properties_reply(struct endpoint *ep,
dbus_message_iter_init_append(reply, &iter);
bt_shell_printf("selecting %s...\n", preset->name);
append_properties(&iter, cfg);
free(cfg);
@ -2098,8 +2153,6 @@ static DBusMessage *endpoint_select_properties(DBusConnection *conn,
if (!reply)
return NULL;
bt_shell_printf("Auto Accepting using %s...\n", p->name);
return reply;
}
@ -3621,14 +3674,6 @@ add_meta:
endpoint_set_metadata_cfg, cfg);
}
static void ltv_find(size_t i, uint8_t l, uint8_t t, uint8_t *v,
void *user_data)
{
bool *found = user_data;
*found = true;
}
static void config_endpoint_iso_group(const char *input, void *user_data)
{
struct endpoint_config *cfg = user_data;
@ -4106,13 +4151,38 @@ static void print_presets(struct preset *preset)
for (i = 0; i < preset->num_presets; i++) {
p = &preset->presets[i];
bt_shell_printf("%s%s\n", p == preset->default_preset ?
"*" : "", p->name);
if (p == preset->default_preset)
bt_shell_printf("*%s\n", p->name);
else if (preset->default_preset &&
p == preset->default_preset->alt_preset)
bt_shell_printf("**%s\n", p->name);
else
bt_shell_printf("%s\n", p->name);
}
queue_foreach(preset->custom, foreach_custom_preset_print, preset);
}
static void custom_chan_alloc(const char *input, void *user_data)
{
struct codec_preset *p = user_data;
char *endptr = NULL;
p->chan_alloc = strtol(input, &endptr, 0);
if (!endptr || *endptr != '\0') {
bt_shell_printf("Invalid argument: %s\n", input);
return bt_shell_noninteractive_quit(EXIT_FAILURE);
}
if (p->alt_preset)
bt_shell_prompt_input(p->alt_preset->name,
"Enter Channel Allocation: ",
custom_chan_alloc, p->alt_preset);
else
return bt_shell_noninteractive_quit(EXIT_SUCCESS);
}
static void cmd_presets_endpoint(int argc, char *argv[])
{
struct preset *preset;
@ -4133,8 +4203,20 @@ static void cmd_presets_endpoint(int argc, char *argv[])
preset->default_preset = default_preset;
if (argc > 4) {
struct codec_preset *alt_preset;
struct iovec *iov = (void *)&default_preset->data;
/* Check if and alternative preset was given */
alt_preset = preset_find_name(preset, argv[4]);
if (alt_preset) {
default_preset->alt_preset = alt_preset;
bt_shell_prompt_input(default_preset->name,
"Enter Channel Allocation: ",
custom_chan_alloc,
default_preset);
return;
}
iov->iov_base = str2bytearray(argv[4], &iov->iov_len);
if (!iov->iov_base) {
bt_shell_printf("Invalid configuration %s\n",