mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-12-22 22:06:31 +01:00
alsactl: use epoll(7) instead of poll(2)
Linux kernel supports unique system call; epoll(7). This allows applications to make associations for descriptor-unique data in a easy way. This commit uses epoll(7) instead of poll(2) for this point. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
parent
fbc31a7593
commit
5c859fa649
1 changed files with 118 additions and 26 deletions
|
@ -20,6 +20,9 @@
|
|||
#include "aconfig.h"
|
||||
#include "version.h"
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
#define MAX_CARDS 256
|
||||
|
@ -114,41 +117,121 @@ static int print_event(int card, snd_ctl_t *ctl)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int run_dispatcher(snd_ctl_t **ctls, int ncards, int show_cards)
|
||||
static int operate_dispatcher(int epfd, uint32_t op, struct epoll_event *epev,
|
||||
snd_ctl_t *ctl)
|
||||
{
|
||||
struct pollfd *pfds;
|
||||
int count;
|
||||
unsigned int pfd_count;
|
||||
int i;
|
||||
int err;
|
||||
|
||||
count = snd_ctl_poll_descriptors_count(ctl);
|
||||
if (count < 0)
|
||||
return count;
|
||||
if (count == 0)
|
||||
return -ENXIO;
|
||||
pfd_count = count;
|
||||
|
||||
pfds = calloc(pfd_count, sizeof(*pfds));
|
||||
if (!pfds)
|
||||
return -ENOMEM;
|
||||
|
||||
count = snd_ctl_poll_descriptors(ctl, pfds, pfd_count);
|
||||
if (count < 0) {
|
||||
err = count;
|
||||
goto end;
|
||||
}
|
||||
if (count != pfd_count) {
|
||||
err = -EIO;
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (i = 0; i < pfd_count; ++i) {
|
||||
err = epoll_ctl(epfd, op, pfds[i].fd, epev);
|
||||
if (err < 0)
|
||||
break;
|
||||
}
|
||||
end:
|
||||
free(pfds);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int prepare_dispatcher(int epfd, snd_ctl_t **ctls, int ncards)
|
||||
{
|
||||
int i;
|
||||
int err = 0;
|
||||
|
||||
for (;ncards > 0;) {
|
||||
struct pollfd fds[ncards];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ncards; i++)
|
||||
snd_ctl_poll_descriptors(ctls[i], &fds[i], 1);
|
||||
|
||||
err = poll(fds, ncards, -1);
|
||||
if (err <= 0) {
|
||||
err = 0;
|
||||
for (i = 0; i < ncards; ++i) {
|
||||
snd_ctl_t *ctl = ctls[i];
|
||||
struct epoll_event ev;
|
||||
ev.events = EPOLLIN;
|
||||
ev.data.ptr = (void *)ctl;
|
||||
err = operate_dispatcher(epfd, EPOLL_CTL_ADD, &ev, ctl);
|
||||
if (err < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < ncards; i++) {
|
||||
unsigned short revents;
|
||||
snd_ctl_poll_descriptors_revents(ctls[i], &fds[i], 1,
|
||||
&revents);
|
||||
if (revents & POLLIN)
|
||||
print_event(show_cards ? i : -1, ctls[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int run_dispatcher(int epfd, unsigned int max_ev_count, int show_cards)
|
||||
{
|
||||
struct epoll_event *epev;
|
||||
int err = 0;
|
||||
|
||||
epev = calloc(max_ev_count, sizeof(*epev));
|
||||
if (!epev)
|
||||
return -ENOMEM;
|
||||
|
||||
while (true) {
|
||||
int count;
|
||||
int i;
|
||||
|
||||
count = epoll_wait(epfd, epev, max_ev_count, 200);
|
||||
if (count < 0) {
|
||||
err = count;
|
||||
break;
|
||||
}
|
||||
if (count == 0)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
struct epoll_event *ev = epev + i;
|
||||
snd_ctl_t *handle = (snd_ctl_t *)ev->data.ptr;
|
||||
|
||||
if (ev->events & EPOLLIN)
|
||||
print_event(show_cards ? i : -1, handle);
|
||||
}
|
||||
}
|
||||
|
||||
free(epev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void clear_dispatcher(int epfd, snd_ctl_t **ctls, int ncards)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ncards; ++i) {
|
||||
snd_ctl_t *ctl = ctls[i];
|
||||
operate_dispatcher(epfd, EPOLL_CTL_DEL, NULL, ctl);
|
||||
}
|
||||
}
|
||||
|
||||
int monitor(const char *name)
|
||||
{
|
||||
snd_ctl_t *ctls[MAX_CARDS];
|
||||
snd_ctl_t *ctls[MAX_CARDS] = {0};
|
||||
int ncards = 0;
|
||||
int show_cards;
|
||||
int i, err = 0;
|
||||
int epfd;
|
||||
int i;
|
||||
int err = 0;
|
||||
|
||||
epfd = epoll_create(1);
|
||||
if (epfd < 0)
|
||||
return -errno;
|
||||
|
||||
if (!name) {
|
||||
struct snd_card_iterator iter;
|
||||
|
@ -170,9 +253,18 @@ int monitor(const char *name)
|
|||
show_cards = 0;
|
||||
}
|
||||
|
||||
err = run_dispatcher(ctls, ncards, show_cards);
|
||||
error:
|
||||
for (i = 0; i < ncards; i++)
|
||||
snd_ctl_close(ctls[i]);
|
||||
err = prepare_dispatcher(epfd, ctls, ncards);
|
||||
if (err >= 0)
|
||||
err = run_dispatcher(epfd, ncards, show_cards);
|
||||
clear_dispatcher(epfd, ctls, ncards);
|
||||
|
||||
error:
|
||||
for (i = 0; i < ncards; i++) {
|
||||
if (ctls[i])
|
||||
snd_ctl_close(ctls[i]);
|
||||
}
|
||||
|
||||
close(epfd);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue