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@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]);