From: Takashi Sakamoto Date: Mon, 18 Nov 2019 04:22:44 +0000 (+0900) Subject: ctl: card: add a API to retrieve list of element ID X-Git-Tag: v0.1.0~416 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=37b5e948b72ce19eaa1a1bc34d8215bc5c4d5651;p=alsa-gobject.git ctl: card: add a API to retrieve list of element ID --- diff --git a/src/ctl/alsactl.map b/src/ctl/alsactl.map index df95f63..cb1ed2b 100644 --- a/src/ctl/alsactl.map +++ b/src/ctl/alsactl.map @@ -15,6 +15,7 @@ ALSA_GOBJECT_0_0_0 { "alsactl_card_new"; "alsactl_card_open"; "alsactl_card_get_info"; + "alsactl_card_get_elem_id_list"; "alsactl_card_info_get_type"; diff --git a/src/ctl/card.c b/src/ctl/card.c index fa505a3..065d6e1 100644 --- a/src/ctl/card.c +++ b/src/ctl/card.c @@ -140,3 +140,88 @@ void alsactl_card_get_info(ALSACtlCard *self, ALSACtlCardInfo **card_info, g_object_unref(*card_info); } } + +static void allocate_elem_ids(int fd, struct snd_ctl_elem_list *list, + GError **error) +{ + struct snd_ctl_elem_id *ids; + + // Help for deallocation. + memset(list, 0, sizeof(*list)); + + // Get the number of elements in this control device. + if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, list) < 0) { + generate_error(error, errno); + return; + } + + // No elements found. + if (list->count == 0) + return; + + // Allocate spaces for these elements. + ids = calloc(list->count, sizeof(*ids)); + if (!ids) { + generate_error(error, ENOMEM); + return; + } + + list->offset = 0; + while (list->offset < list->count) { + // ALSA middleware has limitation of one operation. + // 1000 is enought less than the limitation. + list->space = MIN(list->count - list->offset, 1000); + list->pids = ids + list->offset; + + // Get the IDs of elements in this control device. + if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, list) < 0) { + generate_error(error, errno); + free(ids); + list->pids = NULL; + return; + } + + list->offset += list->space; + } + list->pids = ids; + list->space = list->count; +} + +static inline void deallocate_elem_ids(struct snd_ctl_elem_list *list) +{ + if (list->pids!= NULL) + free(list->pids); +} + +/** + * alsactl_card_get_elem_id_list: + * @self: A #ALSACtlCard. + * @entries: (element-type ALSACtl.ElemId)(out): The list of entries for + * ALSACtlElemId. + * @error: A #GError. + * + * Generate a list of ALSACtlElemId for ALSA control character device + * associated to the sound card. + */ +void alsactl_card_get_elem_id_list(ALSACtlCard *self, GList **entries, + GError **error) +{ + ALSACtlCardPrivate *priv; + struct snd_ctl_elem_list list = {0}; + int i; + + g_return_if_fail(ALSACTL_IS_CARD(self)); + priv = alsactl_card_get_instance_private(self); + + allocate_elem_ids(priv->fd, &list, error); + if (*error != NULL) + return; + + for (i = 0; i < list.count; ++i) { + struct snd_ctl_elem_id *id = list.pids + i; + ALSACtlElemId *elem_id = g_boxed_copy(ALSACTL_TYPE_ELEM_ID, id); + *entries = g_list_append(*entries, (gpointer)elem_id); + } + + deallocate_elem_ids(&list); +} diff --git a/src/ctl/card.h b/src/ctl/card.h index 0ead57e..cd1397e 100644 --- a/src/ctl/card.h +++ b/src/ctl/card.h @@ -6,6 +6,7 @@ #include #include +#include G_BEGIN_DECLS @@ -54,6 +55,9 @@ void alsactl_card_open(ALSACtlCard *self, guint card_id, GError **error); void alsactl_card_get_info(ALSACtlCard *self, ALSACtlCardInfo **card_info, GError **error); +void alsactl_card_get_elem_id_list(ALSACtlCard *self, GList **entries, + GError **error); + G_END_DECLS #endif diff --git a/src/ctl/elem-id.c b/src/ctl/elem-id.c index 3ff9969..b598e91 100644 --- a/src/ctl/elem-id.c +++ b/src/ctl/elem-id.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: LGPL-3.0-or-later -#include "elem-id.h" #include "privates.h" ALSACtlElemId *ctl_elem_id_copy(const ALSACtlElemId *self) diff --git a/src/ctl/privates.h b/src/ctl/privates.h index 69aeb2b..986c7de 100644 --- a/src/ctl/privates.h +++ b/src/ctl/privates.h @@ -8,6 +8,7 @@ #include #include "card-info.h" +#include "elem-id.h" #include diff --git a/tests/alsactl-card b/tests/alsactl-card index 05127ee..12f51de 100644 --- a/tests/alsactl-card +++ b/tests/alsactl-card @@ -17,6 +17,7 @@ methods = ( 'new', 'open', 'get_info', + 'get_elem_id_list', ) signals = ()