mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
bluez5: fix BAP profiles for source/duplex cases
Codec switching does not currently work properly for source/duplex. With BAP it's also possible only when we're BAP client. When we can't codec switch, emit the "codecless" BAP profile.
This commit is contained in:
parent
4b60569c4a
commit
cfee662f0b
1 changed files with 74 additions and 26 deletions
|
|
@ -204,6 +204,33 @@ static const struct media_codec *get_supported_media_codec(struct impl *this, en
|
|||
return media_codec;
|
||||
}
|
||||
|
||||
static bool is_bap_client(struct impl *this)
|
||||
{
|
||||
struct spa_bt_device *device = this->bt_dev;
|
||||
struct spa_bt_transport *t;
|
||||
|
||||
spa_list_for_each(t, &device->transport_list, device_link) {
|
||||
if (t->bap_initiator)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool can_bap_codec_switch(struct impl *this)
|
||||
{
|
||||
if (!is_bap_client(this))
|
||||
return false;
|
||||
|
||||
/* XXX: codec switching for source/duplex is not currently
|
||||
* XXX: implemented properly. TODO: fix this
|
||||
*/
|
||||
if (this->bt_dev->connected_profiles & SPA_BT_PROFILE_BAP_SOURCE)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static unsigned int get_hfp_codec(enum spa_bluetooth_audio_codec id)
|
||||
{
|
||||
switch (id) {
|
||||
|
|
@ -873,9 +900,15 @@ static int set_profile(struct impl *this, uint32_t profile, enum spa_bluetooth_a
|
|||
* A2DP/BAP: ensure there's a transport with the selected codec (0 means any).
|
||||
* Don't try to switch codecs when the device is in the A2DP source role, since
|
||||
* devices do not appear to like that.
|
||||
*
|
||||
* For BAP, only BAP client can configure the codec.
|
||||
*
|
||||
* XXX: codec switching also currently does not work in the duplex or
|
||||
* XXX: source-only case, as it will only switch the sink, and we only
|
||||
* XXX: list the sink codecs here. TODO: fix this
|
||||
*/
|
||||
if ((profile == DEVICE_PROFILE_A2DP || profile == DEVICE_PROFILE_BAP)
|
||||
&& !(this->bt_dev->connected_profiles & SPA_BT_PROFILE_A2DP_SOURCE)) {
|
||||
if ((profile == DEVICE_PROFILE_A2DP || (profile == DEVICE_PROFILE_BAP && can_bap_codec_switch(this)))
|
||||
&& !(this->bt_dev->connected_profiles & SPA_BT_PROFILE_A2DP_SOURCE)) {
|
||||
int ret;
|
||||
const struct media_codec *codecs[64];
|
||||
|
||||
|
|
@ -1332,11 +1365,6 @@ static struct spa_pod *build_profile(struct impl *this, struct spa_pod_builder *
|
|||
if (profile == 0)
|
||||
return NULL;
|
||||
|
||||
if (!codec) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (profile & (SPA_BT_PROFILE_BAP_SINK))
|
||||
n_sink++;
|
||||
if (profile & (SPA_BT_PROFILE_BAP_SOURCE))
|
||||
|
|
@ -1344,28 +1372,48 @@ static struct spa_pod *build_profile(struct impl *this, struct spa_pod_builder *
|
|||
|
||||
name = spa_bt_profile_name(profile);
|
||||
|
||||
media_codec = get_supported_media_codec(this, codec, &idx);
|
||||
if (media_codec == NULL) {
|
||||
errno = EINVAL;
|
||||
/* If we can't codec switch, emit codecless profile */
|
||||
if ((codec != 0) != can_bap_codec_switch(this)) {
|
||||
errno = -EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
name_and_codec = spa_aprintf("%s-%s", name, media_codec->name);
|
||||
name = name_and_codec;
|
||||
switch (profile) {
|
||||
case SPA_BT_PROFILE_BAP_SINK:
|
||||
desc_and_codec = spa_aprintf(_("High Fidelity Playback (BAP Sink, codec %s)"),
|
||||
media_codec->description);
|
||||
break;
|
||||
case SPA_BT_PROFILE_BAP_SOURCE:
|
||||
desc_and_codec = spa_aprintf(_("High Fidelity Input (BAP Source, codec %s)"),
|
||||
media_codec->description);
|
||||
break;
|
||||
default:
|
||||
desc_and_codec = spa_aprintf(_("High Fidelity Duplex (BAP Source/Sink, codec %s)"),
|
||||
media_codec->description);
|
||||
|
||||
if (codec) {
|
||||
media_codec = get_supported_media_codec(this, codec, &idx);
|
||||
if (media_codec == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
name_and_codec = spa_aprintf("%s-%s", name, media_codec->name);
|
||||
name = name_and_codec;
|
||||
switch (profile) {
|
||||
case SPA_BT_PROFILE_BAP_SINK:
|
||||
desc_and_codec = spa_aprintf(_("High Fidelity Playback (BAP Sink, codec %s)"),
|
||||
media_codec->description);
|
||||
break;
|
||||
case SPA_BT_PROFILE_BAP_SOURCE:
|
||||
desc_and_codec = spa_aprintf(_("High Fidelity Input (BAP Source, codec %s)"),
|
||||
media_codec->description);
|
||||
break;
|
||||
default:
|
||||
desc_and_codec = spa_aprintf(_("High Fidelity Duplex (BAP Source/Sink, codec %s)"),
|
||||
media_codec->description);
|
||||
}
|
||||
desc = desc_and_codec;
|
||||
priority = 128 + this->supported_codec_count - idx; /* order as in codec list */
|
||||
} else {
|
||||
switch (profile) {
|
||||
case SPA_BT_PROFILE_BAP_SINK:
|
||||
desc = _("High Fidelity Playback (BAP Sink)");
|
||||
break;
|
||||
case SPA_BT_PROFILE_BAP_SOURCE:
|
||||
desc = _("High Fidelity Input (BAP Source)");
|
||||
break;
|
||||
default:
|
||||
desc = _("High Fidelity Duplex (BAP Source/Sink)");
|
||||
}
|
||||
priority = 128;
|
||||
}
|
||||
desc = desc_and_codec;
|
||||
priority = 128 + this->supported_codec_count - idx; /* order as in codec list */
|
||||
break;
|
||||
}
|
||||
case DEVICE_PROFILE_HSP_HFP:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue