Skip to content

Commit fa7e1e0

Browse files
committed
Implement channel map query for ALSA PCM plug-in
1 parent 48ac9b1 commit fa7e1e0

File tree

3 files changed

+140
-22
lines changed

3 files changed

+140
-22
lines changed

src/asound/bluealsa-pcm.c

+95-6
Original file line numberDiff line numberDiff line change
@@ -580,17 +580,34 @@ static int bluealsa_hw_params(snd_pcm_ioplug_t *io, snd_pcm_hw_params_t *params)
580580
debug2("Changing BlueALSA PCM configuration: %u ch, %u Hz -> %u ch, %u Hz",
581581
pcm->ba_pcm.channels, pcm->ba_pcm.sampling, channels, sampling);
582582

583-
if (ba_dbus_pcm_select_codec(&pcm->dbus_ctx, pcm->ba_pcm.pcm_path,
584-
pcm->ba_pcm.codec.name, pcm->ba_pcm_codec_config, pcm->ba_pcm_codec_config_len,
583+
const char *codec_name = pcm->ba_pcm.codec.name;
584+
if (!ba_dbus_pcm_select_codec(&pcm->dbus_ctx, pcm->ba_pcm.pcm_path,
585+
codec_name, pcm->ba_pcm_codec_config, pcm->ba_pcm_codec_config_len,
585586
channels, sampling, BA_PCM_SELECT_CODEC_FLAG_NONE, &err)) {
586-
pcm->ba_pcm.channels = channels;
587-
pcm->ba_pcm.sampling = sampling;
588-
}
589-
else {
590587
SNDERR("Couldn't change BlueALSA PCM configuration: %s", err.message);
591588
return -dbus_error_to_errno(&err);
592589
}
593590

591+
/* After new codec selection, it is necessary to update the PCM data.
592+
* We will do it the off-line manner (without server interaction) to
593+
* speed up the process. */
594+
595+
pcm->ba_pcm.channels = channels;
596+
pcm->ba_pcm.sampling = sampling;
597+
598+
for (size_t i = 0; i < pcm->ba_pcm_codecs.codecs_len; i++) {
599+
const struct ba_pcm_codec *codec = &pcm->ba_pcm_codecs.codecs[i];
600+
if (strcmp(codec->name, codec_name) == 0) {
601+
for (size_t j = 0; j < ARRAYSIZE(codec->channel_maps); j++)
602+
if (codec->channels[j] == channels) {
603+
memcpy(pcm->ba_pcm.channel_map, codec->channel_maps[j],
604+
sizeof(pcm->ba_pcm.channel_map));
605+
break;
606+
}
607+
break;
608+
}
609+
}
610+
594611
}
595612

596613
#if BLUEALSA_HW_PARAMS_FIX
@@ -1133,6 +1150,76 @@ static int bluealsa_poll_revents(snd_pcm_ioplug_t *io, struct pollfd *pfd,
11331150
return -ENODEV;
11341151
}
11351152

1153+
static enum snd_pcm_chmap_position ba_channel_map_to_position(const char *tag) {
1154+
1155+
static const struct {
1156+
const char *tag;
1157+
enum snd_pcm_chmap_position pos;
1158+
} mapping[] = {
1159+
{ "MONO", SND_CHMAP_MONO },
1160+
{ "FL", SND_CHMAP_FL },
1161+
{ "FR", SND_CHMAP_FR },
1162+
{ "RL", SND_CHMAP_RL },
1163+
{ "RR", SND_CHMAP_RR },
1164+
{ "FC", SND_CHMAP_FC },
1165+
{ "LFE", SND_CHMAP_LFE },
1166+
{ "SL", SND_CHMAP_SL },
1167+
{ "SR", SND_CHMAP_SR },
1168+
};
1169+
1170+
for (size_t i = 0; i < ARRAYSIZE(mapping); i++)
1171+
if (strcmp(tag, mapping[i].tag) == 0)
1172+
return mapping[i].pos;
1173+
return SND_CHMAP_UNKNOWN;
1174+
}
1175+
1176+
static snd_pcm_chmap_query_t **bluealsa_query_chmaps(snd_pcm_ioplug_t *io) {
1177+
struct bluealsa_pcm *pcm = io->private_data;
1178+
1179+
const struct ba_pcm_codec *codec = &pcm->ba_pcm.codec;
1180+
for (size_t i = 0; i < pcm->ba_pcm_codecs.codecs_len; i++)
1181+
if (strcmp(pcm->ba_pcm_codecs.codecs[i].name, codec->name) == 0) {
1182+
codec = &pcm->ba_pcm_codecs.codecs[i];
1183+
break;
1184+
}
1185+
1186+
snd_pcm_chmap_query_t **maps;
1187+
if ((maps = malloc(sizeof(*maps) * (ARRAYSIZE(codec->channel_maps) + 1))) == NULL)
1188+
return NULL;
1189+
1190+
maps[ARRAYSIZE(codec->channel_maps)] = NULL;
1191+
for (size_t i = 0; i < ARRAYSIZE(codec->channel_maps); i++) {
1192+
1193+
unsigned int channels;
1194+
if ((channels = codec->channels[i]) == 0)
1195+
break;
1196+
1197+
maps[i] = malloc(sizeof(*maps[i]) + (channels * sizeof(*maps[i]->map.pos)));
1198+
maps[i]->type = SND_CHMAP_TYPE_FIXED;
1199+
maps[i]->map.channels = channels;
1200+
1201+
for (size_t j = 0; j < channels; j++)
1202+
maps[i]->map.pos[j] = ba_channel_map_to_position(codec->channel_maps[i][j]);
1203+
1204+
}
1205+
1206+
return maps;
1207+
}
1208+
1209+
static snd_pcm_chmap_t *bluealsa_get_chmap(snd_pcm_ioplug_t *io) {
1210+
struct bluealsa_pcm *pcm = io->private_data;
1211+
1212+
snd_pcm_chmap_t *map;
1213+
if ((map = malloc(sizeof(*map) + (io->channels * sizeof(*map->pos)))) == NULL)
1214+
return NULL;
1215+
1216+
map->channels = io->channels;
1217+
for (size_t i = 0; i < io->channels; i++)
1218+
map->pos[i] = ba_channel_map_to_position(pcm->ba_pcm.channel_map[i]);
1219+
1220+
return map;
1221+
}
1222+
11361223
static const snd_pcm_ioplug_callback_t bluealsa_callback = {
11371224
.start = bluealsa_start,
11381225
.stop = bluealsa_stop,
@@ -1149,6 +1236,8 @@ static const snd_pcm_ioplug_callback_t bluealsa_callback = {
11491236
.poll_descriptors_count = bluealsa_poll_descriptors_count,
11501237
.poll_descriptors = bluealsa_poll_descriptors,
11511238
.poll_revents = bluealsa_poll_revents,
1239+
.query_chmaps = bluealsa_query_chmaps,
1240+
.get_chmap = bluealsa_get_chmap,
11521241
};
11531242

11541243
static int str2bdaddr(const char *str, bdaddr_t *ba) {

src/shared/dbus-client-pcm.c

+43-16
Original file line numberDiff line numberDiff line change
@@ -232,32 +232,54 @@ static void dbus_message_iter_get_codec_data(DBusMessageIter *variant,
232232
static void dbus_message_iter_get_codec_supported_channels(DBusMessageIter *variant,
233233
struct ba_pcm_codec *codec) {
234234

235-
DBusMessageIter iter;
236-
unsigned char *data;
237-
int len;
235+
DBusMessageIter iter;
236+
unsigned char *data;
237+
int len;
238238

239-
dbus_message_iter_recurse(variant, &iter);
240-
dbus_message_iter_get_fixed_array(&iter, &data, &len);
239+
dbus_message_iter_recurse(variant, &iter);
240+
dbus_message_iter_get_fixed_array(&iter, &data, &len);
241241

242-
len = MIN(len, ARRAYSIZE(codec->channels));
243-
for (size_t i = 0; i < (size_t)len; i++)
244-
codec->channels[i] = data[i];
242+
len = MIN(len, ARRAYSIZE(codec->channels));
243+
for (size_t i = 0; i < (size_t)len; i++)
244+
codec->channels[i] = data[i];
245245

246246
}
247247

248248
static void dbus_message_iter_get_codec_supported_sampling(DBusMessageIter *variant,
249249
struct ba_pcm_codec *codec) {
250250

251-
DBusMessageIter iter;
252-
dbus_uint32_t *data;
253-
int len;
251+
DBusMessageIter iter;
252+
dbus_uint32_t *data;
253+
int len;
254254

255-
dbus_message_iter_recurse(variant, &iter);
256-
dbus_message_iter_get_fixed_array(&iter, &data, &len);
255+
dbus_message_iter_recurse(variant, &iter);
256+
dbus_message_iter_get_fixed_array(&iter, &data, &len);
257257

258-
len = MIN(len, ARRAYSIZE(codec->sampling));
259-
for (size_t i = 0; i < (size_t)len; i++)
260-
codec->sampling[i] = data[i];
258+
len = MIN(len, ARRAYSIZE(codec->sampling));
259+
for (size_t i = 0; i < (size_t)len; i++)
260+
codec->sampling[i] = data[i];
261+
262+
}
263+
264+
static void dbus_message_iter_get_codec_channel_maps(DBusMessageIter *variant,
265+
struct ba_pcm_codec *codec) {
266+
267+
size_t i;
268+
DBusMessageIter iter_array;
269+
for (dbus_message_iter_recurse(variant, &iter_array), i = 0;
270+
dbus_message_iter_get_arg_type(&iter_array) != DBUS_TYPE_INVALID;
271+
dbus_message_iter_next(&iter_array)) {
272+
273+
const char *data[ARRAYSIZE(*codec->channel_maps)];
274+
size_t length = ARRAYSIZE(data);
275+
276+
dbus_message_iter_array_get_strings(&iter_array, NULL, data, &length);
277+
278+
for (size_t j = 0; j < length; j++)
279+
strncpy(codec->channel_maps[i][j], data[j], sizeof(codec->channel_maps[i][j]) - 1);
280+
281+
i++;
282+
}
261283

262284
}
263285

@@ -295,6 +317,11 @@ static dbus_bool_t ba_dbus_message_iter_pcm_codec_get_props_cb(const char *key,
295317
goto fail;
296318
dbus_message_iter_get_codec_supported_sampling(&variant, codec);
297319
}
320+
else if (strcmp(key, "ChannelMaps") == 0) {
321+
if (type != (type_expected = DBUS_TYPE_ARRAY))
322+
goto fail;
323+
dbus_message_iter_get_codec_channel_maps(&variant, codec);
324+
}
298325

299326
return TRUE;
300327

src/shared/dbus-client-pcm.h

+2
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ struct ba_pcm_codec {
8989
unsigned char channels[8];
9090
/* sampling frequencies supported by the codec */
9191
dbus_uint32_t sampling[16];
92+
/* channel maps associated with supported number of channels */
93+
char channel_maps[8][8][5];
9294
};
9395

9496
/**

0 commit comments

Comments
 (0)