bluez5: fix device set profile/route enumerations

Now that we have ASHA & BAP, this->device_set now refers to the device
set of the active profile.  It cannot be used to produce
EnumProfile/EnumRoute.

Fix this by computing the device set for given profile(s) as needed.
This commit is contained in:
Pauli Virtanen 2025-05-15 19:42:56 +03:00 committed by Wim Taymans
parent 01d1e29402
commit e375364c87

View file

@ -1135,12 +1135,48 @@ static void device_set_update_bap(struct impl *this, struct device_set *dset)
dset->source_enabled = dset->path && (dset->sources > 1); dset->source_enabled = dset->path && (dset->sources > 1);
} }
static void device_set_update(struct impl *this, struct device_set *dset) static void device_set_update(struct impl *this, struct device_set *dset, int profile)
{ {
if (this->profile == DEVICE_PROFILE_BAP) if (profile == DEVICE_PROFILE_BAP)
device_set_update_bap(this, dset); device_set_update_bap(this, dset);
else if (this->profile == DEVICE_PROFILE_ASHA) else if (profile == DEVICE_PROFILE_ASHA)
device_set_update_asha(this, dset); device_set_update_asha(this, dset);
else
device_set_clear(this, dset);
}
static void device_set_get_dset_info(const struct device_set *dset,
int *n_set_sink, int *n_set_source)
{
if (dset->sink_enabled)
*n_set_sink = dset->leader ? 1 : 0;
if (dset->source_enabled)
*n_set_source = dset->leader ? 1 : 0;
}
static void device_set_get_info(struct impl *this, uint32_t profile,
int *n_set_sink, int *n_set_source)
{
struct device_set dset = { .impl = this };
*n_set_sink = -1;
*n_set_source = -1;
if (profile == this->profile) {
device_set_get_dset_info(&this->device_set, n_set_sink, n_set_source);
} else if (profile != SPA_ID_INVALID) {
device_set_update(this, &dset, profile);
device_set_get_dset_info(&dset, n_set_sink, n_set_source);
device_set_clear(this, &dset);
} else {
device_set_update(this, &dset, DEVICE_PROFILE_BAP);
device_set_get_dset_info(&dset, n_set_sink, n_set_source);
device_set_clear(this, &dset);
device_set_update(this, &dset, DEVICE_PROFILE_ASHA);
device_set_get_dset_info(&dset, n_set_sink, n_set_source);
device_set_clear(this, &dset);
}
} }
static bool device_set_equal(struct device_set *a, struct device_set *b) static bool device_set_equal(struct device_set *a, struct device_set *b)
@ -1166,7 +1202,7 @@ static int emit_nodes(struct impl *this)
this->props.codec = 0; this->props.codec = 0;
device_set_update(this, &this->device_set); device_set_update(this, &this->device_set, this->profile);
switch (this->profile) { switch (this->profile) {
case DEVICE_PROFILE_OFF: case DEVICE_PROFILE_OFF:
@ -1485,7 +1521,7 @@ static bool device_set_needs_update(struct impl *this)
this->profile != DEVICE_PROFILE_ASHA) this->profile != DEVICE_PROFILE_ASHA)
return false; return false;
device_set_update(this, &dset); device_set_update(this, &dset, this->profile);
changed = !device_set_equal(&dset, &this->device_set); changed = !device_set_equal(&dset, &this->device_set);
device_set_clear(this, &dset); device_set_clear(this, &dset);
return changed; return changed;
@ -1910,6 +1946,7 @@ static struct spa_pod *build_profile(struct impl *this, struct spa_pod_builder *
case DEVICE_PROFILE_ASHA: case DEVICE_PROFILE_ASHA:
{ {
uint32_t profile = device->connected_profiles & SPA_BT_PROFILE_ASHA_SINK; uint32_t profile = device->connected_profiles & SPA_BT_PROFILE_ASHA_SINK;
int n_set_sink, n_set_source;
if (codec == 0) if (codec == 0)
return NULL; return NULL;
@ -1925,9 +1962,9 @@ static struct spa_pod *build_profile(struct impl *this, struct spa_pod_builder *
n_sink++; n_sink++;
priority = 1; priority = 1;
if (this->device_set.sink_enabled) device_set_get_info(this, DEVICE_PROFILE_ASHA, &n_set_sink, &n_set_source);
n_sink = this->device_set.leader ? 1 : 0; if (n_set_sink >= 0)
n_sink = n_set_sink;
break; break;
} }
case DEVICE_PROFILE_A2DP: case DEVICE_PROFILE_A2DP:
@ -1990,6 +2027,7 @@ static struct spa_pod *build_profile(struct impl *this, struct spa_pod_builder *
| SPA_BT_PROFILE_BAP_BROADCAST_SINK); | SPA_BT_PROFILE_BAP_BROADCAST_SINK);
size_t idx; size_t idx;
const struct media_codec *media_codec; const struct media_codec *media_codec;
int n_set_sink, n_set_source;
/* BAP will only enlist codec profiles */ /* BAP will only enlist codec profiles */
if (codec == 0) if (codec == 0)
@ -2056,10 +2094,11 @@ static struct spa_pod *build_profile(struct impl *this, struct spa_pod_builder *
priority = 128; priority = 128;
} }
if (this->device_set.sink_enabled) device_set_get_info(this, DEVICE_PROFILE_BAP, &n_set_sink, &n_set_source);
n_sink = this->device_set.leader ? 1 : 0; if (n_set_sink >= 0)
if (this->device_set.source_enabled) n_sink = n_set_sink;
n_source = this->device_set.leader ? 1 : 0; if (n_set_source >= 0)
n_source = n_set_source;
break; break;
} }
case DEVICE_PROFILE_HSP_HFP: case DEVICE_PROFILE_HSP_HFP:
@ -2227,6 +2266,7 @@ static struct spa_pod *build_route(struct impl *this, struct spa_pod_builder *b,
char name[128]; char name[128];
uint32_t i, j, mask, next; uint32_t i, j, mask, next;
uint32_t dev; uint32_t dev;
int n_set_sink, n_set_source;
ff = spa_bt_form_factor_from_class(device->bluetooth_class); ff = spa_bt_form_factor_from_class(device->bluetooth_class);
@ -2294,12 +2334,14 @@ static struct spa_pod *build_route(struct impl *this, struct spa_pod_builder *b,
break; break;
} }
device_set_get_info(this, profile, &n_set_sink, &n_set_source);
switch (route) { switch (route) {
case ROUTE_INPUT: case ROUTE_INPUT:
direction = SPA_DIRECTION_INPUT; direction = SPA_DIRECTION_INPUT;
snprintf(name, sizeof(name), "%s-input", name_prefix); snprintf(name, sizeof(name), "%s-input", name_prefix);
dev = DEVICE_ID_SOURCE; dev = DEVICE_ID_SOURCE;
available = this->device_set.source_enabled ? available = (n_set_source >= 0) ?
SPA_PARAM_AVAILABILITY_no : SPA_PARAM_AVAILABILITY_yes; SPA_PARAM_AVAILABILITY_no : SPA_PARAM_AVAILABILITY_yes;
if ((this->bt_dev->connected_profiles & SPA_BT_PROFILE_A2DP_SINK) && if ((this->bt_dev->connected_profiles & SPA_BT_PROFILE_A2DP_SINK) &&
@ -2312,7 +2354,7 @@ static struct spa_pod *build_route(struct impl *this, struct spa_pod_builder *b,
direction = SPA_DIRECTION_OUTPUT; direction = SPA_DIRECTION_OUTPUT;
snprintf(name, sizeof(name), "%s-output", name_prefix); snprintf(name, sizeof(name), "%s-output", name_prefix);
dev = DEVICE_ID_SINK; dev = DEVICE_ID_SINK;
available = this->device_set.sink_enabled ? available = (n_set_sink >= 0) ?
SPA_PARAM_AVAILABILITY_no : SPA_PARAM_AVAILABILITY_yes; SPA_PARAM_AVAILABILITY_no : SPA_PARAM_AVAILABILITY_yes;
if (device_has_route(this, ROUTE_HF_OUTPUT)) { if (device_has_route(this, ROUTE_HF_OUTPUT)) {
@ -2339,7 +2381,7 @@ static struct spa_pod *build_route(struct impl *this, struct spa_pod_builder *b,
port_icon_name = spa_bt_form_factor_icon_name(SPA_BT_FORM_FACTOR_HEADSET); port_icon_name = spa_bt_form_factor_icon_name(SPA_BT_FORM_FACTOR_HEADSET);
break; break;
case ROUTE_SET_INPUT: case ROUTE_SET_INPUT:
if (!(this->device_set.source_enabled && this->device_set.leader)) if (n_set_source < 1)
return NULL; return NULL;
direction = SPA_DIRECTION_INPUT; direction = SPA_DIRECTION_INPUT;
snprintf(name, sizeof(name), "%s-set-input", name_prefix); snprintf(name, sizeof(name), "%s-set-input", name_prefix);
@ -2347,7 +2389,7 @@ static struct spa_pod *build_route(struct impl *this, struct spa_pod_builder *b,
available = SPA_PARAM_AVAILABILITY_yes; available = SPA_PARAM_AVAILABILITY_yes;
break; break;
case ROUTE_SET_OUTPUT: case ROUTE_SET_OUTPUT:
if (!(this->device_set.sink_enabled && this->device_set.leader)) if (n_set_sink < 1)
return NULL; return NULL;
direction = SPA_DIRECTION_OUTPUT; direction = SPA_DIRECTION_OUTPUT;
snprintf(name, sizeof(name), "%s-set-output", name_prefix); snprintf(name, sizeof(name), "%s-set-output", name_prefix);