[alsa-devel] [PATCH][RFC][alsa-utils 5/9] alsactl: use link list to maintain source of events

Jaroslav Kysela perex at perex.cz
Fri Oct 5 19:14:41 CEST 2018


Dne 5.10.2018 v 16:47 Takashi Sakamoto napsal(a):
> 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.

Thanks for the improved code.

Please, use macros in list.h to manage linked list which are inherited
from the kernel here.

					Jaroslav

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


-- 
Jaroslav Kysela <perex at perex.cz>
Linux Sound Maintainer; ALSA Project; Red Hat, Inc.


More information about the Alsa-devel mailing list