mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-11-10 06:05:43 +01:00
alsactl: add event filter and cache for the daemon mode
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
parent
067f4f3256
commit
ffaff06849
2 changed files with 132 additions and 7 deletions
|
@ -189,7 +189,6 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
short_option[k] = '\0';
|
short_option[k] = '\0';
|
||||||
command = argv[0];
|
command = argv[0];
|
||||||
printf("short_option = '%s'\n", short_option);
|
|
||||||
while (1) {
|
while (1) {
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
|
|
136
alsactl/daemon.c
136
alsactl/daemon.c
|
@ -32,10 +32,17 @@
|
||||||
#include <alsa/asoundlib.h>
|
#include <alsa/asoundlib.h>
|
||||||
#include "alsactl.h"
|
#include "alsactl.h"
|
||||||
|
|
||||||
|
struct id_list {
|
||||||
|
snd_ctl_elem_id_t **list;
|
||||||
|
int size;
|
||||||
|
};
|
||||||
|
|
||||||
struct card {
|
struct card {
|
||||||
int index;
|
int index;
|
||||||
int pfds;
|
int pfds;
|
||||||
snd_ctl_t *handle;
|
snd_ctl_t *handle;
|
||||||
|
struct id_list whitelist;
|
||||||
|
struct id_list blacklist;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int quit = 0;
|
static int quit = 0;
|
||||||
|
@ -60,9 +67,21 @@ static void signal_handler_rescan(int sig)
|
||||||
signal(sig, signal_handler_rescan);
|
signal(sig, signal_handler_rescan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void free_list(struct id_list *list)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < list->size; i++)
|
||||||
|
free(list->list[i]);
|
||||||
|
free(list->list);
|
||||||
|
}
|
||||||
|
|
||||||
static void card_free(struct card **card)
|
static void card_free(struct card **card)
|
||||||
{
|
{
|
||||||
struct card *c = *card;
|
struct card *c = *card;
|
||||||
|
|
||||||
|
free_list(&c->blacklist);
|
||||||
|
free_list(&c->whitelist);
|
||||||
if (c->handle)
|
if (c->handle)
|
||||||
snd_ctl_close(c->handle);
|
snd_ctl_close(c->handle);
|
||||||
free(c);
|
free(c);
|
||||||
|
@ -135,18 +154,125 @@ static void add_cards(struct card ***cards, int *count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int card_events(struct card *card)
|
static int compare_ids(snd_ctl_elem_id_t *id1, snd_ctl_elem_id_t *id2)
|
||||||
|
{
|
||||||
|
if (id1 == NULL || id2 == NULL)
|
||||||
|
return 0;
|
||||||
|
return snd_ctl_elem_id_get_interface(id1) == snd_ctl_elem_id_get_interface(id2) &&
|
||||||
|
snd_ctl_elem_id_get_index(id1) == snd_ctl_elem_id_get_index(id2) &&
|
||||||
|
strcmp(snd_ctl_elem_id_get_name(id1), snd_ctl_elem_id_get_name(id2)) == 0 &&
|
||||||
|
snd_ctl_elem_id_get_device(id1) == snd_ctl_elem_id_get_device(id2) &&
|
||||||
|
snd_ctl_elem_id_get_subdevice(id1) == snd_ctl_elem_id_get_subdevice(id2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int in_list(struct id_list *list, snd_ctl_elem_id_t *id)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
snd_ctl_elem_id_t *id1;
|
||||||
|
|
||||||
|
for (i = 0; i < list->size; i++) {
|
||||||
|
id1 = list->list[i];
|
||||||
|
if (id1 == NULL)
|
||||||
|
continue;
|
||||||
|
if (compare_ids(id, id1))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_from_list(struct id_list *list, snd_ctl_elem_id_t *id)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < list->size; i++) {
|
||||||
|
if (compare_ids(id, list->list[i])) {
|
||||||
|
free(list->list[i]);
|
||||||
|
list->list[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_to_list(struct id_list *list, snd_ctl_elem_id_t *id)
|
||||||
|
{
|
||||||
|
snd_ctl_elem_id_t *id1;
|
||||||
|
snd_ctl_elem_id_t **n;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (snd_ctl_elem_id_malloc(&id1))
|
||||||
|
return;
|
||||||
|
snd_ctl_elem_id_copy(id1, id);
|
||||||
|
for (i = 0; i < list->size; i++) {
|
||||||
|
if (list->list[i] == NULL) {
|
||||||
|
list->list[i] = id1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n = realloc(list->list, sizeof(void *) * (list->size + 1));
|
||||||
|
if (n == NULL)
|
||||||
|
return;
|
||||||
|
n[list->size] = id1;
|
||||||
|
list->size++;
|
||||||
|
list->list = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_lists(struct card *card, snd_ctl_elem_id_t *id)
|
||||||
|
{
|
||||||
|
snd_ctl_elem_info_t *info;
|
||||||
|
snd_ctl_elem_info_alloca(&info);
|
||||||
|
|
||||||
|
if (in_list(&card->blacklist, id))
|
||||||
|
return 0;
|
||||||
|
if (in_list(&card->whitelist, id))
|
||||||
|
return 1;
|
||||||
|
snd_ctl_elem_info_set_id(info, id);
|
||||||
|
if (snd_ctl_elem_info(card->handle, info) < 0)
|
||||||
|
return 0;
|
||||||
|
if (snd_ctl_elem_info_is_writable(info) ||
|
||||||
|
snd_ctl_elem_info_is_tlv_writable(info)) {
|
||||||
|
add_to_list(&card->whitelist, id);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
add_to_list(&card->blacklist, id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int card_events(struct card *card)
|
||||||
{
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
snd_ctl_event_t *ev;
|
snd_ctl_event_t *ev;
|
||||||
|
snd_ctl_event_type_t type;
|
||||||
|
unsigned int mask;
|
||||||
|
snd_ctl_elem_id_t *id;
|
||||||
snd_ctl_event_alloca(&ev);
|
snd_ctl_event_alloca(&ev);
|
||||||
|
snd_ctl_elem_id_alloca(&id);
|
||||||
|
|
||||||
while (snd_ctl_read(card->handle, ev) == 1)
|
while (snd_ctl_read(card->handle, ev) == 1) {
|
||||||
|
type = snd_ctl_event_get_type(ev);
|
||||||
|
if (type != SND_CTL_EVENT_ELEM)
|
||||||
|
continue;
|
||||||
|
mask = snd_ctl_event_elem_get_mask(ev);
|
||||||
|
snd_ctl_event_elem_get_id(ev, id);
|
||||||
|
if (mask == SND_CTL_EVENT_MASK_REMOVE) {
|
||||||
|
remove_from_list(&card->whitelist, id);
|
||||||
|
remove_from_list(&card->blacklist, id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (mask & SND_CTL_EVENT_MASK_INFO) {
|
||||||
|
remove_from_list(&card->whitelist, id);
|
||||||
|
remove_from_list(&card->blacklist, id);
|
||||||
|
}
|
||||||
|
if (mask & (SND_CTL_EVENT_MASK_VALUE|
|
||||||
|
SND_CTL_EVENT_MASK_ADD|
|
||||||
|
SND_CTL_EVENT_MASK_TLV)) {
|
||||||
|
if (check_lists(card, id))
|
||||||
res = 1;
|
res = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
long read_pid_file(const char *pidfile)
|
static long read_pid_file(const char *pidfile)
|
||||||
{
|
{
|
||||||
int fd, err;
|
int fd, err;
|
||||||
char pid_txt[12];
|
char pid_txt[12];
|
||||||
|
@ -164,7 +290,7 @@ long read_pid_file(const char *pidfile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int write_pid_file(const char *pidfile)
|
static int write_pid_file(const char *pidfile)
|
||||||
{
|
{
|
||||||
int fd, err;
|
int fd, err;
|
||||||
char pid_txt[12];
|
char pid_txt[12];
|
||||||
|
@ -214,7 +340,7 @@ int state_daemon_kill(const char *pidfile, const char *cmd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int check_another_instance(const char *pidfile)
|
static int check_another_instance(const char *pidfile)
|
||||||
{
|
{
|
||||||
long pid;
|
long pid;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue