From 99a101f9c1c61b20fb8cee3862483191e158e6fc Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Wed, 4 Sep 2024 08:38:25 +0200 Subject: [PATCH] Remove duplicated channel count and channel maps --- INSTALL.md | 4 ++-- configure.ac | 2 +- src/bluealsa-dbus.c | 32 +++++++++++++++++++++++------ test/test-alsa-pcm.c | 48 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 9 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 733c150a3..c860a0009 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -26,8 +26,8 @@ then, to see a complete list of all options: Dependencies: -- [alsa-lib](https://www.alsa-project.org/) -- [bluez](http://www.bluez.org/) >= 5.0 +- [alsa-lib](https://www.alsa-project.org/) >= 1.0.27 +- [bluez](http://www.bluez.org/) >= 5.51 - [glib](https://wiki.gnome.org/Projects/GLib) >= 2.58.2 with GIO support - [sbc](https://git.kernel.org/cgit/bluetooth/sbc.git) >= 1.5 - [docutils](https://docutils.sourceforge.io) (when man pages build is enabled diff --git a/configure.ac b/configure.ac index 72f0c8652..6af51cde4 100644 --- a/configure.ac +++ b/configure.ac @@ -85,7 +85,7 @@ AC_SEARCH_LIBS([pow], [m], AC_SEARCH_LIBS([pthread_create], [pthread], [], [AC_MSG_ERROR([pthread library not found])]) -PKG_CHECK_MODULES([ALSA], [alsa]) +PKG_CHECK_MODULES([ALSA], [alsa >= 1.0.27]) PKG_CHECK_MODULES([BLUEZ], [bluez >= 5.51]) PKG_CHECK_MODULES([DBUS1], [dbus-1 >= 1.6]) PKG_CHECK_MODULES([GIO2], [gio-unix-2.0]) diff --git a/src/bluealsa-dbus.c b/src/bluealsa-dbus.c index d66d4f03e..30751c57d 100644 --- a/src/bluealsa-dbus.c +++ b/src/bluealsa-dbus.c @@ -310,23 +310,39 @@ static GVariant *ba_variant_new_pcm_volume(const struct ba_transport_pcm *pcm) { return g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, volume, n, sizeof(*volume)); } +struct ba_populate_data { + GVariantBuilder *builder; + /* previously added value */ + unsigned int value; +}; + static int ba_populate_channels(struct a2dp_bit_mapping mapping, void *userdata) { - g_variant_builder_add_value(userdata, g_variant_new_byte(mapping.value)); + struct ba_populate_data *data = userdata; + if (data->value == mapping.value) + return 0; + g_variant_builder_add_value(data->builder, g_variant_new_byte(mapping.value)); + data->value = mapping.value; return 0; } static int ba_populate_sampling(struct a2dp_bit_mapping mapping, void *userdata) { - g_variant_builder_add_value(userdata, g_variant_new_uint32(mapping.value)); + struct ba_populate_data *data = userdata; + g_variant_builder_add_value(data->builder, g_variant_new_uint32(mapping.value)); return 0; } static int ba_populate_channel_map(struct a2dp_bit_mapping mapping, void *userdata) { + struct ba_populate_data *data = userdata; + + if (data->value == mapping.ch.channels) + return 0; const char *strv[16]; for (size_t i = 0; i < mapping.ch.channels; i++) strv[i] = ba_transport_pcm_channel_to_string(mapping.ch.map[i]); - g_variant_builder_add_value(userdata, g_variant_new_strv(strv, mapping.ch.channels)); + g_variant_builder_add_value(data->builder, g_variant_new_strv(strv, mapping.ch.channels)); + data->value = mapping.ch.channels; return 0; } @@ -337,6 +353,7 @@ static void ba_variant_populate_remote_sep(GVariantBuilder *props, enum a2dp_stream stream) { GVariantBuilder builder; + struct ba_populate_data data = { .builder = &builder }; a2dp_t caps = remote_sep_cfg->capabilities; sep->caps_helpers->intersect(&caps, &sep->config.capabilities); @@ -344,16 +361,19 @@ static void ba_variant_populate_remote_sep(GVariantBuilder *props, g_variant_builder_add(props, "{sv}", "Capabilities", g_variant_new_fixed_array( G_VARIANT_TYPE_BYTE, &caps, remote_sep_cfg->caps_size, sizeof(uint8_t))); + data.value = 0; g_variant_builder_init(&builder, G_VARIANT_TYPE("ay")); - sep->caps_helpers->foreach_channel_mode(&caps, stream, ba_populate_channels, &builder); + sep->caps_helpers->foreach_channel_mode(&caps, stream, ba_populate_channels, &data); g_variant_builder_add(props, "{sv}", "SupportedChannels", g_variant_builder_end(&builder)); + data.value = 0; g_variant_builder_init(&builder, G_VARIANT_TYPE("au")); - sep->caps_helpers->foreach_sampling_freq(&caps, stream, ba_populate_sampling, &builder); + sep->caps_helpers->foreach_sampling_freq(&caps, stream, ba_populate_sampling, &data); g_variant_builder_add(props, "{sv}", "SupportedSampling", g_variant_builder_end(&builder)); + data.value = 0; g_variant_builder_init(&builder, G_VARIANT_TYPE("aas")); - sep->caps_helpers->foreach_channel_mode(&caps, stream, ba_populate_channel_map, &builder); + sep->caps_helpers->foreach_channel_mode(&caps, stream, ba_populate_channel_map, &data); g_variant_builder_add(props, "{sv}", "ChannelMaps", g_variant_builder_end(&builder)); } diff --git a/test/test-alsa-pcm.c b/test/test-alsa-pcm.c index 1f2323bac..65836b601 100644 --- a/test/test-alsa-pcm.c +++ b/test/test-alsa-pcm.c @@ -526,6 +526,53 @@ CK_START_TEST(ba_test_playback_hw_constraints) { } CK_END_TEST +CK_START_TEST(ba_test_playback_channel_maps) { + + if (pcm_device != NULL) + return; + + unsigned int buffer_time = 200000; + unsigned int period_time = 25000; + struct spawn_process sp_ba_mock; + snd_pcm_chmap_query_t **ch_maps; + snd_pcm_chmap_t *ch_map; + snd_pcm_t *pcm = NULL; + + ck_assert_int_eq(test_pcm_open(&sp_ba_mock, &pcm, SND_PCM_STREAM_PLAYBACK), 0); + ck_assert_int_eq(set_hw_params(pcm, pcm_format, pcm_channels, pcm_sampling, + &buffer_time, &period_time), 0); + + /* get all supported channel maps */ + ck_assert_ptr_nonnull(ch_maps = snd_pcm_query_chmaps(pcm)); + + size_t ch_maps_count = 0; + for (size_t i = 0; ch_maps[i] != NULL; i++) + ch_maps_count++; + /* SBC codec supports only mono and stereo */ + ck_assert_uint_eq(ch_maps_count, 2); + + ck_assert_uint_eq(ch_maps[0]->type, SND_CHMAP_TYPE_FIXED); + ck_assert_uint_eq(ch_maps[0]->map.channels, 1); + ck_assert_uint_eq(ch_maps[0]->map.pos[0], SND_CHMAP_MONO); + + ck_assert_uint_eq(ch_maps[1]->type, SND_CHMAP_TYPE_FIXED); + ck_assert_uint_eq(ch_maps[1]->map.channels, 2); + ck_assert_uint_eq(ch_maps[1]->map.pos[0], SND_CHMAP_FL); + ck_assert_uint_eq(ch_maps[1]->map.pos[1], SND_CHMAP_FR); + + /* get currently selected channel map */ + ck_assert_ptr_nonnull(ch_map = snd_pcm_get_chmap(pcm)); + /* stereo channel mode shall be selected by default */ + ck_assert_uint_eq(ch_map->channels, 2); + ck_assert_uint_eq(ch_map->pos[0], SND_CHMAP_FL); + ck_assert_uint_eq(ch_map->pos[1], SND_CHMAP_FR); + + free(ch_map); + snd_pcm_free_chmaps(ch_maps); + ck_assert_int_eq(test_pcm_close(&sp_ba_mock, pcm), 0); + +} CK_END_TEST + CK_START_TEST(ba_test_playback_no_codec_selected) { if (pcm_device != NULL) @@ -1164,6 +1211,7 @@ int main(int argc, char *argv[]) { TCase *tc = tcase_create("playback"); tcase_add_test(tc, dump_playback); tcase_add_test(tc, ba_test_playback_hw_constraints); + tcase_add_test(tc, ba_test_playback_channel_maps); tcase_add_test(tc, ba_test_playback_no_codec_selected); tcase_add_test(tc, ba_test_playback_no_such_device); tcase_add_test(tc, ba_test_playback_extra_setup);