[pulseaudio-discuss] [RFC 07/12] bluetooth: Handle SelectConfiguration for MP3 endpoint
Frédéric Dalleau
frederic.dalleau at linux.intel.com
Mon Feb 6 06:24:43 PST 2012
---
src/modules/bluetooth/bluetooth-util.c | 141 ++++++++++++++++++++++----------
1 files changed, 98 insertions(+), 43 deletions(-)
diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
index deef7ce..30ceba5 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -1279,14 +1279,51 @@ static uint8_t a2dp_default_bitpool(uint8_t freq, uint8_t mode) {
}
}
-static DBusMessage *endpoint_select_configuration(DBusConnection *c, DBusMessage *m, void *userdata) {
- pa_bluetooth_discovery *y = userdata;
- a2dp_sbc_t *cap, config;
- uint8_t *pconf = (uint8_t *) &config;
- int i, size;
- DBusMessage *r;
- DBusError e;
+static int endpoint_mpeg_select_configuration(pa_bluetooth_discovery *y, uint8_t *capbuf, uint8_t *buf, unsigned int size) {
+ a2dp_mpeg_t *config = (a2dp_mpeg_t *)buf;
+ a2dp_mpeg_t *cap = (a2dp_mpeg_t *)capbuf;
+
+ pa_assert(size >= sizeof(a2dp_mpeg_t));
+
+ config->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
+ config->crc = 0;
+ config->layer = BT_MPEG_LAYER_3;
+ config->mpf = 0;
+ config->rfa = 0;
+ config->bitrate = (1 << 11); /* vbr? */
+
+ if (y->core->default_sample_spec.rate == 48000)
+ config->frequency = BT_MPEG_SAMPLING_FREQ_48000;
+ else
+ config->frequency = BT_MPEG_SAMPLING_FREQ_44100;
+ if (y->core->default_sample_spec.channels <= 1) {
+ if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
+ config->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
+ }
+
+ if (y->core->default_sample_spec.channels >= 2) {
+ if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
+ config->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
+ else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
+ config->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
+ else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
+ config->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
+ else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) {
+ config->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
+ } else {
+ pa_log("No supported channel modes");
+ return -1;
+ }
+ }
+
+ return sizeof(a2dp_mpeg_t);
+}
+
+static int endpoint_sbc_select_configuration(pa_bluetooth_discovery *y, uint8_t *capbuf, uint8_t *buf, unsigned int size) {
+ int i;
+ a2dp_sbc_t *cap = (a2dp_sbc_t *)capbuf;
+ a2dp_sbc_t *config = (a2dp_sbc_t *)buf;
static const struct {
uint32_t rate;
uint8_t cap;
@@ -1297,40 +1334,29 @@ static DBusMessage *endpoint_select_configuration(DBusConnection *c, DBusMessage
{ 48000U, BT_SBC_SAMPLING_FREQ_48000 }
};
- dbus_error_init(&e);
+ pa_assert(size >= sizeof(a2dp_sbc_t));
- if (!dbus_message_get_args(m, &e, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &cap, &size, DBUS_TYPE_INVALID)) {
- pa_log("org.bluez.MediaEndpoint.SelectConfiguration: %s", e.message);
- dbus_error_free(&e);
- goto fail;
- }
-
- if (dbus_message_has_path(m, HFP_AG_ENDPOINT) || dbus_message_has_path(m, HFP_HS_ENDPOINT))
- goto done;
-
- pa_assert(size == sizeof(config));
-
- memset(&config, 0, sizeof(config));
+ memset(config, 0, size);
/* Find the lowest freq that is at least as high as the requested
* sampling rate */
for (i = 0; (unsigned) i < PA_ELEMENTSOF(freq_table); i++)
if (freq_table[i].rate >= y->core->default_sample_spec.rate && (cap->frequency & freq_table[i].cap)) {
- config.frequency = freq_table[i].cap;
+ config->frequency = freq_table[i].cap;
break;
}
if ((unsigned) i == PA_ELEMENTSOF(freq_table)) {
for (--i; i >= 0; i--) {
if (cap->frequency & freq_table[i].cap) {
- config.frequency = freq_table[i].cap;
+ config->frequency = freq_table[i].cap;
break;
}
}
if (i < 0) {
pa_log("Not suitable sample rate");
- goto fail;
+ return -1;
}
}
@@ -1338,59 +1364,88 @@ static DBusMessage *endpoint_select_configuration(DBusConnection *c, DBusMessage
if (y->core->default_sample_spec.channels <= 1) {
if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
- config.channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
+ config->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
}
if (y->core->default_sample_spec.channels >= 2) {
if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
- config.channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
+ config->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
- config.channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
+ config->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
- config.channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
+ config->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) {
- config.channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
+ config->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
} else {
pa_log("No supported channel modes");
- goto fail;
+ return -1;
}
}
if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16)
- config.block_length = BT_A2DP_BLOCK_LENGTH_16;
+ config->block_length = BT_A2DP_BLOCK_LENGTH_16;
else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12)
- config.block_length = BT_A2DP_BLOCK_LENGTH_12;
+ config->block_length = BT_A2DP_BLOCK_LENGTH_12;
else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8)
- config.block_length = BT_A2DP_BLOCK_LENGTH_8;
+ config->block_length = BT_A2DP_BLOCK_LENGTH_8;
else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4)
- config.block_length = BT_A2DP_BLOCK_LENGTH_4;
+ config->block_length = BT_A2DP_BLOCK_LENGTH_4;
else {
pa_log_error("No supported block lengths");
- goto fail;
+ return -1;
}
if (cap->subbands & BT_A2DP_SUBBANDS_8)
- config.subbands = BT_A2DP_SUBBANDS_8;
+ config->subbands = BT_A2DP_SUBBANDS_8;
else if (cap->subbands & BT_A2DP_SUBBANDS_4)
- config.subbands = BT_A2DP_SUBBANDS_4;
+ config->subbands = BT_A2DP_SUBBANDS_4;
else {
pa_log_error("No supported subbands");
- goto fail;
+ return -1;
}
if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS)
- config.allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
+ config->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR)
- config.allocation_method = BT_A2DP_ALLOCATION_SNR;
+ config->allocation_method = BT_A2DP_ALLOCATION_SNR;
+
+ config->min_bitpool = (uint8_t) PA_MAX(MIN_BITPOOL, cap->min_bitpool);
+ config->max_bitpool = (uint8_t) PA_MIN(a2dp_default_bitpool(config->frequency, config->channel_mode), cap->max_bitpool);
+
+ return sizeof(a2dp_sbc_t);
+}
+
+static DBusMessage *endpoint_select_configuration(DBusConnection *c, DBusMessage *m, void *userdata) {
+ pa_bluetooth_discovery *y = userdata;
+ DBusMessage *r;
+ uint8_t *cap, config[4];
+ uint8_t *pconf = config;
+ int size;
+ DBusError e;
+
+ dbus_error_init(&e);
- config.min_bitpool = (uint8_t) PA_MAX(MIN_BITPOOL, cap->min_bitpool);
- config.max_bitpool = (uint8_t) PA_MIN(a2dp_default_bitpool(config.frequency, config.channel_mode), cap->max_bitpool);
+ if (!dbus_message_get_args(m, &e, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &cap, &size, DBUS_TYPE_INVALID)) {
+ pa_log("org.bluez.MediaEndpoint.SelectConfiguration: %s", e.message);
+ dbus_error_free(&e);
+ goto fail;
+ }
+
+ if (dbus_message_has_path(m, HFP_AG_ENDPOINT) || dbus_message_has_path(m, HFP_HS_ENDPOINT))
+ goto done;
+
+ if (dbus_message_has_path(m, A2DP_SOURCE_ENDPOINT_MPEG))
+ size = endpoint_mpeg_select_configuration(y, cap, pconf, sizeof(config));
+ else
+ size = endpoint_sbc_select_configuration(y, cap, pconf, sizeof(config));
+
+ if(size < 0)
+ goto fail;
done:
pa_assert_se(r = dbus_message_new_method_return(m));
- pa_assert_se(dbus_message_append_args(
- r,
+ pa_assert_se(dbus_message_append_args(r,
DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &pconf, size,
DBUS_TYPE_INVALID));
--
1.7.5.4
More information about the pulseaudio-discuss
mailing list