alsactl: use link list to maintain source of events

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>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
Takashi Sakamoto 2018-10-14 23:36:29 +09:00 committed by Jaroslav Kysela
parent 5c859fa649
commit 5e010366d3

View file

@ -25,6 +25,16 @@
#include <sys/epoll.h> #include <sys/epoll.h>
#include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
#include <stddef.h>
#include "list.h"
struct src_entry {
snd_ctl_t *handle;
char *name;
unsigned int pfd_count;
struct list_head list;
};
#define MAX_CARDS 256 #define MAX_CARDS 256
struct snd_card_iterator { struct snd_card_iterator {
@ -55,6 +65,59 @@ static const char *snd_card_iterator_next(struct snd_card_iterator *iter)
return (const char *)iter->name; return (const char *)iter->name;
} }
static void remove_source_entry(struct src_entry *entry)
{
list_del(&entry->list);
free(entry->name);
free(entry);
}
static void clear_source_list(struct list_head *srcs)
{
struct src_entry *entry, *tmp;
list_for_each_entry_safe(entry, tmp, srcs, list)
remove_source_entry(entry);
}
static int insert_source_entry(struct list_head *srcs, snd_ctl_t *handle,
const char *name)
{
struct src_entry *entry;
int count;
int err;
entry = calloc(1, sizeof(*entry));
if (!entry)
return -ENOMEM;
INIT_LIST_HEAD(&entry->list);
entry->handle = handle;
entry->name = strdup(name);
if (!entry->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;
}
entry->pfd_count = count;
list_add_tail(&entry->list, srcs);
return 0;
error:
remove_source_entry(entry);
return err;
}
static int open_ctl(const char *name, snd_ctl_t **ctlp) static int open_ctl(const char *name, snd_ctl_t **ctlp)
{ {
snd_ctl_t *ctl; snd_ctl_t *ctl;
@ -222,6 +285,7 @@ static void clear_dispatcher(int epfd, snd_ctl_t **ctls, int ncards)
int monitor(const char *name) int monitor(const char *name)
{ {
LIST_HEAD(srcs);
snd_ctl_t *ctls[MAX_CARDS] = {0}; snd_ctl_t *ctls[MAX_CARDS] = {0};
int ncards = 0; int ncards = 0;
int show_cards; int show_cards;
@ -240,6 +304,9 @@ int monitor(const char *name)
snd_card_iterator_init(&iter); snd_card_iterator_init(&iter);
while ((cardname = snd_card_iterator_next(&iter))) { while ((cardname = snd_card_iterator_next(&iter))) {
err = open_ctl(cardname, &ctls[ncards]); err = open_ctl(cardname, &ctls[ncards]);
if (err < 0)
goto error;
err = insert_source_entry(&srcs, ctls[ncards], cardname);
if (err < 0) if (err < 0)
goto error; goto error;
ncards++; ncards++;
@ -247,6 +314,9 @@ int monitor(const char *name)
show_cards = 1; show_cards = 1;
} else { } else {
err = open_ctl(name, &ctls[0]); err = open_ctl(name, &ctls[0]);
if (err < 0)
goto error;
err = insert_source_entry(&srcs, ctls[ncards], name);
if (err < 0) if (err < 0)
goto error; goto error;
ncards++; ncards++;
@ -259,6 +329,7 @@ int monitor(const char *name)
clear_dispatcher(epfd, ctls, ncards); clear_dispatcher(epfd, ctls, ncards);
error: error:
clear_source_list(&srcs);
for (i = 0; i < ncards; i++) { for (i = 0; i < ncards; i++) {
if (ctls[i]) if (ctls[i])
snd_ctl_close(ctls[i]); snd_ctl_close(ctls[i]);