mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-31 22:25:35 -04:00
Add external shared object support
- Add external shared object support - Add poll_* internal ops - Allow multiple poll_fds
This commit is contained in:
parent
3c144ca078
commit
36f715c59a
3 changed files with 96 additions and 11 deletions
|
|
@ -163,6 +163,10 @@ int snd_ctl_async(snd_ctl_t *ctl, int sig, pid_t pid)
|
||||||
int snd_ctl_poll_descriptors_count(snd_ctl_t *ctl)
|
int snd_ctl_poll_descriptors_count(snd_ctl_t *ctl)
|
||||||
{
|
{
|
||||||
assert(ctl);
|
assert(ctl);
|
||||||
|
if (ctl->ops->poll_descriptors_count)
|
||||||
|
return ctl->ops->poll_descriptors_count(ctl);
|
||||||
|
if (ctl->poll_fd < 0)
|
||||||
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,6 +180,10 @@ int snd_ctl_poll_descriptors_count(snd_ctl_t *ctl)
|
||||||
int snd_ctl_poll_descriptors(snd_ctl_t *ctl, struct pollfd *pfds, unsigned int space)
|
int snd_ctl_poll_descriptors(snd_ctl_t *ctl, struct pollfd *pfds, unsigned int space)
|
||||||
{
|
{
|
||||||
assert(ctl && pfds);
|
assert(ctl && pfds);
|
||||||
|
if (ctl->ops->poll_descriptors)
|
||||||
|
return ctl->ops->poll_descriptors(ctl, pfds, space);
|
||||||
|
if (ctl->poll_fd < 0)
|
||||||
|
return 0;
|
||||||
if (space > 0) {
|
if (space > 0) {
|
||||||
pfds->fd = ctl->poll_fd;
|
pfds->fd = ctl->poll_fd;
|
||||||
pfds->events = POLLIN|POLLERR|POLLNVAL;
|
pfds->events = POLLIN|POLLERR|POLLNVAL;
|
||||||
|
|
@ -195,6 +203,8 @@ int snd_ctl_poll_descriptors(snd_ctl_t *ctl, struct pollfd *pfds, unsigned int s
|
||||||
int snd_ctl_poll_descriptors_revents(snd_ctl_t *ctl, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
|
int snd_ctl_poll_descriptors_revents(snd_ctl_t *ctl, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
|
||||||
{
|
{
|
||||||
assert(ctl && pfds && revents);
|
assert(ctl && pfds && revents);
|
||||||
|
if (ctl->ops->poll_revents)
|
||||||
|
return ctl->ops->poll_revents(ctl, pfds, nfds, revents);
|
||||||
if (nfds == 1) {
|
if (nfds == 1) {
|
||||||
*revents = pfds->revents;
|
*revents = pfds->revents;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -571,14 +581,44 @@ int snd_ctl_read(snd_ctl_t *ctl, snd_ctl_event_t *event)
|
||||||
*/
|
*/
|
||||||
int snd_ctl_wait(snd_ctl_t *ctl, int timeout)
|
int snd_ctl_wait(snd_ctl_t *ctl, int timeout)
|
||||||
{
|
{
|
||||||
struct pollfd pfd;
|
struct pollfd *pfd;
|
||||||
int err;
|
unsigned short *revents;
|
||||||
err = snd_ctl_poll_descriptors(ctl, &pfd, 1);
|
int i, npfds, pollio, err, err_poll;
|
||||||
assert(err == 1);
|
|
||||||
err = poll(&pfd, 1, timeout);
|
npfds = snd_ctl_poll_descriptors_count(ctl);
|
||||||
|
if (npfds <= 0 || npfds >= 16) {
|
||||||
|
SNDERR("Invalid poll_fds %d\n", npfds);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
pfd = alloca(sizeof(*pfd) * npfds);
|
||||||
|
revents = alloca(sizeof(*revents) * npfds);
|
||||||
|
err = snd_ctl_poll_descriptors(ctl, pfd, npfds);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return -errno;
|
return err;
|
||||||
return 0;
|
if (err != npfds) {
|
||||||
|
SNDMSG("invalid poll descriptors %d\n", err);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
err_poll = poll(pfd, npfds, timeout);
|
||||||
|
if (err_poll < 0)
|
||||||
|
return -errno;
|
||||||
|
if (! err_poll)
|
||||||
|
break;
|
||||||
|
err = snd_ctl_poll_descriptors_revents(ctl, pfd, npfds, revents);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
pollio = 0;
|
||||||
|
for (i = 0; i < npfds; i++) {
|
||||||
|
if (revents[i] & (POLLERR | POLLNVAL))
|
||||||
|
return -EIO;
|
||||||
|
if ((revents[i] & (POLLIN | POLLOUT)) == 0)
|
||||||
|
continue;
|
||||||
|
pollio++;
|
||||||
|
}
|
||||||
|
} while (! pollio);
|
||||||
|
|
||||||
|
return err_poll > 0 ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -625,11 +665,15 @@ snd_ctl_t *snd_async_handler_get_ctl(snd_async_handler_t *handler)
|
||||||
return handler->u.ctl;
|
return handler->u.ctl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *build_in_ctls[] = {
|
||||||
|
"hw", "shm", NULL
|
||||||
|
};
|
||||||
|
|
||||||
static int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name,
|
static int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name,
|
||||||
snd_config_t *ctl_root, snd_config_t *ctl_conf, int mode)
|
snd_config_t *ctl_root, snd_config_t *ctl_conf, int mode)
|
||||||
{
|
{
|
||||||
const char *str;
|
const char *str;
|
||||||
char buf[256];
|
char *buf = NULL, *buf1 = NULL;
|
||||||
int err;
|
int err;
|
||||||
snd_config_t *conf, *type_conf = NULL;
|
snd_config_t *conf, *type_conf = NULL;
|
||||||
snd_config_iterator_t i, next;
|
snd_config_iterator_t i, next;
|
||||||
|
|
@ -697,12 +741,39 @@ static int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!open_name) {
|
if (!open_name) {
|
||||||
|
buf = malloc(strlen(str) + 32);
|
||||||
|
if (buf == NULL) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
open_name = buf;
|
open_name = buf;
|
||||||
snprintf(buf, sizeof(buf), "_snd_ctl_%s_open", str);
|
sprintf(buf, "_snd_ctl_%s_open", str);
|
||||||
|
}
|
||||||
|
if (!lib) {
|
||||||
|
const char **build_in = build_in_ctls;
|
||||||
|
while (*build_in) {
|
||||||
|
if (!strcmp(*build_in, str))
|
||||||
|
break;
|
||||||
|
build_in++;
|
||||||
|
}
|
||||||
|
if (*build_in == NULL) {
|
||||||
|
buf1 = malloc(strlen(str) + sizeof(PKGLIBDIR) + 32);
|
||||||
|
if (buf1 == NULL) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
|
lib = buf1;
|
||||||
|
sprintf(buf1, "%s/libasound_module_ctl_%s.so", PKGLIBDIR, str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#ifndef PIC
|
#ifndef PIC
|
||||||
snd_control_open_symbols();
|
snd_control_open_symbols();
|
||||||
#endif
|
#endif
|
||||||
|
open_func = snd_dlobj_cache_lookup(open_name);
|
||||||
|
if (open_func) {
|
||||||
|
err = 0;
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
h = snd_dlopen(lib, RTLD_NOW);
|
h = snd_dlopen(lib, RTLD_NOW);
|
||||||
if (h)
|
if (h)
|
||||||
open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_CONTROL_DLSYM_VERSION));
|
open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_CONTROL_DLSYM_VERSION));
|
||||||
|
|
@ -721,12 +792,19 @@ static int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name,
|
||||||
if (err >= 0) {
|
if (err >= 0) {
|
||||||
err = open_func(ctlp, name, ctl_root, ctl_conf, mode);
|
err = open_func(ctlp, name, ctl_root, ctl_conf, mode);
|
||||||
if (err >= 0) {
|
if (err >= 0) {
|
||||||
|
if (h /*&& (mode & SND_CTL_KEEP_ALIVE)*/) {
|
||||||
|
snd_dlobj_cache_add(open_name, h, open_func);
|
||||||
|
h = NULL;
|
||||||
|
}
|
||||||
(*ctlp)->dl_handle = h;
|
(*ctlp)->dl_handle = h;
|
||||||
return 0;
|
err = 0;
|
||||||
} else {
|
} else {
|
||||||
snd_dlclose(h);
|
if (h)
|
||||||
|
snd_dlclose(h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
free(buf);
|
||||||
|
free(buf1);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,9 @@ typedef struct _snd_ctl_ops {
|
||||||
int (*set_power_state)(snd_ctl_t *handle, unsigned int state);
|
int (*set_power_state)(snd_ctl_t *handle, unsigned int state);
|
||||||
int (*get_power_state)(snd_ctl_t *handle, unsigned int *state);
|
int (*get_power_state)(snd_ctl_t *handle, unsigned int *state);
|
||||||
int (*read)(snd_ctl_t *handle, snd_ctl_event_t *event);
|
int (*read)(snd_ctl_t *handle, snd_ctl_event_t *event);
|
||||||
|
int (*poll_descriptors_count)(snd_ctl_t *handle);
|
||||||
|
int (*poll_descriptors)(snd_ctl_t *handle, struct pollfd *pfds, unsigned int space);
|
||||||
|
int (*poll_revents)(snd_ctl_t *handle, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
|
||||||
} snd_ctl_ops_t;
|
} snd_ctl_ops_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -665,6 +665,10 @@ int snd_hctl_wait(snd_hctl_t *hctl, int timeout)
|
||||||
struct pollfd pfd;
|
struct pollfd pfd;
|
||||||
int err;
|
int err;
|
||||||
err = snd_hctl_poll_descriptors(hctl, &pfd, 1);
|
err = snd_hctl_poll_descriptors(hctl, &pfd, 1);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
if (! err)
|
||||||
|
return 0;
|
||||||
assert(err == 1);
|
assert(err == 1);
|
||||||
err = poll(&pfd, 1, timeout);
|
err = poll(&pfd, 1, timeout);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue