From: Takashi Iwai Date: Thu, 9 Jun 2005 17:09:24 +0000 (+0000) Subject: Add external shared object support X-Git-Tag: v1.0.10rc1~33 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=36f715c59a803f5be61440924628589fbf4bd02f;p=alsa-lib.git Add external shared object support - Add external shared object support - Add poll_* internal ops - Allow multiple poll_fds --- diff --git a/src/control/control.c b/src/control/control.c index 06ee4d21..4e1d4435 100644 --- a/src/control/control.c +++ b/src/control/control.c @@ -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) { assert(ctl); + if (ctl->ops->poll_descriptors_count) + return ctl->ops->poll_descriptors_count(ctl); + if (ctl->poll_fd < 0) + return 0; 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) { 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) { pfds->fd = ctl->poll_fd; 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) { assert(ctl && pfds && revents); + if (ctl->ops->poll_revents) + return ctl->ops->poll_revents(ctl, pfds, nfds, revents); if (nfds == 1) { *revents = pfds->revents; 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) { - struct pollfd pfd; - int err; - err = snd_ctl_poll_descriptors(ctl, &pfd, 1); - assert(err == 1); - err = poll(&pfd, 1, timeout); + struct pollfd *pfd; + unsigned short *revents; + int i, npfds, pollio, err, err_poll; + + 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) - return -errno; - return 0; + return err; + 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; } +static const char *build_in_ctls[] = { + "hw", "shm", NULL +}; + 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) { const char *str; - char buf[256]; + char *buf = NULL, *buf1 = NULL; int err; snd_config_t *conf, *type_conf = NULL; 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) { + buf = malloc(strlen(str) + 32); + if (buf == NULL) { + err = -ENOMEM; + goto _err; + } 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 snd_control_open_symbols(); #endif + open_func = snd_dlobj_cache_lookup(open_name); + if (open_func) { + err = 0; + goto _err; + } h = snd_dlopen(lib, RTLD_NOW); if (h) 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) { err = open_func(ctlp, name, ctl_root, ctl_conf, mode); 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; - return 0; + err = 0; } else { - snd_dlclose(h); + if (h) + snd_dlclose(h); } } + free(buf); + free(buf1); return err; } diff --git a/src/control/control_local.h b/src/control/control_local.h index 0c38db48..ce7bb837 100644 --- a/src/control/control_local.h +++ b/src/control/control_local.h @@ -47,6 +47,9 @@ typedef struct _snd_ctl_ops { int (*set_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 (*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; diff --git a/src/control/hcontrol.c b/src/control/hcontrol.c index ea3f2ab3..be28d3e0 100644 --- a/src/control/hcontrol.c +++ b/src/control/hcontrol.c @@ -665,6 +665,10 @@ int snd_hctl_wait(snd_hctl_t *hctl, int timeout) struct pollfd pfd; int err; err = snd_hctl_poll_descriptors(hctl, &pfd, 1); + if (err < 0) + return err; + if (! err) + return 0; assert(err == 1); err = poll(&pfd, 1, timeout); if (err < 0)