mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
bluez5: adjust codec profile priority ordering
Higher priority for A2DP over HFP/HSP. Prefer mSBC over CVSD for HFP, and put A2DP codecs in the order we tell BlueZ to use. Ensures that picking highest-priority profile gives sensible results (e.g. does not pick HFP unless input route is required, and prefers A2DP duplex codecs over HFP).
This commit is contained in:
parent
878e630527
commit
effa0ca124
1 changed files with 20 additions and 8 deletions
|
|
@ -183,13 +183,17 @@ static void get_a2dp_codecs(struct impl *this, enum spa_bluetooth_audio_codec id
|
||||||
*codecs = NULL;
|
*codecs = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct a2dp_codec *get_supported_a2dp_codec(struct impl *this, enum spa_bluetooth_audio_codec id)
|
static const struct a2dp_codec *get_supported_a2dp_codec(struct impl *this, enum spa_bluetooth_audio_codec id, size_t *idx)
|
||||||
{
|
{
|
||||||
const struct a2dp_codec *a2dp_codec = NULL;
|
const struct a2dp_codec *a2dp_codec = NULL;
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < this->supported_codec_count; ++i)
|
for (i = 0; i < this->supported_codec_count; ++i) {
|
||||||
if (this->supported_codecs[i]->id == id)
|
if (this->supported_codecs[i]->id == id) {
|
||||||
a2dp_codec = this->supported_codecs[i];
|
a2dp_codec = this->supported_codecs[i];
|
||||||
|
if (idx)
|
||||||
|
*idx = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
return a2dp_codec;
|
return a2dp_codec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -684,7 +688,7 @@ static int emit_nodes(struct impl *this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_supported_a2dp_codec(this, this->props.codec) == NULL)
|
if (get_supported_a2dp_codec(this, this->props.codec, NULL) == NULL)
|
||||||
this->props.codec = 0;
|
this->props.codec = 0;
|
||||||
break;
|
break;
|
||||||
case DEVICE_PROFILE_HSP_HFP:
|
case DEVICE_PROFILE_HSP_HFP:
|
||||||
|
|
@ -894,7 +898,7 @@ static void profiles_changed(void *userdata, uint32_t prev_profiles, uint32_t pr
|
||||||
nodes_changed);
|
nodes_changed);
|
||||||
break;
|
break;
|
||||||
case DEVICE_PROFILE_A2DP:
|
case DEVICE_PROFILE_A2DP:
|
||||||
if (get_supported_a2dp_codec(this, this->props.codec) == NULL)
|
if (get_supported_a2dp_codec(this, this->props.codec, NULL) == NULL)
|
||||||
this->props.codec = 0;
|
this->props.codec = 0;
|
||||||
nodes_changed = (connected_change & (SPA_BT_PROFILE_A2DP_SINK |
|
nodes_changed = (connected_change & (SPA_BT_PROFILE_A2DP_SINK |
|
||||||
SPA_BT_PROFILE_A2DP_SOURCE));
|
SPA_BT_PROFILE_A2DP_SOURCE));
|
||||||
|
|
@ -990,7 +994,7 @@ static uint32_t profile_direction_mask(struct impl *this, uint32_t index, enum s
|
||||||
if (device->connected_profiles & SPA_BT_PROFILE_A2DP_SINK)
|
if (device->connected_profiles & SPA_BT_PROFILE_A2DP_SINK)
|
||||||
have_output = true;
|
have_output = true;
|
||||||
|
|
||||||
a2dp_codec = get_supported_a2dp_codec(this, codec);
|
a2dp_codec = get_supported_a2dp_codec(this, codec, NULL);
|
||||||
if (a2dp_codec && a2dp_codec->duplex_codec)
|
if (a2dp_codec && a2dp_codec->duplex_codec)
|
||||||
have_input = true;
|
have_input = true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1138,11 +1142,13 @@ static struct spa_pod *build_profile(struct impl *this, struct spa_pod_builder *
|
||||||
char *desc_and_codec = NULL;
|
char *desc_and_codec = NULL;
|
||||||
uint32_t n_source = 0, n_sink = 0;
|
uint32_t n_source = 0, n_sink = 0;
|
||||||
uint32_t capture[1] = { DEVICE_ID_SOURCE }, playback[1] = { DEVICE_ID_SINK };
|
uint32_t capture[1] = { DEVICE_ID_SOURCE }, playback[1] = { DEVICE_ID_SINK };
|
||||||
|
int priority;
|
||||||
|
|
||||||
switch (profile_index) {
|
switch (profile_index) {
|
||||||
case DEVICE_PROFILE_OFF:
|
case DEVICE_PROFILE_OFF:
|
||||||
name = "off";
|
name = "off";
|
||||||
desc = _("Off");
|
desc = _("Off");
|
||||||
|
priority = 0;
|
||||||
break;
|
break;
|
||||||
case DEVICE_PROFILE_AG:
|
case DEVICE_PROFILE_AG:
|
||||||
{
|
{
|
||||||
|
|
@ -1154,6 +1160,7 @@ static struct spa_pod *build_profile(struct impl *this, struct spa_pod_builder *
|
||||||
name = "audio-gateway";
|
name = "audio-gateway";
|
||||||
desc = _("Audio Gateway (A2DP Source & HSP/HFP AG)");
|
desc = _("Audio Gateway (A2DP Source & HSP/HFP AG)");
|
||||||
}
|
}
|
||||||
|
priority = 256;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DEVICE_PROFILE_A2DP:
|
case DEVICE_PROFILE_A2DP:
|
||||||
|
|
@ -1167,7 +1174,8 @@ static struct spa_pod *build_profile(struct impl *this, struct spa_pod_builder *
|
||||||
name = spa_bt_profile_name(profile);
|
name = spa_bt_profile_name(profile);
|
||||||
n_sink++;
|
n_sink++;
|
||||||
if (codec) {
|
if (codec) {
|
||||||
const struct a2dp_codec *a2dp_codec = get_supported_a2dp_codec(this, codec);
|
size_t idx;
|
||||||
|
const struct a2dp_codec *a2dp_codec = get_supported_a2dp_codec(this, codec, &idx);
|
||||||
if (a2dp_codec == NULL) {
|
if (a2dp_codec == NULL) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -1183,12 +1191,14 @@ static struct spa_pod *build_profile(struct impl *this, struct spa_pod_builder *
|
||||||
|
|
||||||
}
|
}
|
||||||
desc = desc_and_codec;
|
desc = desc_and_codec;
|
||||||
|
priority = 16 + this->supported_codec_count - idx; /* order as in codec list */
|
||||||
} else {
|
} else {
|
||||||
if (profile == SPA_BT_PROFILE_A2DP_SINK) {
|
if (profile == SPA_BT_PROFILE_A2DP_SINK) {
|
||||||
desc = _("High Fidelity Playback (A2DP Sink)");
|
desc = _("High Fidelity Playback (A2DP Sink)");
|
||||||
} else {
|
} else {
|
||||||
desc = _("High Fidelity Duplex (A2DP Source/Sink)");
|
desc = _("High Fidelity Duplex (A2DP Source/Sink)");
|
||||||
}
|
}
|
||||||
|
priority = 16;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1217,8 +1227,10 @@ static struct spa_pod *build_profile(struct impl *this, struct spa_pod_builder *
|
||||||
desc_and_codec = spa_aprintf(_("Headset Head Unit (HSP/HFP, codec %s)"),
|
desc_and_codec = spa_aprintf(_("Headset Head Unit (HSP/HFP, codec %s)"),
|
||||||
get_hfp_codec_description(hfp_codec));
|
get_hfp_codec_description(hfp_codec));
|
||||||
desc = desc_and_codec;
|
desc = desc_and_codec;
|
||||||
|
priority = 1 + hfp_codec; /* prefer msbc over cvsd */
|
||||||
} else {
|
} else {
|
||||||
desc = _("Headset Head Unit (HSP/HFP)");
|
desc = _("Headset Head Unit (HSP/HFP)");
|
||||||
|
priority = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1233,7 +1245,7 @@ static struct spa_pod *build_profile(struct impl *this, struct spa_pod_builder *
|
||||||
SPA_PARAM_PROFILE_name, SPA_POD_String(name),
|
SPA_PARAM_PROFILE_name, SPA_POD_String(name),
|
||||||
SPA_PARAM_PROFILE_description, SPA_POD_String(desc),
|
SPA_PARAM_PROFILE_description, SPA_POD_String(desc),
|
||||||
SPA_PARAM_PROFILE_available, SPA_POD_Id(SPA_PARAM_AVAILABILITY_yes),
|
SPA_PARAM_PROFILE_available, SPA_POD_Id(SPA_PARAM_AVAILABILITY_yes),
|
||||||
SPA_PARAM_PROFILE_priority, SPA_POD_Int(codec),
|
SPA_PARAM_PROFILE_priority, SPA_POD_Int(priority),
|
||||||
0);
|
0);
|
||||||
if (n_source > 0 || n_sink > 0) {
|
if (n_source > 0 || n_sink > 0) {
|
||||||
spa_pod_builder_prop(b, SPA_PARAM_PROFILE_classes, 0);
|
spa_pod_builder_prop(b, SPA_PARAM_PROFILE_classes, 0);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue