mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
Enable SBC-XQ by default, and move it at the end of the codecs list, so that bluez does not connect to it automatically except when it is the codec used previously. When the codec is disabled by quirks, it won't appear in the codecs list, and so can't be selected by user (and so won't be connected automatically). However, since SelectConfiguration does not carry information which device is in question, we cannot prevent BlueZ connecting to the codec even if it's disabled for a specific device. If the "impossible" occurs regardless, we won't reject the connection and the profile will be shown as the generic "A2DP" one. If the sound is garbled, the user can select some other profile that works.
156 lines
3.2 KiB
C
156 lines
3.2 KiB
C
/*
|
|
* BlueALSA - bluez-a2dp.c
|
|
* Copyright (c) 2016-2017 Arkadiusz Bokowy
|
|
*
|
|
* This file is a part of bluez-alsa.
|
|
*
|
|
* This project is licensed under the terms of the MIT license.
|
|
*
|
|
*/
|
|
|
|
#include "a2dp-codecs.h"
|
|
|
|
int a2dp_codec_select_config(const struct a2dp_codec_config configs[], size_t n,
|
|
uint32_t cap, int preferred_value)
|
|
{
|
|
size_t i;
|
|
int *scores, res;
|
|
unsigned int max_priority;
|
|
|
|
if (n == 0)
|
|
return -EINVAL;
|
|
|
|
scores = calloc(n, sizeof(int));
|
|
if (scores == NULL)
|
|
return -errno;
|
|
|
|
max_priority = configs[0].priority;
|
|
for (i = 1; i < n; ++i) {
|
|
if (configs[i].priority > max_priority)
|
|
max_priority = configs[i].priority;
|
|
}
|
|
|
|
for (i = 0; i < n; ++i) {
|
|
if (!(configs[i].config & cap)) {
|
|
scores[i] = -1;
|
|
continue;
|
|
}
|
|
if (configs[i].value == preferred_value)
|
|
scores[i] = 100 * (max_priority + 1);
|
|
else if (configs[i].value > preferred_value)
|
|
scores[i] = 10 * (max_priority + 1);
|
|
else
|
|
scores[i] = 1;
|
|
|
|
scores[i] *= configs[i].priority + 1;
|
|
}
|
|
|
|
res = 0;
|
|
for (i = 1; i < n; ++i) {
|
|
if (scores[i] > scores[res])
|
|
res = i;
|
|
}
|
|
|
|
if (scores[res] < 0)
|
|
res = -EINVAL;
|
|
|
|
free(scores);
|
|
return res;
|
|
}
|
|
|
|
bool a2dp_codec_check_caps(const struct a2dp_codec *codec, unsigned int codec_id,
|
|
const void *caps, size_t caps_size,
|
|
const struct a2dp_codec_audio_info *info)
|
|
{
|
|
uint8_t config[A2DP_MAX_CAPS_SIZE];
|
|
int res;
|
|
|
|
if (codec_id != codec->codec_id)
|
|
return false;
|
|
|
|
if (caps == NULL)
|
|
return false;
|
|
|
|
res = codec->select_config(codec, 0, caps, caps_size, info, NULL, config);
|
|
if (res < 0)
|
|
return false;
|
|
|
|
return ((size_t)res == caps_size);
|
|
}
|
|
|
|
#if ENABLE_MP3
|
|
const a2dp_mpeg_t bluez_a2dp_mpeg = {
|
|
.layer =
|
|
MPEG_LAYER_MP1 |
|
|
MPEG_LAYER_MP2 |
|
|
MPEG_LAYER_MP3,
|
|
.crc = 1,
|
|
.channel_mode =
|
|
MPEG_CHANNEL_MODE_MONO |
|
|
MPEG_CHANNEL_MODE_DUAL_CHANNEL |
|
|
MPEG_CHANNEL_MODE_STEREO |
|
|
MPEG_CHANNEL_MODE_JOINT_STEREO,
|
|
.mpf = 1,
|
|
.frequency =
|
|
MPEG_SAMPLING_FREQ_16000 |
|
|
MPEG_SAMPLING_FREQ_22050 |
|
|
MPEG_SAMPLING_FREQ_24000 |
|
|
MPEG_SAMPLING_FREQ_32000 |
|
|
MPEG_SAMPLING_FREQ_44100 |
|
|
MPEG_SAMPLING_FREQ_48000,
|
|
.bitrate =
|
|
MPEG_BIT_RATE_VBR |
|
|
MPEG_BIT_RATE_320000 |
|
|
MPEG_BIT_RATE_256000 |
|
|
MPEG_BIT_RATE_224000 |
|
|
MPEG_BIT_RATE_192000 |
|
|
MPEG_BIT_RATE_160000 |
|
|
MPEG_BIT_RATE_128000 |
|
|
MPEG_BIT_RATE_112000 |
|
|
MPEG_BIT_RATE_96000 |
|
|
MPEG_BIT_RATE_80000 |
|
|
MPEG_BIT_RATE_64000 |
|
|
MPEG_BIT_RATE_56000 |
|
|
MPEG_BIT_RATE_48000 |
|
|
MPEG_BIT_RATE_40000 |
|
|
MPEG_BIT_RATE_32000 |
|
|
MPEG_BIT_RATE_FREE,
|
|
};
|
|
#endif
|
|
|
|
extern struct a2dp_codec a2dp_codec_sbc;
|
|
extern struct a2dp_codec a2dp_codec_sbc_xq;
|
|
#if ENABLE_LDAC
|
|
extern struct a2dp_codec a2dp_codec_ldac;
|
|
#endif
|
|
#if ENABLE_AAC
|
|
extern struct a2dp_codec a2dp_codec_aac;
|
|
#endif
|
|
#if ENABLE_MP3
|
|
extern struct a2dp_codec a2dp_codec_mpeg;
|
|
#endif
|
|
#if ENABLE_APTX
|
|
extern struct a2dp_codec a2dp_codec_aptx;
|
|
extern struct a2dp_codec a2dp_codec_aptx_hd;
|
|
#endif
|
|
|
|
static const struct a2dp_codec * const a2dp_codec_list[] = {
|
|
#if ENABLE_LDAC
|
|
&a2dp_codec_ldac,
|
|
#endif
|
|
#if ENABLE_APTX
|
|
&a2dp_codec_aptx_hd,
|
|
&a2dp_codec_aptx,
|
|
#endif
|
|
#if ENABLE_AAC
|
|
&a2dp_codec_aac,
|
|
#endif
|
|
#if ENABLE_MP3
|
|
&a2dp_codec_mpeg,
|
|
#endif
|
|
&a2dp_codec_sbc,
|
|
&a2dp_codec_sbc_xq,
|
|
NULL
|
|
};
|
|
|
|
const struct a2dp_codec * const * const a2dp_codecs = a2dp_codec_list;
|