bluez5: cleanup bluez5.bcast_source.config parsing

Also fix doc.
This commit is contained in:
Pauli Virtanen 2024-05-10 20:15:18 +03:00 committed by Wim Taymans
parent 44d96ed4b9
commit 345131475c
3 changed files with 106 additions and 107 deletions

View file

@ -425,26 +425,23 @@ PipeWire Opus Pro audio profile duplex frame duration (1/10 ms).
@PAR@ device-param bluez5.bcast_source.config # JSON @PAR@ device-param bluez5.bcast_source.config # JSON
\parblock \parblock
example JSON Example:
{ ```
"broadcast_code": [ // broadcast code bluez5.bcast_source.config = [
1, 2, 104, 5, 83, 241, 65, 90, 162, 101, 187, 175, 198, 234, 3, 184 {
], "broadcast_code": [ 1, 2, 104, 5, 83, 241, 65, 90, 162, 101, 187, 175, 198, 234, 3, 184 ],
"bis": [ "bis": [
{ // BIS configuration { # BIS configuration
"qos_preset": "16_2_1", // QOS preset name from table Table 6.4 from BAP_v1.0.1. "qos_preset": "16_2_1", # QOS preset name from table Table 6.4 from BAP_v1.0.1.
"audio_channel_allocation": 1, // audio channel allocation configuration for the BIS "audio_channel_allocation": 1, # audio channel allocation configuration for the BIS
"metadata": [ // metadata configurations for the BIS "metadata": [ # metadata configurations for the BIS
{ { "type": 1, "value": [ 1, 1 ] }
"type": 1, ]
"value": [ }
1, 1
]
}
]
}
] ]
} }
]
```
\endparblock \endparblock
## Device properties ## Device properties

View file

@ -1174,7 +1174,7 @@ static int codec_get_bis_config(const struct media_codec *codec, uint8_t *caps,
return -EINVAL; return -EINVAL;
SPA_FOR_EACH_ELEMENT_VAR(bap_bcast_qos_configs, c) { SPA_FOR_EACH_ELEMENT_VAR(bap_bcast_qos_configs, c) {
if (strcmp(c->name, preset) == 0) { if (spa_streq(c->name, preset)) {
preset_found = true; preset_found = true;
break; break;
} }

View file

@ -6078,121 +6078,123 @@ static void parse_broadcast_source_config(struct spa_bt_monitor *monitor, const
int cursor; int cursor;
int big_id = 0; int big_id = 0;
struct spa_json it[4], it_array[4]; struct spa_json it[4], it_array[4];
struct spa_bt_big *big_entry = NULL;
struct spa_bt_bis *bis_entry = NULL;
struct spa_bt_metadata *metadata_entry = NULL;
int temp_val = 0;
struct spa_list big_list = SPA_LIST_INIT(&big_list); struct spa_list big_list = SPA_LIST_INIT(&big_list);
struct spa_error_location loc;
struct spa_bt_big *big;
/* Search for bluez5.bcast_source.config */ /* Search for bluez5.bcast_source.config */
if (info && (str = spa_dict_lookup(info, "bluez5.bcast_source.config"))) { if (!(info && (str = spa_dict_lookup(info, "bluez5.bcast_source.config"))))
spa_json_init(&it[0], str, strlen(str)); return;
/* Verify is an array of BIGS */
if (spa_json_enter_array(&it[0], &it_array[0]) <= 0)
goto parse_failed;
/* Iterate on all BIG objects */ spa_json_init(&it[0], str, strlen(str));
while (spa_json_enter_object(&it_array[0], &it[1]) > 0) {
big_entry = calloc(1, sizeof(struct spa_bt_big)); /* Verify is an array of BIGS */
spa_list_init(&big_entry->bis_list); if (spa_json_enter_array(&it[0], &it_array[0]) <= 0)
spa_list_append(&big_list, &big_entry->link); goto parse_failed;
/* Iterate on all BIG values */
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) { /* Iterate on all BIG objects */
if (spa_streq(key, "broadcast_code")) { while (spa_json_enter_object(&it_array[0], &it[1]) > 0) {
if (spa_json_enter_array(&it[1], &it_array[1]) <= 0) struct spa_bt_big *big_entry = calloc(1, sizeof(struct spa_bt_big));
if (!big_entry)
goto errno_failed;
big_entry->big_id = big_id++;
spa_list_init(&big_entry->bis_list);
spa_list_append(&big_list, &big_entry->link);
/* Iterate on all BIG values */
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) {
if (spa_streq(key, "broadcast_code")) {
if (spa_json_enter_array(&it[1], &it_array[1]) <= 0)
goto parse_failed;
for (cursor = 0; cursor < BROADCAST_CODE_LEN; cursor++) {
if (spa_json_get_int(&it_array[1], &big_entry->broadcast_code[cursor]) <= 0)
goto parse_failed; goto parse_failed;
for (cursor = 0; cursor < BROADCAST_CODE_LEN; cursor++) { spa_log_debug(monitor->log, "big_entry->broadcast_code[%d] %d", cursor, big_entry->broadcast_code[cursor]);
if (spa_json_get_int(&it_array[1], &big_entry->broadcast_code[cursor]) <= 0) }
goto parse_failed; } else if (spa_streq(key, "bis")) {
spa_log_debug(monitor->log, "big_entry->broadcast_code %d", big_entry->broadcast_code[cursor]); if (spa_json_enter_array(&it[1], &it_array[1]) <= 0)
} goto parse_failed;
} else if (spa_streq(key, "bis")) { while (spa_json_enter_object(&it_array[1], &it[2]) > 0) {
if (spa_json_enter_array(&it[1], &it_array[1]) <= 0) /* Iterate on all BIS values */
goto parse_failed; struct spa_bt_bis *bis_entry = calloc(1, sizeof(struct spa_bt_bis));
while (spa_json_enter_object(&it_array[1], &it[2]) > 0) {
/* Iterate on all BIS values */ if (!bis_entry)
bis_entry = calloc(1, sizeof(struct spa_bt_bis)); goto errno_failed;
spa_list_init(&bis_entry->metadata_list);
while (spa_json_get_string(&it[2], bis_key, sizeof(bis_key)) > 0) { spa_list_init(&bis_entry->metadata_list);
if (spa_streq(bis_key, "qos_preset")) { spa_list_append(&big_entry->bis_list, &bis_entry->link);
spa_json_get_string(&it[2], bis_entry->qos_preset, sizeof(bis_entry->qos_preset));
spa_log_debug(monitor->log, "bis_entry->qos_preset %s", bis_entry->qos_preset); while (spa_json_get_string(&it[2], bis_key, sizeof(bis_key)) > 0) {
} else if (spa_streq(bis_key, "audio_channel_allocation")) { if (spa_streq(bis_key, "qos_preset")) {
if (spa_json_get_int(&it[2], &bis_entry->channel_allocation) <= 0) if (spa_json_get_string(&it[2], bis_entry->qos_preset, sizeof(bis_entry->qos_preset)) <= 0)
goto parse_failed;
spa_log_debug(monitor->log, "bis_entry->qos_preset %s", bis_entry->qos_preset);
} else if (spa_streq(bis_key, "audio_channel_allocation")) {
if (spa_json_get_int(&it[2], &bis_entry->channel_allocation) <= 0)
goto parse_failed;
spa_log_debug(monitor->log, "bis_entry->channel_allocation %d", bis_entry->channel_allocation);
} else if (spa_streq(bis_key, "metadata")) {
if (spa_json_enter_array(&it[2], &it_array[2]) <= 0)
goto parse_failed;
while (spa_json_enter_object(&it_array[2], &it[3]) > 0) {
struct spa_bt_metadata *metadata_entry = calloc(1, sizeof(struct spa_bt_metadata));
if (!metadata_entry)
goto errno_failed;
spa_list_append(&bis_entry->metadata_list, &metadata_entry->link);
while (spa_json_get_string(&it[3], qos_key, sizeof(qos_key)) > 0) {
if (spa_streq(qos_key, "type")) {
if (spa_json_get_int(&it[3], &metadata_entry->type) <= 0)
goto parse_failed; goto parse_failed;
spa_log_debug(monitor->log, "bis_entry->channel_allocation %d", bis_entry->channel_allocation); spa_log_debug(monitor->log, "metadata_entry->type %d", metadata_entry->type);
} else if (spa_streq(bis_key, "metadata")) { } else if (spa_streq(qos_key, "value")) {
if (spa_json_enter_array(&it[2], &it_array[2]) <= 0) if (spa_json_enter_array(&it[3], &it_array[3]) <= 0)
goto parse_failed; goto parse_failed;
while (spa_json_enter_object(&it_array[2], &it[3]) > 0) { for (cursor = 0; cursor < METADATA_MAX_LEN; cursor++) {
metadata_entry = calloc(1, sizeof(struct spa_bt_metadata)); int temp_val = 0;
while (spa_json_get_string(&it[3], qos_key, sizeof(qos_key)) > 0) { if (spa_json_get_int(&it_array[3], &temp_val) <= 0)
if (spa_streq(qos_key, "type")) { break;
if (spa_json_get_int(&it[3], &metadata_entry->type) <= 0) metadata_entry->value[cursor] = (uint8_t)temp_val;
goto parse_failed; spa_log_debug(monitor->log, "metadata_entry->value[%d] %d", cursor, metadata_entry->value[cursor]);
spa_log_debug(monitor->log, "metadata_entry->type %d", metadata_entry->type);
} else if (spa_streq(qos_key, "value")) {
if (spa_json_enter_array(&it[3], &it_array[3]) <= 0)
goto parse_failed;
for (cursor = 0; cursor < METADATA_MAX_LEN; cursor++) {
if (spa_json_get_int(&it_array[3], &temp_val) <= 0)
break;
metadata_entry->value[cursor] = (uint8_t)temp_val;
spa_log_debug(monitor->log, "metadata_entry->value[cursor] %d", metadata_entry->value[cursor]);
}
/* length is size of value plus 1 octet for type */
metadata_entry->length = cursor + 1;
spa_log_debug(monitor->log, "metadata_entry->length %d", metadata_entry->length);
spa_log_debug(monitor->log, "metadata_entry->value_size %d", cursor);
spa_list_append(&bis_entry->metadata_list, &metadata_entry->link);
metadata_entry = NULL;
} }
/* length is size of value plus 1 octet for type */
metadata_entry->length = cursor + 1;
spa_log_debug(monitor->log, "metadata_entry->length %d", metadata_entry->length);
spa_log_debug(monitor->log, "metadata_entry->value_size %d", cursor);
} }
} }
} }
} }
spa_list_append(&big_entry->bis_list, &bis_entry->link);
bis_entry = NULL;
} }
} }
} }
big_entry->big_id = big_id;
big_id ++;
big_entry = NULL;
} }
} }
spa_list_insert_list(&monitor->bcast_source_config_list, &big_list); spa_list_insert_list(&monitor->bcast_source_config_list, &big_list);
return; return;
parse_failed: errno_failed:
struct spa_error_location loc; spa_log_warn(monitor->log, "failed in bluez5.bcast_source.config: %m");
goto cleanup;
parse_failed:
str = spa_dict_lookup(info, "bluez5.bcast_source.config"); str = spa_dict_lookup(info, "bluez5.bcast_source.config");
if (spa_json_get_error(&it[0], str, &loc)) { if (spa_json_get_error(&it[0], str, &loc)) {
spa_debug_log_error_location(monitor->log, SPA_LOG_LEVEL_WARN, spa_debug_log_error_location(monitor->log, SPA_LOG_LEVEL_WARN,
&loc, "malformed bluez5.bcast_source.config: %s", loc.reason); &loc, "malformed bluez5.bcast_source.config: %s", loc.reason);
} else {
spa_log_warn(monitor->log, "malformed bluez5.bcast_source.config");
} }
goto cleanup;
if (metadata_entry) cleanup:
free(metadata_entry); spa_list_consume(big, &big_list, link)
big_entry_free(big);
if (bis_entry) {
spa_list_consume(metadata_entry, &bis_entry->metadata_list, link)
free(metadata_entry);
free(bis_entry);
}
if (big_entry) {
spa_list_consume(bis_entry, &big_entry->bis_list, link)
bis_entry_free(bis_entry);
free(big_entry);
}
spa_list_consume(big_entry, &big_list, link)
big_entry_free(big_entry);
} }
static int parse_codec_array(struct spa_bt_monitor *this, const struct spa_dict *info) static int parse_codec_array(struct spa_bt_monitor *this, const struct spa_dict *info)