[alsa-devel] [PATCH][RFC][alsa-utils 5/9] alsactl: use link list to maintain source of events
Takashi Sakamoto
o-takashi at sakamocchi.jp
Fri Oct 5 16:47:25 CEST 2018
At present, handlers for control nodes are maintained by one-dimensional
array. This is not necessarily useful to maintain handlers with
associated information.
This commit adds link-list for the maintenance.
Signed-off-by: Takashi Sakamoto <o-takashi at sakamocchi.jp>
---
alsactl/monitor.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 84 insertions(+)
diff --git a/alsactl/monitor.c b/alsactl/monitor.c
index cf5c50a..8b16307 100644
--- a/alsactl/monitor.c
+++ b/alsactl/monitor.c
@@ -29,6 +29,16 @@
static int signal_type;
static bool interrupted;
+struct src_entry {
+ snd_ctl_t *handle;
+ char *name;
+ unsigned int pfd_count;
+ struct {
+ struct src_entry *prev;
+ struct src_entry *next;
+ } list;
+};
+
#define MAX_CARDS 256
struct snd_card_iterator {
@@ -59,6 +69,72 @@ static const char *snd_card_iterator_next(struct snd_card_iterator *iter)
return (const char *)iter->name;
}
+static inline void remove_source_entry(struct src_entry *src)
+{
+ struct src_entry *prev = src->list.prev;
+ struct src_entry *next = src->list.next;
+
+ if (prev)
+ prev->list.next = src->list.next;
+ if (next)
+ next->list.prev = src->list.prev;
+ free(src->name);
+ free(src);
+}
+
+static void clear_source_list(struct src_entry **srcs)
+{
+ while (*srcs) {
+ struct src_entry *src = *srcs;
+ *srcs = src->list.next;
+
+ remove_source_entry(src);
+ }
+}
+
+static int insert_source_entry(struct src_entry **head, snd_ctl_t *handle,
+ const char *name)
+{
+ struct src_entry *src;
+ int count;
+ int err;
+
+ src = calloc(1, sizeof(*src));
+ if (!src)
+ return -ENOMEM;
+ src->handle = handle;
+
+ src->name = strdup(name);
+ if (!src->name) {
+ err = -ENOMEM;
+ goto error;
+ }
+
+ count = snd_ctl_poll_descriptors_count(handle);
+ if (count < 0) {
+ err = count;
+ goto error;
+ }
+ if (count == 0) {
+ err = -ENXIO;
+ goto error;
+ }
+ src->pfd_count = count;
+
+ if (*head) {
+ src->list.next = (*head)->list.next;
+ src->list.prev = *head;
+ (*head)->list.next = src;
+ } else {
+ *head = src;
+ }
+
+ return 0;
+error:
+ free(src);
+ return err;
+}
+
static int open_ctl(const char *name, snd_ctl_t **ctlp)
{
snd_ctl_t *ctl;
@@ -259,6 +335,7 @@ static int prepare_signal_handler(void)
int monitor(const char *name)
{
+ struct src_entry *srcs = NULL;
snd_ctl_t *ctls[MAX_CARDS] = {0};
int ncards = 0;
int show_cards;
@@ -281,6 +358,9 @@ int monitor(const char *name)
snd_card_iterator_init(&iter);
while ((cardname = snd_card_iterator_next(&iter))) {
err = open_ctl(cardname, &ctls[ncards]);
+ if (err < 0)
+ goto error;
+ err = insert_source_entry(&srcs, ctls[ncards], cardname);
if (err < 0)
goto error;
++ncards;
@@ -288,6 +368,9 @@ int monitor(const char *name)
show_cards = 1;
} else {
err = open_ctl(name, &ctls[0]);
+ if (err < 0)
+ goto error;
+ err = insert_source_entry(&srcs, ctls[ncards], name);
if (err < 0)
goto error;
ncards++;
@@ -300,6 +383,7 @@ int monitor(const char *name)
clear_dispatcher(epfd, ctls, ncards);
error:
+ clear_source_list(&srcs);
for (i = 0; i < ncards; i++) {
if (ctls[i])
snd_ctl_close(ctls[i]);
--
2.19.0
More information about the Alsa-devel
mailing list