]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Add external shared object support
authorTakashi Iwai <tiwai@suse.de>
Thu, 9 Jun 2005 17:09:24 +0000 (17:09 +0000)
committerTakashi Iwai <tiwai@suse.de>
Thu, 9 Jun 2005 17:09:24 +0000 (17:09 +0000)
- Add external shared object support
- Add poll_* internal ops
- Allow multiple poll_fds

src/control/control.c
src/control/control_local.h
src/control/hcontrol.c

index 06ee4d2100f1f9bd5eacbb8748ff4ce6612f7018..4e1d4435bb9bf73ca22db9e43d6c4bc1036995b8 100644 (file)
@@ -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;
 }
 
index 0c38db48c53ef9781dcb656f563c52c4c76442e7..ce7bb8373a05fde6ed4a0e2255d182cda786727c 100644 (file)
@@ -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;
 
 
index ea3f2ab3792eae61c178a5cd06a9482f539e8c32..be28d3e074eccaef9617b553aba2991a87b894de 100644 (file)
@@ -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)