]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Added abstraction layer to controls. Added client/server support to controls. Cleaned...
authorAbramo Bagnara <abramo@alsa-project.org>
Mon, 11 Sep 2000 15:49:10 +0000 (15:49 +0000)
committerAbramo Bagnara <abramo@alsa-project.org>
Mon, 11 Sep 2000 15:49:10 +0000 (15:49 +0000)
18 files changed:
TODO
include/aserver.h
include/control.h
include/mixer.h
src/aserver/aserver.c
src/control/Makefile.am
src/control/cards.c
src/control/control.c
src/control/control_client.c [new file with mode: 0644]
src/control/control_hw.c [new file with mode: 0644]
src/control/control_local.h
src/mixer/mixer.c
src/pcm/pcm.c
src/pcm/pcm_client.c
src/pcm/pcm_hw.c
src/pcm/pcm_local.h
src/pcm/pcm_multi.c
src/pcm/pcm_plug.c

diff --git a/TODO b/TODO
index 5a776fa4a7bbd9df18b8c7548522c14e5df781e0..99b877390c85bfaee54c43586388ef3790c91968 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,5 +1,4 @@
-M add abstraction layer to control, timer, rawmidi, hwdep, seq
+M add abstraction layer to timer, rawmidi, hwdep, seq
 M plug sync and pos problems
 M Loopback implementation?
-M change callback argument to be snd_pcm_t instead of void *
 L move OSS emulation to user space? (pseudo device driver and daemon)
index 7c477fa3163dc56f0932d03e24265f1263ef3769..0094b2da9dc6e2ef3032dcb53e79f465c934a210 100644 (file)
@@ -54,6 +54,30 @@ typedef struct {
 #define PCM_SHM_SIZE 65536
 #define PCM_SHM_DATA_MAXLEN (PCM_SHM_SIZE - offsetof(snd_pcm_client_shm_t, data))
                
+#define SND_CTL_IOCTL_READ             _IOR('U', 0xf0, snd_ctl_event_t)
+#define SND_CTL_IOCTL_CLOSE            _IO ('U', 0xf1)
+
+typedef struct {
+       int result;
+       int cmd;
+       union {
+               snd_ctl_hw_info_t hw_info;
+               snd_control_list_t clist;
+               snd_control_info_t cinfo;
+               snd_control_t cread;
+               snd_control_t cwrite;
+               snd_hwdep_info_t hwdep_info;
+               snd_pcm_info_t pcm_info;
+               int pcm_prefer_subdevice;
+               snd_rawmidi_info_t rawmidi_info;
+               snd_ctl_event_t read;
+       } u;
+       char data[0];
+} snd_ctl_client_shm_t;
+
+#define CTL_SHM_SIZE 65536
+#define CTL_SHM_DATA_MAXLEN (CTL_SHM_SIZE - offsetof(snd_ctl_client_shm_t, data))
+
 typedef struct {
        unsigned char dev_type;
        unsigned char transport_type;
@@ -68,10 +92,3 @@ typedef struct {
        int cookie;
 } snd_client_open_answer_t;
 
-struct cmsg_fd
-{
-    int len;   /* sizeof structure */
-    int level; /* SOL_SOCKET */
-    int type;  /* SCM_RIGHTS */
-    int fd;    /* fd to pass */
-};
index 446b4fc432a0514f78be284086274f266459b5a9..f68b5ac0ee7c6297b3eaa920e485bd0d4df0f49c 100644 (file)
@@ -7,6 +7,8 @@
 
 typedef struct snd_ctl snd_ctl_t;
 
+typedef enum { SND_CTL_TYPE_HW, SND_CTL_TYPE_CLIENT } snd_ctl_type_t;
+
 typedef struct snd_ctl_callbacks {
        void *private_data;     /* may be used by an application */
        void (*rebuild) (snd_ctl_t *handle, void *private_data);
@@ -35,7 +37,10 @@ int snd_defaults_pcm_device(void);
 int snd_defaults_rawmidi_card(void);
 int snd_defaults_rawmidi_device(void);
 
-int snd_ctl_open(snd_ctl_t **handle, int card);
+int snd_ctl_hw_open(snd_ctl_t **handle, int card);
+int snd_ctl_client_open(snd_ctl_t **handlep, char *host, int port, int transport, char *name);
+snd_ctl_type_t snd_ctl_type(snd_ctl_t *handle);
+int snd_ctl_open(snd_ctl_t **handle, char *name);
 int snd_ctl_close(snd_ctl_t *handle);
 int snd_ctl_file_descriptor(snd_ctl_t *handle);
 int snd_ctl_hw_info(snd_ctl_t *handle, snd_ctl_hw_info_t *info);
index e224ecdb2a0d532daa5c165007aba45f051ac75b..1daef64e97cbb242b40f65d1abd4ca88136aa0cc 100644 (file)
@@ -11,7 +11,7 @@ typedef struct snd_mixer snd_mixer_t;
 extern "C" {
 #endif
 
-int snd_mixer_open(snd_mixer_t **handle, int card);
+int snd_mixer_open(snd_mixer_t **handle, char *name);
 int snd_mixer_close(snd_mixer_t *handle);
 int snd_mixer_file_descriptor(snd_mixer_t *handle);
 
index f4234ab021f52f37de5e08ad4fa2b01a87bef074..362441cbdf81e4bfa2225b9cc8977656b33ec0b5 100644 (file)
@@ -35,6 +35,7 @@
 #include "asoundlib.h"
 #include "pcm_local.h"
 #include "aserver.h"
+#include "list.h"
 
 char *command;
 
@@ -140,20 +141,66 @@ int send_fd(int socket, void *data, size_t len, int fd)
     return ret;
 }
 
+struct pollfd pollfds[OPEN_MAX];
+unsigned int pollfds_count = 0;
+typedef struct waiter waiter_t;
+typedef int (*waiter_handler_t)(waiter_t *waiter, unsigned short events);
+struct waiter {
+       int fd;
+       void *private_data;
+       waiter_handler_t handler;
+};
+waiter_t waiters[OPEN_MAX];
+
+void add_waiter(int fd, unsigned short events, waiter_handler_t handler,
+               void *data)
+{
+       waiter_t *w = &waiters[fd];
+       struct pollfd *pfd = &pollfds[pollfds_count];
+       assert(!w->handler);
+       pfd->fd = fd;
+       pfd->events = events;
+       pfd->revents = 0;
+       w->fd = fd;
+       w->private_data = data;
+       w->handler = handler;
+       pollfds_count++;
+}
+
+void del_waiter(int fd)
+{
+       waiter_t *w = &waiters[fd];
+       unsigned int k;
+       assert(w->handler);
+       w->handler = 0;
+       for (k = 0; k < pollfds_count; ++k) {
+               if (pollfds[k].fd == fd)
+                       break;
+       }
+       assert(k < pollfds_count);
+       pollfds_count--;
+       memmove(&pollfds[k], &pollfds[k + 1], pollfds_count - k);
+}
+
+typedef struct {
+       struct list_head list;
+       int fd;
+       int local;
+} master_t;
+LIST_HEAD(masters);
+
 typedef struct client client_t;
 
 typedef struct {
        int (*open)(client_t *client, int *cookie);
        int (*cmd)(client_t *client);
        int (*close)(client_t *client);
-       int (*poll_prepare)(client_t *client, struct pollfd *pfds, int pindex);
-       void (*poll_events)(client_t *client, struct pollfd *pfds);
 } transport_ops_t;
 
 struct client {
+       struct list_head list;
        struct socket {
                int fd;
-               int pindex;
                int local;
        } data, ctrl;
        int transport_type;
@@ -166,12 +213,12 @@ struct client {
                struct {
                        snd_pcm_t *handle;
                        int fd;
-                       int pindex;
                } pcm;
-#if 0
                struct {
                        snd_ctl_t *handle;
+                       int fd;
                } control;
+#if 0
                struct {
                        snd_rawmidi_t *handle;
                } rawmidi;
@@ -186,7 +233,8 @@ struct client {
                } seq;
 #endif
        } device;
-       enum { CLOSED = 0, STOPPED, NORMAL, UNKNOWN } state;
+       int polling;
+       int open;
        int cookie;
        union {
                struct {
@@ -196,11 +244,38 @@ struct client {
        } transport;
 };
 
-#define PENDINGS_MAX 4
-#define CLIENTS_MAX 2
+LIST_HEAD(clients);
 
-client_t clients[CLIENTS_MAX];
-int clients_count = 0;
+typedef struct {
+       struct list_head list;
+       int fd;
+       uint32_t cookie;
+       int local;
+} pending_t;
+LIST_HEAD(pendings);
+
+int pcm_handler(waiter_t *waiter, unsigned short events)
+{
+       client_t *client = waiter->private_data;
+       char buf[1];
+       ssize_t n;
+       if (events & POLLIN) {
+               n = write(client->data.fd, buf, 1);
+               if (n != 1) {
+                       perrno("write");
+                       return -errno;
+               }
+       } else if (events & POLLOUT) {
+               n = read(client->data.fd, buf, 1);
+               if (n != 1) {
+                       perrno("read");
+                       return -errno;
+               }
+       }
+       del_waiter(waiter->fd);
+       client->polling = 0;
+       return 0;
+}
 
 int pcm_shm_open(client_t *client, int *cookie)
 {
@@ -241,6 +316,10 @@ int pcm_shm_close(client_t *client)
 {
        int err;
        snd_pcm_client_shm_t *ctrl = client->transport.shm.ctrl;
+       if (client->polling) {
+               del_waiter(client->device.pcm.fd);
+               client->polling = 0;
+       }
        /* FIXME: blocking */
        err = snd_pcm_close(client->device.pcm.handle);
        ctrl->result = err;
@@ -255,53 +334,10 @@ int pcm_shm_close(client_t *client)
                        perrno("shmctl");
                client->transport.shm.ctrl = 0;
        }
-       client->state = CLOSED;
+       client->open = 0;
        return 0;
 }
 
-int pcm_poll_prepare(client_t *client, struct pollfd *pfds, int pindex)
-{
-       struct pollfd *pfd = &pfds[pindex];
-       pfd->events = 0;
-       switch (client->state) {
-       case UNKNOWN:
-               pfd->events = client->stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN;
-       case NORMAL:
-               pfd->fd = client->device.pcm.fd;
-               client->device.pcm.pindex = pindex;
-               return 1;
-               break;
-       default:
-               client->device.pcm.pindex = -1;
-               return 0;
-       }
-}
-
-void pcm_poll_events(client_t *client, struct pollfd *pfds)
-{
-       int n;
-       char zero = 0;
-       struct pollfd *pfd;
-       if (client->device.pcm.pindex < 0)
-               return;
-       pfd = &pfds[client->device.pcm.pindex];
-       if (pfd->revents & POLLIN) {
-               client->state = NORMAL;
-               n = write(client->data.fd, &zero, 1);
-               if (n != 1) {
-                       perrno("write");
-                       exit(1);
-               }
-       } else if (pfd->revents & POLLOUT) {
-               client->state = NORMAL;
-               n = read(client->data.fd, &zero, 1);
-               if (n != 1) {
-                       perrno("read");
-                       exit(1);
-               }
-       }
-}
-
 int pcm_shm_cmd(client_t *client)
 {
        snd_pcm_client_shm_t *ctrl = client->transport.shm.ctrl;
@@ -362,7 +398,6 @@ int pcm_shm_cmd(client_t *client)
        case SND_PCM_IOCTL_WRITE_FRAMES:
        {
                size_t maxsize = PCM_SHM_DATA_MAXLEN;
-               client->state = UNKNOWN;
                maxsize = snd_pcm_bytes_to_frames(pcm, maxsize);
                if (ctrl->u.write.count > maxsize) {
                        ctrl->result = -EFAULT;
@@ -375,7 +410,6 @@ int pcm_shm_cmd(client_t *client)
        case SND_PCM_IOCTL_READ_FRAMES:
        {
                size_t maxsize = PCM_SHM_DATA_MAXLEN;
-               client->state = UNKNOWN;
                maxsize = snd_pcm_bytes_to_frames(pcm, maxsize);
                if (ctrl->u.read.count > maxsize) {
                        ctrl->result = -EFAULT;
@@ -394,7 +428,6 @@ int pcm_shm_cmd(client_t *client)
                size_t vecsize;
                char *base;
                int bits_per_sample = snd_pcm_samples_to_bytes(pcm, 8);
-               client->state = UNKNOWN;
                vecsize = ctrl->u.writev.count * sizeof(struct iovec);
                if (vecsize > maxsize) {
                        ctrl->result = -EFAULT;
@@ -423,7 +456,6 @@ int pcm_shm_cmd(client_t *client)
                size_t vecsize;
                char *base;
                int bits_per_sample = snd_pcm_samples_to_bytes(pcm, 8);
-               client->state = UNKNOWN;
                vecsize = ctrl->u.readv.count * sizeof(struct iovec);
                if (vecsize > maxsize) {
                        ctrl->result = -EFAULT;
@@ -444,17 +476,17 @@ int pcm_shm_cmd(client_t *client)
                break;
        }
        case SND_PCM_IOCTL_FRAME_DATA:
-               client->state = UNKNOWN;
                ctrl->result = snd_pcm_frame_data(pcm, ctrl->u.frame_data);
                break;
        case SND_PCM_IOCTL_LINK:
        {
-               int k;
-               for (k = 0; k < clients_count; ++k) {
-                       if (clients[k].state == CLOSED)
+               struct list_head *item;
+               list_for_each(item, &clients) {
+                       client_t *client = list_entry(item, client_t, list);
+                       if (!client->open)
                                continue;
-                       if (clients[k].data.fd == ctrl->u.link) {
-                               ctrl->result = snd_pcm_link(pcm, clients[k].device.pcm.handle);
+                       if (client->data.fd == ctrl->u.link) {
+                               ctrl->result = snd_pcm_link(pcm, client->device.pcm.handle);
                                break;
                        }
                }
@@ -484,7 +516,6 @@ int pcm_shm_cmd(client_t *client)
        case SND_PCM_IOCTL_MUNMAP_STATUS:
                ctrl->result = 0;
                break;
-       }
 #endif
        case SND_PCM_IOCTL_CLOSE:
                client->ops->close(client);
@@ -500,6 +531,10 @@ int pcm_shm_cmd(client_t *client)
        err = write(client->ctrl.fd, buf, 1);
        if (err != 1)
                return -EBADFD;
+       if (!client->polling) {
+               add_waiter(client->device.pcm.fd, POLLIN | POLLOUT, pcm_handler, client);
+               client->polling = 1;
+       }
        return 0;
 }
 
@@ -507,11 +542,171 @@ transport_ops_t pcm_shm_ops = {
        open: pcm_shm_open,
        cmd: pcm_shm_cmd,
        close: pcm_shm_close,
-       poll_prepare: pcm_poll_prepare,
-       poll_events: pcm_poll_events,
 };
 
-void snd_client_open(client_t *client)
+int ctl_handler(waiter_t *waiter, unsigned short events)
+{
+       client_t *client = waiter->private_data;
+       char buf[1];
+       ssize_t n;
+       if (events & POLLIN) {
+               n = write(client->data.fd, buf, 1);
+               if (n != 1) {
+                       perrno("write");
+                       return -errno;
+               }
+       }
+       del_waiter(waiter->fd);
+       client->polling = 0;
+       return 0;
+}
+
+int ctl_shm_open(client_t *client, int *cookie)
+{
+       int shmid;
+       snd_ctl_t *ctl;
+       int err;
+       int result;
+       err = snd_ctl_open(&ctl, client->name);
+       if (err < 0)
+               return err;
+       client->device.control.handle = ctl;
+       client->device.control.fd = snd_ctl_file_descriptor(ctl);
+
+       shmid = shmget(IPC_PRIVATE, CTL_SHM_SIZE, 0666);
+       if (shmid < 0) {
+               result = -errno;
+               perrno("shmget");
+               goto _err;
+       }
+       client->transport.shm.ctrl_id = shmid;
+       client->transport.shm.ctrl = shmat(shmid, 0, 0);
+       if (!client->transport.shm.ctrl) {
+               result = -errno;
+               shmctl(shmid, IPC_RMID, 0);
+               perrno("shmat");
+               goto _err;
+       }
+       *cookie = shmid;
+       add_waiter(client->device.control.fd, POLLIN, ctl_handler, client);
+       client->polling = 1;
+       return 0;
+
+ _err:
+       snd_ctl_close(ctl);
+       return result;
+
+}
+
+int ctl_shm_close(client_t *client)
+{
+       int err;
+       snd_ctl_client_shm_t *ctrl = client->transport.shm.ctrl;
+       if (client->polling) {
+               del_waiter(client->device.control.fd);
+               client->polling = 0;
+       }
+       /* FIXME: blocking */
+       err = snd_ctl_close(client->device.control.handle);
+       ctrl->result = err;
+       if (err < 0) 
+               perrno("snd_ctl_close");
+       if (client->transport.shm.ctrl) {
+               err = shmdt((void *)client->transport.shm.ctrl);
+               if (err < 0)
+                       perrno("shmdt");
+               err = shmctl(client->transport.shm.ctrl_id, IPC_RMID, 0);
+               if (err < 0)
+                       perrno("shmctl");
+               client->transport.shm.ctrl = 0;
+       }
+       client->open = 0;
+       return 0;
+}
+
+extern int snd_ctl_read1(snd_ctl_t *ctl, snd_ctl_event_t *event);
+
+int ctl_shm_cmd(client_t *client)
+{
+       snd_ctl_client_shm_t *ctrl = client->transport.shm.ctrl;
+       struct pollfd pfd;
+       char buf[1];
+       int err;
+       int cmd;
+       snd_ctl_t *ctl;
+       err = read(client->ctrl.fd, buf, 1);
+       if (err != 1)
+               return -EBADFD;
+       cmd = ctrl->cmd;
+       ctrl->cmd = 0;
+       ctl = client->device.control.handle;
+       switch (cmd) {
+       case SND_CTL_IOCTL_HW_INFO:
+               ctrl->result = snd_ctl_hw_info(ctl, &ctrl->u.hw_info);
+               break;
+       case SND_CTL_IOCTL_CONTROL_LIST:
+       {
+               size_t maxsize = CTL_SHM_DATA_MAXLEN;
+               if (ctrl->u.clist.controls_request * sizeof(*ctrl->u.clist.pids) > maxsize) {
+                       ctrl->result = -EFAULT;
+                       break;
+               }
+               ctrl->u.clist.pids = (snd_control_id_t*) ctrl->data;
+               ctrl->result = snd_ctl_clist(ctl, &ctrl->u.clist);
+               break;
+       }
+       case SND_CTL_IOCTL_CONTROL_INFO:
+               ctrl->result = snd_ctl_cinfo(ctl, &ctrl->u.cinfo);
+               break;
+       case SND_CTL_IOCTL_CONTROL_READ:
+               ctrl->result = snd_ctl_cread(ctl, &ctrl->u.cread);
+               break;
+       case SND_CTL_IOCTL_CONTROL_WRITE:
+               ctrl->result = snd_ctl_cwrite(ctl, &ctrl->u.cwrite);
+               break;
+       case SND_CTL_IOCTL_HWDEP_INFO:
+               ctrl->result = snd_ctl_hwdep_info(ctl, &ctrl->u.hwdep_info);
+               break;
+       case SND_CTL_IOCTL_PCM_INFO:
+               ctrl->result = snd_ctl_pcm_info(ctl, &ctrl->u.pcm_info);
+               break;
+       case SND_CTL_IOCTL_PCM_PREFER_SUBDEVICE:
+               ctrl->result = snd_ctl_pcm_prefer_subdevice(ctl, ctrl->u.pcm_prefer_subdevice);
+               break;
+       case SND_CTL_IOCTL_RAWMIDI_INFO:
+               ctrl->result = snd_ctl_rawmidi_info(ctl, &ctrl->u.rawmidi_info);
+               break;
+       case SND_CTL_IOCTL_READ:
+               ctrl->result = snd_ctl_read1(ctl, &ctrl->u.read);
+               break;
+       case SND_CTL_IOCTL_CLOSE:
+               client->ops->close(client);
+               break;
+       default:
+               fprintf(stderr, "Bogus cmd: %x\n", ctrl->cmd);
+               ctrl->result = -ENOSYS;
+       }
+       pfd.fd = client->ctrl.fd;
+       pfd.events = POLLHUP;
+       if (poll(&pfd, 1, 0) == 1)
+               return -EBADFD;
+       err = write(client->ctrl.fd, buf, 1);
+       if (err != 1)
+               return -EBADFD;
+       if (!client->polling) {
+               add_waiter(client->device.control.fd, POLLIN, ctl_handler, client);
+               client->polling = 1;
+       }
+       return 0;
+}
+
+transport_ops_t ctl_shm_ops = {
+       open: ctl_shm_open,
+       cmd: ctl_shm_cmd,
+       close: ctl_shm_close,
+};
+
+int snd_client_open(client_t *client)
 {
        int err;
        snd_client_open_request_t req;
@@ -549,6 +744,16 @@ void snd_client_open(client_t *client)
                        goto _answer;
                }
                break;
+       case SND_DEV_TYPE_CONTROL:
+               switch (req.transport_type) {
+               case SND_TRANSPORT_TYPE_SHM:
+                       client->ops = &ctl_shm_ops;
+                       break;
+               default:
+                       ans.result = -EINVAL;
+                       goto _answer;
+               }
+               break;
        default:
                ans.result = -EINVAL;
                goto _answer;
@@ -565,7 +770,7 @@ void snd_client_open(client_t *client)
        if (err < 0) {
                ans.result = err;
        } else {
-               client->state = STOPPED;
+               client->open = 1;
                ans.result = client->data.fd;
        }
 
@@ -575,53 +780,141 @@ void snd_client_open(client_t *client)
                perrno("write");
                exit(1);
        }
-       return;
+       return 0;
+}
+
+int client_data_handler(waiter_t *waiter, unsigned short events ATTRIBUTE_UNUSED)
+{
+       client_t *client = waiter->private_data;
+       if (client->open)
+               client->ops->close(client);
+       close(client->data.fd);
+       close(client->ctrl.fd);
+       del_waiter(client->data.fd);
+       del_waiter(client->ctrl.fd);
+       list_del(&client->list);
+       free(client);
+       return 0;
+}
+
+int client_ctrl_handler(waiter_t *waiter, unsigned short events)
+{
+       client_t *client = waiter->private_data;
+       if (events & POLLHUP)
+               return client_data_handler(waiter, events);
+       if (client->open)
+               return client->ops->cmd(client);
+       else
+               return snd_client_open(client);
+}
+
+int pending_handler(waiter_t *waiter, unsigned short events)
+{
+       pending_t *pending = waiter->private_data;
+       pending_t *pdata;
+       client_t *client;
+       uint32_t cookie;
+       struct list_head *item;
+       int remove = 0;
+       if (events & POLLHUP)
+               remove = 1;
+       else {
+               int err = read(waiter->fd, &cookie, sizeof(cookie));
+               if (err != sizeof(cookie))
+                       remove = 1;
+               else {
+                       err = write(waiter->fd, &cookie, sizeof(cookie));
+                       if (err != sizeof(cookie))
+                               remove = 1;
+               }
+       }
+       del_waiter(waiter->fd);
+       if (remove) {
+               close(waiter->fd);
+               list_del(&pending->list);
+               free(pending);
+               return 0;
+       }
+
+       list_for_each(item, &pendings) {
+               pdata = list_entry(item, pending_t, list);
+               if (pdata->cookie == cookie)
+                       goto found;
+       }
+       pending->cookie = cookie;
+       return 0;
+
+ found:
+       client = calloc(sizeof(*client), 1);
+       client->data.fd = pdata->fd;
+       client->data.local = pdata->local;
+       client->ctrl.fd = waiter->fd;
+       client->ctrl.local = pending->local;
+       add_waiter(client->ctrl.fd, POLLIN | POLLHUP, client_ctrl_handler, client);
+       add_waiter(client->data.fd, POLLHUP, client_data_handler, client);
+       client->open = 0;
+       list_add_tail(&client->list, &clients);
+       list_del(&pending->list);
+       list_del(&pdata->list);
+       free(pending);
+       free(pdata);
+       return 0;
+}
+
+int master_handler(waiter_t *waiter, unsigned short events ATTRIBUTE_UNUSED)
+{
+       master_t *master = waiter->private_data;
+       int sock;
+       sock = accept(waiter->fd, 0, 0);
+       if (sock < 0) {
+               int result = -errno;
+               perrno("accept");
+               return result;
+       } else {
+               pending_t *pending = calloc(sizeof(*pending), 1);
+               pending->fd = sock;
+               pending->local = master->local;
+               pending->cookie = 0;
+               add_waiter(sock, POLLIN, pending_handler, pending);
+               list_add_tail(&pending->list, &pendings);
+       }
+       return 0;
 }
 
 int server(char *sockname, int port)
 {
-       typedef struct {
-               int fd;
-               int pindex;
-               int local;
-       } master_t;
-       master_t masters[2];
-       int masters_count = 0;
-       typedef struct {
-               int fd;
-               int pindex;
-               uint32_t cookie;
-               int local;
-       } pending_t;
-       pending_t pendings[PENDINGS_MAX];
-       int pendings_count = 0;
-       struct pollfd pfds[CLIENTS_MAX * 3 + 16];
-       int pfds_count;
+       struct list_head *item;
        int err;
-       int k;
+       unsigned int k;
 
        if (sockname) {
-               int master = make_local_socket(sockname);
-               if (master < 0)
-                       return master;
-               masters[masters_count].fd = master;
-               masters[masters_count].local = 1;
-               masters_count++;
+               int sock = make_local_socket(sockname);
+               master_t *master;
+               if (sock < 0)
+                       return sock;
+               master = calloc(sizeof(*master), 1);
+               master->fd = sock;
+               master->local = 1;
+               add_waiter(sock, POLLIN, master_handler, master);
+               list_add_tail(&master->list, &masters);
        }
        if (port >= 0) {
-               int master = make_inet_socket(port);
-               if (master < 0)
-                       return master;
-               masters[masters_count].fd = master;
-               masters[masters_count].local = 0;
-               masters_count++;
+               int sock = make_inet_socket(port);
+               master_t *master;
+               if (sock < 0)
+                       return sock;
+               master = calloc(sizeof(*master), 1);
+               master->fd = sock;
+               master->local = 0;
+               add_waiter(sock, POLLIN, master_handler, master);
+               list_add_tail(&master->list, &masters);
        }
 
-       if (masters_count == 0)
+       if (list_empty(&masters))
                return -EINVAL;
 
-       for (k = 0; k < masters_count; ++k) {
-               master_t *master = &masters[k];
+       list_for_each(item, &masters) {
+               master_t *master = list_entry(item, master_t, list);
                if (fcntl(master->fd, F_SETFL, O_NONBLOCK) < 0) {
                        int result = -errno;
                        perrno("fcntl");
@@ -634,205 +927,30 @@ int server(char *sockname, int port)
                }
        }
 
-       for (k = 0; k < PENDINGS_MAX; ++k) {
-               pendings[k].fd = -1;
-       }
-
        while (1) {
-               pfds_count = 0;
-               
-               /* Prepare to poll masters */
-               if (pendings_count < PENDINGS_MAX) {
-                       for (k = 0; k < masters_count; ++k) {
-                               master_t *master = &masters[k];
-                               master->pindex = pfds_count;
-                               pfds[pfds_count].fd = master->fd;
-                               pfds[pfds_count].events = POLLIN;
-                               pfds_count++;
-                       }
-               } else {
-                       for (k = 0; k < masters_count; ++k) {
-                               master_t *master = &masters[k];
-                               master->pindex = -1;
-                       }
-               }
-
-               /* Prepare to poll pendings */
-               for (k = 0; k < PENDINGS_MAX; ++k) {
-                       pending_t *pending = &pendings[k];
-                       if (pending->fd < 0 ||
-                           pending->cookie != 0) {
-                               pending->pindex = -1;
-                               continue;
-                       }
-                       pending->pindex = pfds_count;
-                       pfds[pfds_count].fd = pending->fd;
-                       pfds[pfds_count].events = POLLHUP;
-                       if (pendings_count < PENDINGS_MAX &&
-                           clients_count < CLIENTS_MAX)
-                               pfds[pfds_count].events |= POLLIN;
-                       pfds_count++;
-               }
-
-               /* Prepare to poll clients */
-               for (k = 0; k < clients_count; ++k) {
-                       client_t *client = &clients[k];
-                       client->data.pindex = pfds_count;
-                       pfds[pfds_count].fd = client->data.fd;
-                       pfds[pfds_count].events = POLLHUP;
-                       pfds_count++;
-
-                       client->ctrl.pindex = pfds_count;
-                       pfds[pfds_count].fd = client->ctrl.fd;
-                       pfds[pfds_count].events = POLLIN | POLLHUP;
-                       pfds_count++;
-               }
-
-               /* Prepare to poll devices */
-               for (k = 0; k < clients_count; ++k) {
-                       client_t *client = &clients[k];
-                       int n;
-                       if (client->state == CLOSED)
-                               continue;
-                       n = client->ops->poll_prepare(client, pfds, pfds_count);
-                       pfds_count += n;
-               }
-               
-
-               /* Poll */
+               struct pollfd pfds[OPEN_MAX];
+               size_t pfds_count;
                do {
-                       err = poll(pfds, pfds_count, 1000);
+                       err = poll(pollfds, pollfds_count, 1000);
                } while (err == 0);
                if (err < 0) {
-                       int result = -errno;
                        perrno("poll");
-                       return result;
+                       continue;
                }
 
-               /* Handle clients events */
-               for (k = clients_count - 1; k >= 0; --k) {
-                       client_t *client;
-                       struct pollfd *data_pfd = &pfds[clients[k].data.pindex];
-                       struct pollfd *ctrl_pfd = &pfds[clients[k].ctrl.pindex];
-                       if (!data_pfd->revents && !ctrl_pfd->revents)
-                               continue;
-                       client = &clients[k];
-                       if ((data_pfd->revents & POLLHUP) ||
-                           (ctrl_pfd->revents & POLLHUP)) {
-                               if (client->state != CLOSED) {
-                                       client->ops->close(client);
-                               }
-                               close(client->data.fd);
-                               if (client->ctrl.fd >= 0)
-                                       close(client->ctrl.fd);
-                               memmove(client, client + 1,
-                                       (clients_count - k) * sizeof(client_t));
-                               clients_count--;
-                               continue;
-                       }
-                       if (ctrl_pfd->revents & POLLIN) {
-                               if (client->state == CLOSED)
-                                       snd_client_open(client);
-                               else
-                                       client->ops->cmd(client);
-                       }
-               }
-
-               /* Handle device events */
-               for (k = 0; k < clients_count; ++k) {
-                       client_t *client = &clients[k];
-                       client->ops->poll_events(client, pfds);
-               }
-
-               /* Handle pending events */
-               for (k = 0; k < PENDINGS_MAX; ++k) {
-                       struct pollfd *pfd;
-                       uint32_t cookie;
-                       int j;
-                       pending_t *pending = &pendings[k];
-                       client_t *client;
-                       int remove = 0;
-                       if (pending->pindex < 0)
-                               continue;
-                       pfd = &pfds[pending->pindex];
-                       if (!pfd->revents)
-                               continue;
-                       if (pfd->revents & POLLHUP)
-                               remove = 1;
-                       else {
-                               if (clients_count >= CLIENTS_MAX)
+               pfds_count = pollfds_count;
+               memcpy(pfds, pollfds, sizeof(*pfds) * pfds_count);
+               for (k = 0; k < pfds_count; k++) {
+                       struct pollfd *pfd = &pfds[k];
+                       if (pfd->revents) {
+                               waiter_t *w = &waiters[pfd->fd];
+                               if (!w->handler)
                                        continue;
-                               err = read(pfd->fd, &cookie, sizeof(cookie));
-                               if (err != sizeof(cookie))
-                                       remove = 1;
-                               else {
-                                       err = write(pfd->fd, &cookie, sizeof(cookie));
-                                       if (err != sizeof(cookie))
-                                               remove = 1;
-                               }
-                       }
-                       if (remove) {
-                               close(pending->fd);
-                               pending->fd = -1;
-                               pendings_count--;
-                               continue;
-                       }
-
-                       for (j = 0; j < PENDINGS_MAX; ++j) {
-                               if (pendings[j].cookie == cookie)
-                                       break;
-                       }
-                       if (j == PENDINGS_MAX) {
-                               pendings[k].cookie = cookie;
-                               continue;
-                       }
-                       
-                       client = &clients[clients_count];
-                       memset(client, 0, sizeof(*client));
-                       client->data.fd = pendings[j].fd;
-                       client->data.local = pendings[j].local;
-                       client->ctrl.fd = pendings[k].fd;
-                       client->ctrl.local = pendings[k].local;
-                       client->state = CLOSED;
-                       clients_count++;
-                       pendings[j].fd = -1;
-                       pendings[k].fd = -1;
-                       pendings_count -= 2;
-               }
-
-               /* Handle master events */
-               for (k = 0; k < masters_count; ++k) {
-                       struct pollfd *pfd;
-                       master_t *master;
-                       int sock;
-                       if (pendings_count >= PENDINGS_MAX)
-                               break;
-                       master = &masters[k];
-                       if (master->pindex < 0)
-                               continue;
-                       pfd = &pfds[master->pindex];
-                       if (!pfd->revents)
-                               continue;
-                       
-                       sock = accept(master->fd, 0, 0);
-                       if (sock < 0) {
-                               int result = -errno;
-                                perrno("accept");
-                                return result;
-                       } else {
-                               int j;
-                               for (j = 0; j < PENDINGS_MAX; ++j) {
-                                       if (pendings[j].fd < 0)
-                                               break;
-                               }
-                               assert(j < PENDINGS_MAX);
-                               pendings[j].fd = sock;
-                               pendings[j].local = master->local;
-                               pendings[j].cookie = 0;
-                               pendings_count++;
+                               err = w->handler(w, pfd->revents);
+                               if (err < 0)
+                                       perrno("handler");
                        }
                }
-               
        }
        return 0;
 }
index 61b2679d976e112d2a4d1269e087d16cf147984e..8592e654d4f8e5af6d028379353fda239b032309 100644 (file)
@@ -1,6 +1,7 @@
 EXTRA_LTLIBRARIES = libcontrol.la
 
-libcontrol_la_SOURCES = cards.c control.c controls.c bag.c defaults.c
+libcontrol_la_SOURCES = cards.c controls.c bag.c defaults.c \
+                        control.c control_hw.c control_client.c
 
 all: libcontrol.la
 
index d9c394050fa6e473117bc40aea57f5547a18fbcf..e3dabdc63d46a8d70da18150583af21c1420c18e 100644 (file)
@@ -106,7 +106,7 @@ int snd_card_get_index(const char *string)
        for (card = 0; card < 32; card++) {
                if (snd_card_load(card) < 0)
                        continue;
-               if (snd_ctl_open(&handle, card) < 0)
+               if (snd_ctl_hw_open(&handle, card) < 0)
                        continue;
                if (snd_ctl_hw_info(handle, &info) < 0) {
                        snd_ctl_close(handle);
@@ -127,7 +127,7 @@ int snd_card_get_name(int card, char **name)
        
        if (name == NULL)
                return -EINVAL;
-       if ((err = snd_ctl_open(&handle, card)) < 0)
+       if ((err = snd_ctl_hw_open(&handle, card)) < 0)
                return err;
        if ((err = snd_ctl_hw_info(handle, &info)) < 0) {
                snd_ctl_close(handle);
@@ -148,7 +148,7 @@ int snd_card_get_longname(int card, char **name)
        
        if (name == NULL)
                return -EINVAL;
-       if ((err = snd_ctl_open(&handle, card)) < 0)
+       if ((err = snd_ctl_hw_open(&handle, card)) < 0)
                return err;
        if ((err = snd_ctl_hw_info(handle, &info)) < 0) {
                snd_ctl_close(handle);
index 1a7740e7c76c9670954d010c9aec2ed29a7df95b..bfd38045f468ce7d5c5aacf68969e2d835e6976c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Control Interface - main file
- *  Copyright (c) 1998,1999,2000 by Jaroslav Kysela <perex@suse.cz>
+ *  Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
  *
  *
  *   This library is free software; you can redistribute it and/or modify
 #include <string.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <sys/ioctl.h>
 #include <assert.h>
 #include "asoundlib.h"
 #include "control_local.h"
 
-#define SND_FILE_CONTROL       "/dev/snd/controlC%i"
-#define SND_CTL_VERSION_MAX    SND_PROTOCOL_VERSION(2, 0, 0)
-
-int snd_ctl_open(snd_ctl_t **handle, int card)
+snd_ctl_type_t snd_ctl_type(snd_ctl_t *ctl)
 {
-       int fd, ver;
-       char filename[32];
-       snd_ctl_t *ctl;
-
-       *handle = NULL; 
-
-       assert(card >= 0 && card < SND_CARDS);
-       sprintf(filename, SND_FILE_CONTROL, card);
-       if ((fd = open(filename, O_RDWR)) < 0) {
-               snd_card_load(card);
-               if ((fd = open(filename, O_RDWR)) < 0)
-                       return -errno;
-       }
-               
-       if (ioctl(fd, SND_CTL_IOCTL_PVERSION, &ver) < 0) {
-               close(fd);
-               return -errno;
-       }
-       if (SND_PROTOCOL_INCOMPATIBLE(ver, SND_CTL_VERSION_MAX)) {
-               close(fd);
-               return -SND_ERROR_INCOMPATIBLE_VERSION;
-       }
-       ctl = (snd_ctl_t *) calloc(1, sizeof(snd_ctl_t));
-       if (ctl == NULL) {
-               close(fd);
-               return -ENOMEM;
-       }
-       ctl->card = card;
-       ctl->fd = fd;
-       INIT_LIST_HEAD(&ctl->hlist);
-       *handle = ctl;
-       return 0;
+       return ctl->type;
 }
 
-int snd_ctl_close(snd_ctl_t *handle)
+int snd_ctl_close(snd_ctl_t *ctl)
 {
        int res;
-       assert(handle);
-       res = close(handle->fd) < 0 ? -errno : 0;
-       free(handle);
+       assert(ctl);
+       res = ctl->ops->close(ctl);
+       free(ctl);
        return res;
 }
 
-int snd_ctl_file_descriptor(snd_ctl_t *handle)
+int snd_ctl_file_descriptor(snd_ctl_t *ctl)
+{
+       assert(ctl);
+       return ctl->ops->file_descriptor(ctl);
+}
+
+int snd_ctl_hw_info(snd_ctl_t *ctl, snd_ctl_hw_info_t *info)
 {
-       assert(handle);
-       return handle->fd;
+       assert(ctl && info);
+       return ctl->ops->hw_info(ctl, info);
 }
 
-int snd_ctl_hw_info(snd_ctl_t *handle, snd_ctl_hw_info_t *info)
+int snd_ctl_clist(snd_ctl_t *ctl, snd_control_list_t *list)
 {
-       assert(handle && info);
-       if (ioctl(handle->fd, SND_CTL_IOCTL_HW_INFO, info) < 0)
-               return -errno;
-       return 0;
+       assert(ctl && list);
+       return ctl->ops->clist(ctl, list);
 }
 
-int snd_ctl_clist(snd_ctl_t *handle, snd_control_list_t *list)
+int snd_ctl_cinfo(snd_ctl_t *ctl, snd_control_info_t *info)
 {
-       assert(handle && list);
-       if (ioctl(handle->fd, SND_CTL_IOCTL_CONTROL_LIST, list) < 0)
-               return -errno;
-       return 0;
+       assert(ctl && info && (info->id.name[0] || info->id.numid));
+       return ctl->ops->cinfo(ctl, info);
 }
 
-int snd_ctl_cinfo(snd_ctl_t *handle, snd_control_info_t *info)
+int snd_ctl_cread(snd_ctl_t *ctl, snd_control_t *control)
 {
-       assert(handle && info && (info->id.name[0] || info->id.numid));
-       if (ioctl(handle->fd, SND_CTL_IOCTL_CONTROL_INFO, info) < 0)
-               return -errno;
-       return 0;
+       assert(ctl && control && (control->id.name[0] || control->id.numid));
+       return ctl->ops->cread(ctl, control);
 }
 
-int snd_ctl_cread(snd_ctl_t *handle, snd_control_t *control)
+int snd_ctl_cwrite(snd_ctl_t *ctl, snd_control_t *control)
 {
-       assert(handle && control && (control->id.name[0] || control->id.numid));
-       if (ioctl(handle->fd, SND_CTL_IOCTL_CONTROL_READ, control) < 0)
-               return -errno;
-       return 0;
+       assert(ctl && control && (control->id.name[0] || control->id.numid));
+       return ctl->ops->cwrite(ctl, control);
 }
 
-int snd_ctl_cwrite(snd_ctl_t *handle, snd_control_t *control)
+int snd_ctl_hwdep_info(snd_ctl_t *ctl, snd_hwdep_info_t * info)
 {
-       assert(handle && control && (control->id.name[0] || control->id.numid));
-       if (ioctl(handle->fd, SND_CTL_IOCTL_CONTROL_WRITE, control) < 0)
-               return -errno;
-       return 0;
+       assert(ctl && info);
+       return ctl->ops->hwdep_info(ctl, info);
 }
 
-int snd_ctl_hwdep_info(snd_ctl_t *handle, snd_hwdep_info_t * info)
+int snd_ctl_pcm_info(snd_ctl_t *ctl, snd_pcm_info_t * info)
 {
-       assert(handle && info);
-       if (ioctl(handle->fd, SND_CTL_IOCTL_HWDEP_INFO, info) < 0)
-               return -errno;
-       return 0;
+       assert(ctl && info);
+       return ctl->ops->pcm_info(ctl, info);
 }
 
-int snd_ctl_pcm_info(snd_ctl_t *handle, snd_pcm_info_t * info)
+int snd_ctl_pcm_prefer_subdevice(snd_ctl_t *ctl, int subdev)
 {
-       assert(handle && info);
-       if (ioctl(handle->fd, SND_CTL_IOCTL_PCM_INFO, info) < 0)
-               return -errno;
-       return 0;
+       assert(ctl);
+       return ctl->ops->pcm_prefer_subdevice(ctl, subdev);
 }
 
-int snd_ctl_pcm_prefer_subdevice(snd_ctl_t *handle, int subdev)
+int snd_ctl_rawmidi_info(snd_ctl_t *ctl, snd_rawmidi_info_t * info)
 {
-       assert(handle);
-       if (ioctl(handle->fd, SND_CTL_IOCTL_PCM_PREFER_SUBDEVICE, &subdev) < 0)
-               return -errno;
-       return 0;
+       assert(ctl && info);
+       return ctl->ops->rawmidi_info(ctl, info);
 }
 
-int snd_ctl_rawmidi_info(snd_ctl_t *handle, snd_rawmidi_info_t * info)
+int snd_ctl_read1(snd_ctl_t *ctl, snd_ctl_event_t *event)
 {
-       assert(handle && info);
-       if (ioctl(handle->fd, SND_CTL_IOCTL_RAWMIDI_INFO, info) < 0)
-               return -errno;
-       return 0;
+       assert(ctl && event);
+       return ctl->ops->read(ctl, event);
 }
 
-int snd_ctl_read(snd_ctl_t *handle, snd_ctl_callbacks_t * callbacks)
+int snd_ctl_read(snd_ctl_t *ctl, snd_ctl_callbacks_t * callbacks)
 {
        int result, count;
        snd_ctl_event_t r;
 
-       assert(handle);
+       assert(ctl);
        count = 0;
-       while ((result = read(handle->fd, &r, sizeof(r))) > 0) {
+       while ((result = snd_ctl_read1(ctl, &r)) > 0) {
                if (result != sizeof(r))
                        return -EIO;
                if (!callbacks)
@@ -171,26 +124,142 @@ int snd_ctl_read(snd_ctl_t *handle, snd_ctl_callbacks_t * callbacks)
                switch (r.type) {
                case SND_CTL_EVENT_REBUILD:
                        if (callbacks->rebuild)
-                               callbacks->rebuild(handle, callbacks->private_data);
+                               callbacks->rebuild(ctl, callbacks->private_data);
                        break;
                case SND_CTL_EVENT_VALUE:
                        if (callbacks->value)
-                               callbacks->value(handle, callbacks->private_data, &r.data.id);
+                               callbacks->value(ctl, callbacks->private_data, &r.data.id);
                        break;
                case SND_CTL_EVENT_CHANGE:
                        if (callbacks->change)
-                               callbacks->change(handle, callbacks->private_data, &r.data.id);
+                               callbacks->change(ctl, callbacks->private_data, &r.data.id);
                        break;
                case SND_CTL_EVENT_ADD:
                        if (callbacks->add)
-                               callbacks->add(handle, callbacks->private_data, &r.data.id);
+                               callbacks->add(ctl, callbacks->private_data, &r.data.id);
                        break;
                case SND_CTL_EVENT_REMOVE:
                        if (callbacks->remove)
-                               callbacks->remove(handle, callbacks->private_data, &r.data.id);
+                               callbacks->remove(ctl, callbacks->private_data, &r.data.id);
                        break;
                }
                count++;
        }
        return result >= 0 ? count : -errno;
 }
+
+static int _snd_ctl_open_hw(snd_ctl_t **handlep, snd_config_t *conf)
+{
+       snd_config_iterator_t i;
+       long card = -1;
+       char *str;
+       int err;
+       snd_config_foreach(i, conf) {
+               snd_config_t *n = snd_config_entry(i);
+               if (strcmp(n->id, "comment") == 0)
+                       continue;
+               if (strcmp(n->id, "type") == 0)
+                       continue;
+               if (strcmp(n->id, "card") == 0) {
+                       err = snd_config_integer_get(n, &card);
+                       if (err < 0) {
+                               err = snd_config_string_get(n, &str);
+                               if (err < 0)
+                                       return -EINVAL;
+                               card = snd_card_get_index(str);
+                               if (card < 0)
+                                       return card;
+                       }
+                       continue;
+               }
+               return -EINVAL;
+       }
+       if (card < 0)
+               return -EINVAL;
+       return snd_ctl_hw_open(handlep, card);
+}
+                               
+static int _snd_ctl_open_client(snd_ctl_t **handlep, snd_config_t *conf)
+{
+       snd_config_iterator_t i;
+       char *socket = NULL;
+       char *name = NULL;
+       char *host = NULL;
+       long port = -1;
+       int err;
+       snd_config_foreach(i, conf) {
+               snd_config_t *n = snd_config_entry(i);
+               if (strcmp(n->id, "comment") == 0)
+                       continue;
+               if (strcmp(n->id, "type") == 0)
+                       continue;
+               if (strcmp(n->id, "socket") == 0) {
+                       err = snd_config_string_get(n, &socket);
+                       if (err < 0)
+                               return -EINVAL;
+                       continue;
+               }
+               if (strcmp(n->id, "host") == 0) {
+                       err = snd_config_string_get(n, &host);
+                       if (err < 0)
+                               return -EINVAL;
+                       continue;
+               }
+               if (strcmp(n->id, "port") == 0) {
+                       err = snd_config_integer_get(n, &port);
+                       if (err < 0)
+                               return -EINVAL;
+                       continue;
+               }
+               if (strcmp(n->id, "name") == 0) {
+                       err = snd_config_string_get(n, &name);
+                       if (err < 0)
+                               return -EINVAL;
+                       continue;
+               }
+               return -EINVAL;
+       }
+       if (!name)
+               return -EINVAL;
+       if (socket) {
+               if (port >= 0 || host)
+                       return -EINVAL;
+               return snd_ctl_client_open(handlep, socket, -1, SND_TRANSPORT_TYPE_SHM, name);
+       } else  {
+               if (port < 0 || !name)
+                       return -EINVAL;
+               return snd_ctl_client_open(handlep, host, port, SND_TRANSPORT_TYPE_TCP, name);
+       }
+}
+                               
+int snd_ctl_open(snd_ctl_t **handlep, char *name)
+{
+       char *str;
+       int err;
+       snd_config_t *ctl_conf, *conf;
+       assert(handlep && name);
+       err = snd_config_update();
+       if (err < 0)
+               return err;
+       err = snd_config_searchv(snd_config, &ctl_conf, "ctl", name, 0);
+       if (err < 0) {
+               int idx = snd_card_get_index(name);
+               if (idx < 0)
+                       return idx;
+               return snd_ctl_hw_open(handlep, idx);
+       }
+       if (snd_config_type(ctl_conf) != SND_CONFIG_TYPE_COMPOUND)
+               return -EINVAL;
+       err = snd_config_search(ctl_conf, "type", &conf);
+       if (err < 0)
+               return err;
+       err = snd_config_string_get(conf, &str);
+       if (err < 0)
+               return err;
+       if (strcmp(str, "hw") == 0)
+               return _snd_ctl_open_hw(handlep, ctl_conf);
+       else if (strcmp(str, "client") == 0)
+               return _snd_ctl_open_client(handlep, ctl_conf);
+       else
+               return -EINVAL;
+}
diff --git a/src/control/control_client.c b/src/control/control_client.c
new file mode 100644 (file)
index 0000000..264f4b3
--- /dev/null
@@ -0,0 +1,433 @@
+/*
+ *  Control - Client
+ *  Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
+ *
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Library General Public License as
+ *   published by the Free Software Foundation; either version 2 of
+ *   the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU Library General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Library General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+  
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/shm.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <sys/un.h>
+#include <sys/uio.h>
+#include <sys/mman.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include "control_local.h"
+#include "aserver.h"
+
+typedef struct {
+       int data_fd;
+       int ctrl_fd;
+       union {
+               struct {
+                       void *ctrl;
+               } shm;
+       } u;
+} snd_ctl_client_t;
+
+static void clean_poll(snd_ctl_t *ctl)
+{
+       snd_ctl_client_t *client = ctl->private;
+       struct pollfd pfd;
+       int err;
+       char buf[1];
+       pfd.fd = client->data_fd;
+       pfd.events = POLLIN;
+       while (1) {
+               err = poll(&pfd, 1, 0);
+               if (err == 0)
+                       break;
+               assert(err > 0);
+               err = read(client->data_fd, buf, 1);
+               assert(err == 1);
+       }
+}
+
+static int snd_ctl_client_shm_action(snd_ctl_t *ctl)
+{
+       snd_ctl_client_t *client = ctl->private;
+       int err;
+       char buf[1];
+       snd_ctl_client_shm_t *ctrl = client->u.shm.ctrl;
+       clean_poll(ctl);
+       err = write(client->ctrl_fd, buf, 1);
+       if (err != 1)
+               return -EBADFD;
+       err = read(client->ctrl_fd, buf, 1);
+       if (err != 1)
+               return -EBADFD;
+       if (ctrl->cmd) {
+               fprintf(stderr, "Server has not done the cmd\n");
+               return -EBADFD;
+       }
+       return 0;
+}
+
+static int snd_ctl_client_shm_close(snd_ctl_t *ctl)
+{
+       snd_ctl_client_t *client = ctl->private;
+       snd_ctl_client_shm_t *ctrl = client->u.shm.ctrl;
+       int result;
+       ctrl->cmd = SND_CTL_IOCTL_CLOSE;
+       result = snd_ctl_client_shm_action(ctl);
+       if (result >= 0)
+               result = ctrl->result;
+       shmdt((void *)ctrl);
+       close(client->data_fd);
+       close(client->ctrl_fd);
+       free(client);
+       return result;
+}
+
+static int snd_ctl_client_file_descriptor(snd_ctl_t *ctl)
+{
+       snd_ctl_client_t *client = ctl->private;
+       return client->data_fd;
+}
+
+static int snd_ctl_client_shm_hw_info(snd_ctl_t *ctl, snd_ctl_hw_info_t *info)
+{
+       snd_ctl_client_t *client = ctl->private;
+       snd_ctl_client_shm_t *ctrl = client->u.shm.ctrl;
+       int err;
+//     ctrl->u.hw_info = *info;
+       ctrl->cmd = SND_CTL_IOCTL_HW_INFO;
+       err = snd_ctl_client_shm_action(ctl);
+       if (err < 0)
+               return err;
+       *info = ctrl->u.hw_info;
+       return ctrl->result;
+}
+
+static int snd_ctl_client_shm_clist(snd_ctl_t *ctl, snd_control_list_t *list)
+{
+       snd_ctl_client_t *client = ctl->private;
+       snd_ctl_client_shm_t *ctrl = client->u.shm.ctrl;
+       size_t maxsize = CTL_SHM_DATA_MAXLEN;
+       size_t bytes = list->controls_request * sizeof(*list->pids);
+       int err;
+       snd_control_id_t *pids = list->pids;
+       if (bytes > maxsize)
+               return -EINVAL;
+       ctrl->u.clist = *list;
+       ctrl->cmd = SND_CTL_IOCTL_CONTROL_LIST;
+       err = snd_ctl_client_shm_action(ctl);
+       if (err < 0)
+               return err;
+       *list = ctrl->u.clist;
+       list->pids = pids;
+       memcpy(pids, ctrl->data, bytes);
+       return ctrl->result;
+}
+
+static int snd_ctl_client_shm_cinfo(snd_ctl_t *ctl, snd_control_info_t *info)
+{
+       snd_ctl_client_t *client = ctl->private;
+       snd_ctl_client_shm_t *ctrl = client->u.shm.ctrl;
+       int err;
+       ctrl->u.cinfo = *info;
+       ctrl->cmd = SND_CTL_IOCTL_CONTROL_INFO;
+       err = snd_ctl_client_shm_action(ctl);
+       if (err < 0)
+               return err;
+       *info = ctrl->u.cinfo;
+       return ctrl->result;
+}
+
+static int snd_ctl_client_shm_cread(snd_ctl_t *ctl, snd_control_t *control)
+{
+       snd_ctl_client_t *client = ctl->private;
+       snd_ctl_client_shm_t *ctrl = client->u.shm.ctrl;
+       int err;
+       ctrl->u.cread = *control;
+       ctrl->cmd = SND_CTL_IOCTL_CONTROL_READ;
+       err = snd_ctl_client_shm_action(ctl);
+       if (err < 0)
+               return err;
+       *control = ctrl->u.cread;
+       return ctrl->result;
+}
+
+static int snd_ctl_client_shm_cwrite(snd_ctl_t *ctl, snd_control_t *control)
+{
+       snd_ctl_client_t *client = ctl->private;
+       snd_ctl_client_shm_t *ctrl = client->u.shm.ctrl;
+       int err;
+       ctrl->u.cwrite = *control;
+       ctrl->cmd = SND_CTL_IOCTL_CONTROL_WRITE;
+       err = snd_ctl_client_shm_action(ctl);
+       if (err < 0)
+               return err;
+       *control = ctrl->u.cwrite;
+       return ctrl->result;
+}
+
+static int snd_ctl_client_shm_hwdep_info(snd_ctl_t *ctl, snd_hwdep_info_t * info)
+{
+       snd_ctl_client_t *client = ctl->private;
+       snd_ctl_client_shm_t *ctrl = client->u.shm.ctrl;
+       int err;
+       ctrl->u.hwdep_info = *info;
+       ctrl->cmd = SND_CTL_IOCTL_HWDEP_INFO;
+       err = snd_ctl_client_shm_action(ctl);
+       if (err < 0)
+               return err;
+       *info = ctrl->u.hwdep_info;
+       return ctrl->result;
+}
+
+static int snd_ctl_client_shm_pcm_info(snd_ctl_t *ctl, snd_pcm_info_t * info)
+{
+       snd_ctl_client_t *client = ctl->private;
+       snd_ctl_client_shm_t *ctrl = client->u.shm.ctrl;
+       int err;
+       ctrl->u.pcm_info = *info;
+       ctrl->cmd = SND_CTL_IOCTL_PCM_INFO;
+       err = snd_ctl_client_shm_action(ctl);
+       if (err < 0)
+               return err;
+       *info = ctrl->u.pcm_info;
+       return ctrl->result;
+}
+
+static int snd_ctl_client_shm_pcm_prefer_subdevice(snd_ctl_t *ctl, int subdev)
+{
+       snd_ctl_client_t *client = ctl->private;
+       snd_ctl_client_shm_t *ctrl = client->u.shm.ctrl;
+       int err;
+       ctrl->u.pcm_prefer_subdevice = subdev;
+       ctrl->cmd = SND_CTL_IOCTL_PCM_PREFER_SUBDEVICE;
+       err = snd_ctl_client_shm_action(ctl);
+       if (err < 0)
+               return err;
+       return ctrl->result;
+}
+
+static int snd_ctl_client_shm_rawmidi_info(snd_ctl_t *ctl, snd_rawmidi_info_t * info)
+{
+       snd_ctl_client_t *client = ctl->private;
+       snd_ctl_client_shm_t *ctrl = client->u.shm.ctrl;
+       int err;
+       ctrl->u.rawmidi_info = *info;
+       ctrl->cmd = SND_CTL_IOCTL_RAWMIDI_INFO;
+       err = snd_ctl_client_shm_action(ctl);
+       if (err < 0)
+               return err;
+       *info = ctrl->u.rawmidi_info;
+       return ctrl->result;
+}
+
+static int snd_ctl_client_shm_read(snd_ctl_t *ctl, snd_ctl_event_t *event)
+{
+       snd_ctl_client_t *client = ctl->private;
+       snd_ctl_client_shm_t *ctrl = client->u.shm.ctrl;
+       int err;
+       ctrl->u.read = *event;
+       ctrl->cmd = SND_CTL_IOCTL_READ;
+       err = snd_ctl_client_shm_action(ctl);
+       if (err < 0)
+               return err;
+       *event = ctrl->u.read;
+       return ctrl->result;
+}
+
+struct snd_ctl_ops snd_ctl_client_ops = {
+       close: snd_ctl_client_shm_close,
+       file_descriptor: snd_ctl_client_file_descriptor,
+       hw_info: snd_ctl_client_shm_hw_info,
+       clist: snd_ctl_client_shm_clist,
+       cinfo: snd_ctl_client_shm_cinfo,
+       cread: snd_ctl_client_shm_cread,
+       cwrite: snd_ctl_client_shm_cwrite,
+       hwdep_info: snd_ctl_client_shm_hwdep_info,
+       pcm_info: snd_ctl_client_shm_pcm_info,
+       pcm_prefer_subdevice: snd_ctl_client_shm_pcm_prefer_subdevice,
+       rawmidi_info: snd_ctl_client_shm_rawmidi_info,
+       read: snd_ctl_client_shm_read,
+};
+
+static int make_local_socket(const char *filename)
+{
+       size_t l = strlen(filename);
+       size_t size = offsetof(struct sockaddr_un, sun_path) + l;
+       struct sockaddr_un *addr = alloca(size);
+       int sock;
+
+       sock = socket(PF_LOCAL, SOCK_STREAM, 0);
+       if (sock < 0)
+               return -errno;
+       
+       addr->sun_family = AF_LOCAL;
+       memcpy(addr->sun_path, filename, l);
+
+       if (connect(sock, (struct sockaddr *) addr, size) < 0)
+               return -errno;
+       return sock;
+}
+
+static int make_inet_socket(const char *host, int port)
+{
+       struct sockaddr_in addr;
+       int sock;
+       struct hostent *h = gethostbyname(host);
+       if (!h)
+               return -ENOENT;
+
+       sock = socket(PF_INET, SOCK_STREAM, 0);
+       if (sock < 0)
+               return -errno;
+       
+       addr.sin_family = AF_INET;
+       addr.sin_port = htons(port);
+       memcpy(&addr.sin_addr, h->h_addr_list[0], sizeof(struct in_addr));
+
+       if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0)
+               return -errno;
+       return sock;
+}
+
+/* port == -1 -> PF_LOCAL and host is the socket name */
+int snd_ctl_client_open(snd_ctl_t **handlep, char *host, int port, int transport, char *name)
+{
+       snd_ctl_t *ctl;
+       snd_ctl_client_t *client;
+       snd_client_open_request_t *req;
+       snd_client_open_answer_t ans;
+       size_t namelen, reqlen;
+       int err;
+       int result;
+       int fds[2] = {-1, -1};
+       int k;
+       snd_ctl_client_shm_t *ctrl = NULL;
+       uint32_t rcookie, scookie = getpid();
+       namelen = strlen(name);
+       if (namelen > 255)
+               return -EINVAL;
+
+       for (k = 0; k < 2; ++k) {
+               if (port == -1)
+                       fds[k] = make_local_socket(host);
+               else
+                       fds[k] = make_inet_socket(host, port);
+               if (fds[k] < 0) {
+                       result = fds[k];
+                       goto _err;
+               }
+               err = write(fds[k], &scookie, sizeof(scookie));
+               if (err != sizeof(scookie)) {
+                       result = -EBADFD;
+                       goto _err;
+               }
+               err = read(fds[k], &rcookie, sizeof(rcookie));
+               if (err != sizeof(rcookie) ||
+                   rcookie != scookie) {
+                       result = -EBADFD;
+                       goto _err;
+               }
+       }
+
+       reqlen = sizeof(*req) + namelen;
+       req = alloca(reqlen);
+       memcpy(req->name, name, namelen);
+       req->dev_type = SND_DEV_TYPE_CONTROL;
+       req->transport_type = transport;
+       req->stream = 0;
+       req->mode = 0;
+       req->namelen = namelen;
+       err = write(fds[1], req, reqlen);
+       if (err < 0) {
+               result = -errno;
+               goto _err;
+       }
+       if ((size_t) err != reqlen) {
+               result = -EINVAL;
+               goto _err;
+       }
+       err = read(fds[1], &ans, sizeof(ans));
+       if (err < 0) {
+               result = -errno;
+               goto _err;
+       }
+       if (err != sizeof(ans)) {
+               result = -EINVAL;
+               goto _err;
+       }
+       result = ans.result;
+       if (result < 0)
+               goto _err;
+
+       switch (transport) {
+       case SND_TRANSPORT_TYPE_SHM:
+               ctrl = shmat(ans.cookie, 0, 0);
+               if (!ctrl) {
+                       result = -errno;
+                       goto _err;
+               }
+               break;
+       default:
+               result = -ENOSYS;
+               goto _err;
+       }
+               
+       ctl = calloc(1, sizeof(snd_ctl_t));
+       if (!ctl) {
+               result = -ENOMEM;
+               goto _err;
+       }
+       client = calloc(1, sizeof(snd_ctl_client_t));
+       if (!ctl) {
+               free(ctl);
+               result = -ENOMEM;
+               goto _err;
+       }
+
+       client->data_fd = fds[0];
+       client->ctrl_fd = fds[1];
+       switch (transport) {
+       case SND_TRANSPORT_TYPE_SHM:
+               client->u.shm.ctrl = ctrl;
+               break;
+       }
+       ctl->type = SND_CTL_TYPE_CLIENT;
+       ctl->ops = &snd_ctl_client_ops;
+       ctl->private = client;
+       INIT_LIST_HEAD(&ctl->hlist);
+       *handlep = ctl;
+       return 0;
+
+ _err:
+       if (fds[0] >= 0)
+               close(fds[0]);
+       if (fds[1] >= 0)
+               close(fds[1]);
+       switch (transport) {
+       case SND_TRANSPORT_TYPE_SHM:
+               if (ctrl)
+                       shmdt(ctrl);
+               break;
+       }
+       return result;
+}
+
diff --git a/src/control/control_hw.c b/src/control/control_hw.c
new file mode 100644 (file)
index 0000000..496ce22
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ *  Control Interface - Hardware
+ *  Copyright (c) 1998,1999,2000 by Jaroslav Kysela <perex@suse.cz>
+ *  Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
+ *
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Library General Public License as
+ *   published by the Free Software Foundation; either version 2 of
+ *   the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU Library General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Library General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <assert.h>
+#include "asoundlib.h"
+#include "control_local.h"
+
+#define SND_FILE_CONTROL       "/dev/snd/controlC%i"
+#define SND_CTL_VERSION_MAX    SND_PROTOCOL_VERSION(2, 0, 0)
+
+typedef struct {
+       int card;
+       int fd;
+} snd_ctl_hw_t;
+
+static int snd_ctl_hw_close(snd_ctl_t *handle)
+{
+       snd_ctl_hw_t *hw = handle->private;
+       int res;
+       res = close(hw->fd) < 0 ? -errno : 0;
+       free(hw);
+       return res;
+}
+
+static int snd_ctl_hw_file_descriptor(snd_ctl_t *handle)
+{
+       snd_ctl_hw_t *hw = handle->private;
+       return hw->fd;
+}
+
+static int snd_ctl_hw_hw_info(snd_ctl_t *handle, snd_ctl_hw_info_t *info)
+{
+       snd_ctl_hw_t *hw = handle->private;
+       if (ioctl(hw->fd, SND_CTL_IOCTL_HW_INFO, info) < 0)
+               return -errno;
+       return 0;
+}
+
+static int snd_ctl_hw_clist(snd_ctl_t *handle, snd_control_list_t *list)
+{
+       snd_ctl_hw_t *hw = handle->private;
+       if (ioctl(hw->fd, SND_CTL_IOCTL_CONTROL_LIST, list) < 0)
+               return -errno;
+       return 0;
+}
+
+static int snd_ctl_hw_cinfo(snd_ctl_t *handle, snd_control_info_t *info)
+{
+       snd_ctl_hw_t *hw = handle->private;
+       if (ioctl(hw->fd, SND_CTL_IOCTL_CONTROL_INFO, info) < 0)
+               return -errno;
+       return 0;
+}
+
+static int snd_ctl_hw_cread(snd_ctl_t *handle, snd_control_t *control)
+{
+       snd_ctl_hw_t *hw = handle->private;
+       if (ioctl(hw->fd, SND_CTL_IOCTL_CONTROL_READ, control) < 0)
+               return -errno;
+       return 0;
+}
+
+static int snd_ctl_hw_cwrite(snd_ctl_t *handle, snd_control_t *control)
+{
+       snd_ctl_hw_t *hw = handle->private;
+       if (ioctl(hw->fd, SND_CTL_IOCTL_CONTROL_WRITE, control) < 0)
+               return -errno;
+       return 0;
+}
+
+static int snd_ctl_hw_hwdep_info(snd_ctl_t *handle, snd_hwdep_info_t * info)
+{
+       snd_ctl_hw_t *hw = handle->private;
+       if (ioctl(hw->fd, SND_CTL_IOCTL_HWDEP_INFO, info) < 0)
+               return -errno;
+       return 0;
+}
+
+static int snd_ctl_hw_pcm_info(snd_ctl_t *handle, snd_pcm_info_t * info)
+{
+       snd_ctl_hw_t *hw = handle->private;
+       if (ioctl(hw->fd, SND_CTL_IOCTL_PCM_INFO, info) < 0)
+               return -errno;
+       return 0;
+}
+
+static int snd_ctl_hw_pcm_prefer_subdevice(snd_ctl_t *handle, int subdev)
+{
+       snd_ctl_hw_t *hw = handle->private;
+       if (ioctl(hw->fd, SND_CTL_IOCTL_PCM_PREFER_SUBDEVICE, &subdev) < 0)
+               return -errno;
+       return 0;
+}
+
+static int snd_ctl_hw_rawmidi_info(snd_ctl_t *handle, snd_rawmidi_info_t * info)
+{
+       snd_ctl_hw_t *hw = handle->private;
+       if (ioctl(hw->fd, SND_CTL_IOCTL_RAWMIDI_INFO, info) < 0)
+               return -errno;
+       return 0;
+}
+
+static int snd_ctl_hw_read(snd_ctl_t *handle, snd_ctl_event_t *event)
+{
+       snd_ctl_hw_t *hw = handle->private;
+       return read(hw->fd, event, sizeof(*event));
+}
+
+struct snd_ctl_ops snd_ctl_hw_ops = {
+       close: snd_ctl_hw_close,
+       file_descriptor: snd_ctl_hw_file_descriptor,
+       hw_info: snd_ctl_hw_hw_info,
+       clist: snd_ctl_hw_clist,
+       cinfo: snd_ctl_hw_cinfo,
+       cread: snd_ctl_hw_cread,
+       cwrite: snd_ctl_hw_cwrite,
+       hwdep_info: snd_ctl_hw_hwdep_info,
+       pcm_info: snd_ctl_hw_pcm_info,
+       pcm_prefer_subdevice: snd_ctl_hw_pcm_prefer_subdevice,
+       rawmidi_info: snd_ctl_hw_rawmidi_info,
+       read: snd_ctl_hw_read,
+};
+
+int snd_ctl_hw_open(snd_ctl_t **handle, int card)
+{
+       int fd, ver;
+       char filename[32];
+       snd_ctl_t *ctl;
+       snd_ctl_hw_t *hw;
+
+       *handle = NULL; 
+
+       assert(card >= 0 && card < SND_CARDS);
+       sprintf(filename, SND_FILE_CONTROL, card);
+       if ((fd = open(filename, O_RDWR)) < 0) {
+               snd_card_load(card);
+               if ((fd = open(filename, O_RDWR)) < 0)
+                       return -errno;
+       }
+               
+       if (ioctl(fd, SND_CTL_IOCTL_PVERSION, &ver) < 0) {
+               close(fd);
+               return -errno;
+       }
+       if (SND_PROTOCOL_INCOMPATIBLE(ver, SND_CTL_VERSION_MAX)) {
+               close(fd);
+               return -SND_ERROR_INCOMPATIBLE_VERSION;
+       }
+       ctl = calloc(1, sizeof(snd_ctl_t));
+       if (ctl == NULL) {
+               close(fd);
+               return -ENOMEM;
+       }
+       hw = calloc(1, sizeof(snd_ctl_hw_t));
+       if (hw == NULL) {
+               close(fd);
+               free(ctl);
+               return -ENOMEM;
+       }
+       hw->card = card;
+       hw->fd = fd;
+       ctl->ops = &snd_ctl_hw_ops;
+       ctl->private = hw;
+       INIT_LIST_HEAD(&ctl->hlist);
+       *handle = ctl;
+       return 0;
+}
+
index 4c2e826cf3372f4acd5b652da347f2ca3952e706..d396df5a47b61d7f76f6e0137d987ec12e8232e2 100644 (file)
  *
  */
 
+#include <assert.h>
+#include "asoundlib.h"
 #include "list.h"
 
+struct snd_ctl_ops {
+       int (*close)(snd_ctl_t *handle);
+       int (*file_descriptor)(snd_ctl_t *handle);
+       int (*hw_info)(snd_ctl_t *handle, snd_ctl_hw_info_t *info);
+       int (*clist)(snd_ctl_t *handle, snd_control_list_t *list);
+       int (*cinfo)(snd_ctl_t *handle, snd_control_info_t *info);
+       int (*cread)(snd_ctl_t *handle, snd_control_t *control);
+       int (*cwrite)(snd_ctl_t *handle, snd_control_t *control);
+       int (*hwdep_info)(snd_ctl_t *handle, snd_hwdep_info_t * info);
+       int (*pcm_info)(snd_ctl_t *handle, snd_pcm_info_t * info);
+       int (*pcm_prefer_subdevice)(snd_ctl_t *handle, int subdev);
+       int (*rawmidi_info)(snd_ctl_t *handle, snd_rawmidi_info_t * info);
+       int (*read)(snd_ctl_t *handle, snd_ctl_event_t *event);
+};
+
+
 struct snd_ctl {
-       int card;
-       int fd;
+       snd_ctl_type_t type;
+       struct snd_ctl_ops *ops;
+       void *private;
        int hcount;
        int herr;
        struct list_head hlist; /* list of all controls */
index 1bea0d5ab646974f82c5be4c25587aba0e6bde24..ed22bf34dc644e2b863faf7d1d84568eaf03d756 100644 (file)
@@ -32,7 +32,7 @@
 static void snd_mixer_simple_read_rebuild(snd_ctl_t *ctl_handle, void *private_data);
 static void snd_mixer_simple_read_add(snd_ctl_t *ctl_handle, void *private_data, snd_hcontrol_t *hcontrol);
 
-int snd_mixer_open(snd_mixer_t **r_handle, int card)
+int snd_mixer_open(snd_mixer_t **r_handle, char *name)
 {
        snd_mixer_t *handle;
        snd_ctl_t *ctl_handle;
@@ -41,7 +41,7 @@ int snd_mixer_open(snd_mixer_t **r_handle, int card)
        if (r_handle == NULL)
                return -EINVAL;
        *r_handle = NULL;
-       if ((err = snd_ctl_open(&ctl_handle, card)) < 0)
+       if ((err = snd_ctl_open(&ctl_handle, name)) < 0)
                return err;
        handle = (snd_mixer_t *) calloc(1, sizeof(snd_mixer_t));
        if (handle == NULL) {
index fc2507a1143a36996627f020e768693d1ee4845e..fffd6c12a69260bcb6179c47d4d9672d6535644b 100644 (file)
@@ -788,7 +788,7 @@ static int _snd_pcm_open_client(snd_pcm_t **handlep, snd_config_t *conf,
        } else  {
                if (port < 0 || !name)
                        return -EINVAL;
-               return snd_pcm_client_create(handlep, host, port, SND_TRANSPORT_TYPE_SHM, name, stream, mode);
+               return snd_pcm_client_create(handlep, host, port, SND_TRANSPORT_TYPE_TCP, name, stream, mode);
        }
 }
                                
index ed72f53aa7745573fb12a8a1084f91f4d3e5e06f..8d721256e6e31f1ff32be96526be315ce231ddba 100644 (file)
@@ -38,7 +38,6 @@
 #include "aserver.h"
 
 typedef struct {
-       snd_pcm_t *handle;
        int data_fd;
        int ctrl_fd;
        union {
@@ -80,13 +79,14 @@ int receive_fd(int socket, void *data, size_t len, int *fd)
     return ret;
 }
 
-static void clean_state(snd_pcm_client_t *client)
+static void clean_poll(snd_pcm_t *pcm)
 {
+       snd_pcm_client_t *client = pcm->private;
        struct pollfd pfd;
        int err;
        char buf[1];
        pfd.fd = client->data_fd;
-       switch (client->handle->stream) {
+       switch (pcm->stream) {
        case SND_PCM_STREAM_PLAYBACK:
                pfd.events = POLLOUT;
                while (1) {
@@ -112,11 +112,13 @@ static void clean_state(snd_pcm_client_t *client)
        }
 }
 
-static int snd_pcm_client_shm_action(snd_pcm_client_t *client)
+static int snd_pcm_client_shm_action(snd_pcm_t *pcm)
 {
+       snd_pcm_client_t *client = pcm->private;
        int err;
        char buf[1];
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
+       clean_poll(pcm);
        err = write(client->ctrl_fd, buf, 1);
        if (err != 1)
                return -EBADFD;
@@ -130,12 +132,14 @@ static int snd_pcm_client_shm_action(snd_pcm_client_t *client)
        return 0;
 }
 
-static int snd_pcm_client_shm_action_fd(snd_pcm_client_t *client)
+static int snd_pcm_client_shm_action_fd(snd_pcm_t *pcm)
 {
+       snd_pcm_client_t *client = pcm->private;
        int err;
        char buf[1];
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int fd;
+       clean_poll(pcm);
        err = write(client->ctrl_fd, buf, 1);
        if (err != 1)
                return -EBADFD;
@@ -151,242 +155,242 @@ static int snd_pcm_client_shm_action_fd(snd_pcm_client_t *client)
        return fd;
 }
 
-static int snd_pcm_client_shm_close(void *private)
+static int snd_pcm_client_shm_close(snd_pcm_t *pcm)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int result;
        ctrl->cmd = SND_PCM_IOCTL_CLOSE;
-       result = snd_pcm_client_shm_action(client);
+       result = snd_pcm_client_shm_action(pcm);
        if (result >= 0)
                result = ctrl->result;
        shmdt((void *)ctrl);
        close(client->data_fd);
        close(client->ctrl_fd);
+       free(client);
        return result;
 }
 
-static int snd_pcm_client_shm_nonblock(void *private, int nonblock)
+static int snd_pcm_client_shm_nonblock(snd_pcm_t *pcm, int nonblock)
 {
        /* FIXME */
        return 0;
 }
 
-static int snd_pcm_client_shm_info(void *private, snd_pcm_info_t * info)
+static int snd_pcm_client_shm_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int err;
 //     ctrl->u.info = *info;
        ctrl->cmd = SND_PCM_IOCTL_INFO;
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
-       memcpy(info, &ctrl->u.info, sizeof(*info));
+       *info = ctrl->u.info;
        return ctrl->result;
 }
 
-static int snd_pcm_client_shm_params_info(void *private, snd_pcm_params_info_t * info)
+static int snd_pcm_client_shm_params_info(snd_pcm_t *pcm, snd_pcm_params_info_t * info)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_PARAMS_INFO;
        ctrl->u.params_info = *info;
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        *info = ctrl->u.params_info;
        return ctrl->result;
 }
 
-static int snd_pcm_client_shm_params(void *private, snd_pcm_params_t * params)
+static int snd_pcm_client_shm_params(snd_pcm_t *pcm, snd_pcm_params_t * params)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_PARAMS;
        ctrl->u.params = *params;
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        *params = ctrl->u.params;
        return ctrl->result;
 }
 
-static int snd_pcm_client_shm_setup(void *private, snd_pcm_setup_t * setup)
+static int snd_pcm_client_shm_setup(snd_pcm_t *pcm, snd_pcm_setup_t * setup)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_SETUP;
        // ctrl->u.setup = *setup;
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        *setup = ctrl->u.setup;
        return ctrl->result;
 }
 
-static int snd_pcm_client_shm_channel_info(void *private, snd_pcm_channel_info_t * info)
+static int snd_pcm_client_shm_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_CHANNEL_INFO;
        ctrl->u.channel_info = *info;
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        *info = ctrl->u.channel_info;
        return ctrl->result;
 }
 
-static int snd_pcm_client_shm_channel_params(void *private, snd_pcm_channel_params_t * params)
+static int snd_pcm_client_shm_channel_params(snd_pcm_t *pcm, snd_pcm_channel_params_t * params)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_CHANNEL_PARAMS;
        ctrl->u.channel_params = *params;
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        *params = ctrl->u.channel_params;
        return ctrl->result;
 }
 
-static int snd_pcm_client_shm_channel_setup(void *private, snd_pcm_channel_setup_t * setup)
+static int snd_pcm_client_shm_channel_setup(snd_pcm_t *pcm, snd_pcm_channel_setup_t * setup)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_CHANNEL_SETUP;
        ctrl->u.channel_setup = *setup;
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        *setup = ctrl->u.channel_setup;
        return ctrl->result;
 }
 
-static int snd_pcm_client_shm_status(void *private, snd_pcm_status_t * status)
+static int snd_pcm_client_shm_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_STATUS;
        // ctrl->u.status = *status;
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        *status = ctrl->u.status;
        return ctrl->result;
 }
 
-static int snd_pcm_client_shm_state(void *private)
+static int snd_pcm_client_shm_state(snd_pcm_t *pcm)
 {
        snd_pcm_status_t status;
-       int err = snd_pcm_client_shm_status(private, &status);
+       int err = snd_pcm_client_shm_status(pcm, &status);
        if (err < 0)
                return err;
        return status.state;
 }
 
-static ssize_t snd_pcm_client_shm_frame_io(void *private, int update)
+static ssize_t snd_pcm_client_shm_frame_io(snd_pcm_t *pcm, int update)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_FRAME_IO;
        ctrl->u.frame_io = update;
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        return ctrl->result;
 }
 
-static int snd_pcm_client_shm_prepare(void *private)
+static int snd_pcm_client_shm_prepare(snd_pcm_t *pcm)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_PREPARE;
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        return ctrl->result;
 }
 
-static int snd_pcm_client_shm_go(void *private)
+static int snd_pcm_client_shm_go(snd_pcm_t *pcm)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_GO;
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        return ctrl->result;
 }
 
-static int snd_pcm_client_shm_drain(void *private)
+static int snd_pcm_client_shm_drain(snd_pcm_t *pcm)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_DRAIN;
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        return ctrl->result;
 }
 
-static int snd_pcm_client_shm_flush(void *private)
+static int snd_pcm_client_shm_flush(snd_pcm_t *pcm)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_FLUSH;
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        return ctrl->result;
 }
 
-static int snd_pcm_client_shm_pause(void *private, int enable)
+static int snd_pcm_client_shm_pause(snd_pcm_t *pcm, int enable)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_PAUSE;
        ctrl->u.pause = enable;
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        return ctrl->result;
 }
 
-static ssize_t snd_pcm_client_shm_frame_data(void *private, off_t offset)
+static ssize_t snd_pcm_client_shm_frame_data(snd_pcm_t *pcm, off_t offset)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_FRAME_DATA;
        ctrl->u.frame_data = offset;
-       clean_state(client);
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        return ctrl->result;
 }
 
-static ssize_t snd_pcm_client_shm_write(void *private, snd_timestamp_t *tstamp, const void *buffer, size_t size)
+static ssize_t snd_pcm_client_shm_write(snd_pcm_t *pcm, snd_timestamp_t *tstamp, const void *buffer, size_t size)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        size_t maxsize = PCM_SHM_DATA_MAXLEN;
-       size_t bytes = snd_pcm_frames_to_bytes(client->handle, size);
+       size_t bytes = snd_pcm_frames_to_bytes(pcm, size);
        int err;
        if (bytes > maxsize)
                return -EINVAL;
@@ -394,21 +398,20 @@ static ssize_t snd_pcm_client_shm_write(void *private, snd_timestamp_t *tstamp,
 //     ctrl->u.write.tstamp = *tstamp;
        ctrl->u.write.count = size;
        memcpy(ctrl->data, buffer, bytes);
-       clean_state(client);
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        return ctrl->result;
 }
 
-static ssize_t snd_pcm_client_shm_writev(void *private, snd_timestamp_t *tstamp, const struct iovec *vector, unsigned long count)
+static ssize_t snd_pcm_client_shm_writev(snd_pcm_t *pcm, snd_timestamp_t *tstamp, const struct iovec *vector, unsigned long count)
 {
        /* FIXME: interleaved */
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        size_t vecsize = count * sizeof(struct iovec);
        size_t maxsize = PCM_SHM_DATA_MAXLEN;
-       int bits_per_sample = client->handle->bits_per_sample;
+       int bits_per_sample = pcm->bits_per_sample;
        char *base;
        struct iovec *vec;
        unsigned long k;
@@ -430,44 +433,42 @@ static ssize_t snd_pcm_client_shm_writev(void *private, snd_timestamp_t *tstamp,
                vec[k].iov_base = (void *) ofs;
                ofs += len;
        }
-       clean_state(client);
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        return ctrl->result;
 }
 
-static ssize_t snd_pcm_client_shm_read(void *private, snd_timestamp_t *tstamp, void *buffer, size_t size)
+static ssize_t snd_pcm_client_shm_read(snd_pcm_t *pcm, snd_timestamp_t *tstamp, void *buffer, size_t size)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        size_t maxsize = PCM_SHM_DATA_MAXLEN;
-       size_t bytes = snd_pcm_frames_to_bytes(client->handle, size);
+       size_t bytes = snd_pcm_frames_to_bytes(pcm, size);
        int err;
        if (bytes > maxsize)
                return -EINVAL;
        ctrl->cmd = SND_PCM_IOCTL_READ_FRAMES;
 //     ctrl->u.read.tstamp = *tstamp;
        ctrl->u.read.count = size;
-       clean_state(client);
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        if (ctrl->result <= 0)
                return ctrl->result;
-       bytes = snd_pcm_frames_to_bytes(client->handle, ctrl->result);
+       bytes = snd_pcm_frames_to_bytes(pcm, ctrl->result);
        memcpy(buffer, ctrl->data, bytes);
        return ctrl->result;
 }
 
-ssize_t snd_pcm_client_shm_readv(void *private, snd_timestamp_t *tstamp, const struct iovec *vector, unsigned long count)
+ssize_t snd_pcm_client_shm_readv(snd_pcm_t *pcm, snd_timestamp_t *tstamp, const struct iovec *vector, unsigned long count)
 {
        /* FIXME: interleaved */
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        size_t vecsize = count * sizeof(struct iovec);
        size_t maxsize = PCM_SHM_DATA_MAXLEN;
-       int bits_per_sample = client->handle->bits_per_sample;
+       int bits_per_sample = pcm->bits_per_sample;
        char *base;
        struct iovec *vec;
        unsigned long k;
@@ -488,13 +489,12 @@ ssize_t snd_pcm_client_shm_readv(void *private, snd_timestamp_t *tstamp, const s
                vec[k].iov_base = (void *) ofs;
                ofs += len;
        }
-       clean_state(client);
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        if (ctrl->result <= 0)
                return ctrl->result;
-       bytes = snd_pcm_frames_to_bytes(client->handle, ctrl->result);
+       bytes = snd_pcm_frames_to_bytes(pcm, ctrl->result);
        ofs = 0;
        for (k = 0; k < count; ++k) {
                /* FIXME: optimize partial read */
@@ -505,14 +505,14 @@ ssize_t snd_pcm_client_shm_readv(void *private, snd_timestamp_t *tstamp, const s
        return ctrl->result;
 }
 
-static int snd_pcm_client_shm_mmap_status(void *private, snd_pcm_mmap_status_t **status)
+static int snd_pcm_client_shm_mmap_status(snd_pcm_t *pcm, snd_pcm_mmap_status_t **status)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        void *ptr;
        int fd;
        ctrl->cmd = SND_PCM_IOCTL_MMAP_STATUS;
-       fd = snd_pcm_client_shm_action_fd(client);
+       fd = snd_pcm_client_shm_action_fd(pcm);
        if (fd < 0)
                return fd;
        ptr = mmap(NULL, sizeof(snd_pcm_mmap_status_t), PROT_READ, MAP_FILE|MAP_SHARED, 
@@ -524,14 +524,14 @@ static int snd_pcm_client_shm_mmap_status(void *private, snd_pcm_mmap_status_t *
        return 0;
 }
 
-static int snd_pcm_client_shm_mmap_control(void *private, snd_pcm_mmap_control_t **control)
+static int snd_pcm_client_shm_mmap_control(snd_pcm_t *pcm, snd_pcm_mmap_control_t **control)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        void *ptr;
        int fd;
        ctrl->cmd = SND_PCM_IOCTL_MMAP_CONTROL;
-       fd = snd_pcm_client_shm_action_fd(client);
+       fd = snd_pcm_client_shm_action_fd(pcm);
        if (fd < 0)
                return fd;
        ptr = mmap(NULL, sizeof(snd_pcm_mmap_control_t), PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, 
@@ -543,18 +543,18 @@ static int snd_pcm_client_shm_mmap_control(void *private, snd_pcm_mmap_control_t
        return 0;
 }
 
-static int snd_pcm_client_shm_mmap_data(void *private, void **buffer, size_t bsize ATTRIBUTE_UNUSED)
+static int snd_pcm_client_shm_mmap_data(snd_pcm_t *pcm, void **buffer, size_t bsize ATTRIBUTE_UNUSED)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        void *ptr;
        int prot;
        int fd;
        ctrl->cmd = SND_PCM_IOCTL_MMAP_DATA;
-       fd = snd_pcm_client_shm_action_fd(client);
+       fd = snd_pcm_client_shm_action_fd(pcm);
        if (fd < 0)
                return fd;
-       prot = client->handle->stream == SND_PCM_STREAM_PLAYBACK ? PROT_WRITE : PROT_READ;
+       prot = pcm->stream == SND_PCM_STREAM_PLAYBACK ? PROT_WRITE : PROT_READ;
        ptr = mmap(NULL, bsize, prot, MAP_FILE|MAP_SHARED, 
                     fd, SND_PCM_MMAP_OFFSET_DATA);
        close(fd);
@@ -564,14 +564,14 @@ static int snd_pcm_client_shm_mmap_data(void *private, void **buffer, size_t bsi
        return 0;
 }
 
-static int snd_pcm_client_shm_munmap_status(void *private ATTRIBUTE_UNUSED, snd_pcm_mmap_status_t *status ATTRIBUTE_UNUSED)
+static int snd_pcm_client_shm_munmap_status(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_mmap_status_t *status ATTRIBUTE_UNUSED)
 {
 #if 0
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_MUNMAP_STATUS;
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        return ctrl->result;
@@ -582,14 +582,14 @@ static int snd_pcm_client_shm_munmap_status(void *private ATTRIBUTE_UNUSED, snd_
 #endif
 }
 
-static int snd_pcm_client_shm_munmap_control(void *private ATTRIBUTE_UNUSED, snd_pcm_mmap_control_t *control ATTRIBUTE_UNUSED)
+static int snd_pcm_client_shm_munmap_control(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_mmap_control_t *control ATTRIBUTE_UNUSED)
 {
 #if 0
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_MUNMAP_CONTROL;
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        return ctrl->result;
@@ -600,14 +600,14 @@ static int snd_pcm_client_shm_munmap_control(void *private ATTRIBUTE_UNUSED, snd
 #endif
 }
 
-static int snd_pcm_client_shm_munmap_data(void *private ATTRIBUTE_UNUSED, void *buffer, size_t bsize)
+static int snd_pcm_client_shm_munmap_data(snd_pcm_t *pcm ATTRIBUTE_UNUSED, void *buffer, size_t bsize)
 {
 #if 0
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_MUNMAP_DATA;
-       err = snd_pcm_client_shm_action(client);
+       err = snd_pcm_client_shm_action(pcm);
        if (err < 0)
                return err;
        return ctrl->result;
@@ -618,26 +618,24 @@ static int snd_pcm_client_shm_munmap_data(void *private ATTRIBUTE_UNUSED, void *
 #endif
 }
 
-static int snd_pcm_client_file_descriptor(void *private)
+static int snd_pcm_client_file_descriptor(snd_pcm_t *pcm)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
+       snd_pcm_client_t *client = pcm->private;
        return client->data_fd;
 }
 
-static int snd_pcm_client_channels_mask(void *private ATTRIBUTE_UNUSED,
+static int snd_pcm_client_channels_mask(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
                                        bitset_t *client_vmask ATTRIBUTE_UNUSED)
 {
        return 0;
 }
 
-static void snd_pcm_client_dump(void *private, FILE *fp)
+static void snd_pcm_client_dump(snd_pcm_t *pcm, FILE *fp)
 {
-       snd_pcm_client_t *client = (snd_pcm_client_t*) private;
-       snd_pcm_t *handle = client->handle;
        fprintf(fp, "Client PCM\n");
-       if (handle->valid_setup) {
+       if (pcm->valid_setup) {
                fprintf(fp, "\nIts setup is:\n");
-               snd_pcm_dump_setup(handle, fp);
+               snd_pcm_dump_setup(pcm, fp);
        }
 }
 
@@ -844,7 +842,6 @@ int snd_pcm_client_create(snd_pcm_t **handlep, char *host, int port, int transpo
                goto _err;
        }
 
-       client->handle = handle;
        client->data_fd = fds[0];
        client->ctrl_fd = fds[1];
        switch (transport) {
@@ -855,9 +852,9 @@ int snd_pcm_client_create(snd_pcm_t **handlep, char *host, int port, int transpo
        handle->type = SND_PCM_TYPE_CLIENT;
        handle->stream = stream;
        handle->ops = &snd_pcm_client_ops;
-       handle->op_arg = client;
+       handle->op_arg = handle;
        handle->fast_ops = &snd_pcm_client_fast_ops;
-       handle->fast_op_arg = client;
+       handle->fast_op_arg = handle;
        handle->mode = mode;
        handle->private = client;
        *handlep = handle;
index 1f49327739f8cee90a11c9ab258ddb589dcff5eb..dce890a9f016f19bdff377edaac33b83442857ef 100644 (file)
@@ -30,7 +30,6 @@
 #include "pcm_local.h"
 
 typedef struct {
-       snd_pcm_t *handle;
        int fd;
        int card, device, subdevice;
        void *mmap_data_ptr;
@@ -40,21 +39,21 @@ typedef struct {
 #define SND_FILE_PCM_STREAM_CAPTURE            "/dev/snd/pcmC%iD%ic"
 #define SND_PCM_VERSION_MAX    SND_PROTOCOL_VERSION(2, 0, 0)
 
-static int snd_pcm_hw_close(void *private)
+static int snd_pcm_hw_close(snd_pcm_t *pcm)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
-       free(private);
+       free(hw);
        if (fd >= 0)
                if (close(fd))
                        return -errno;
        return 0;
 }
 
-static int snd_pcm_hw_nonblock(void *private, int nonblock)
+static int snd_pcm_hw_nonblock(snd_pcm_t *pcm, int nonblock)
 {
        long flags;
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
 
        if ((flags = fcntl(fd, F_GETFL)) < 0)
@@ -68,63 +67,63 @@ static int snd_pcm_hw_nonblock(void *private, int nonblock)
        return 0;
 }
 
-static int snd_pcm_hw_info(void *private, snd_pcm_info_t * info)
+static int snd_pcm_hw_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
        if (ioctl(fd, SND_PCM_IOCTL_INFO, info) < 0)
                return -errno;
        return 0;
 }
 
-static int snd_pcm_hw_params_info(void *private, snd_pcm_params_info_t * info)
+static int snd_pcm_hw_params_info(snd_pcm_t *pcm, snd_pcm_params_info_t * info)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
        if (ioctl(fd, SND_PCM_IOCTL_PARAMS_INFO, info) < 0)
                return -errno;
        return 0;
 }
 
-static int snd_pcm_hw_params(void *private, snd_pcm_params_t * params)
+static int snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_params_t * params)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
        if (ioctl(fd, SND_PCM_IOCTL_PARAMS, params) < 0)
                return -errno;
        return 0;
 }
 
-static int snd_pcm_hw_setup(void *private, snd_pcm_setup_t * setup)
+static int snd_pcm_hw_setup(snd_pcm_t *pcm, snd_pcm_setup_t * setup)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
        if (ioctl(fd, SND_PCM_IOCTL_SETUP, setup) < 0)
                return -errno;
        return 0;
 }
 
-static int snd_pcm_hw_channel_info(void *private, snd_pcm_channel_info_t * info)
+static int snd_pcm_hw_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
        if (ioctl(fd, SND_PCM_IOCTL_CHANNEL_INFO, info) < 0)
                return -errno;
        return 0;
 }
 
-static int snd_pcm_hw_channel_params(void *private, snd_pcm_channel_params_t * params)
+static int snd_pcm_hw_channel_params(snd_pcm_t *pcm, snd_pcm_channel_params_t * params)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
        if (ioctl(fd, SND_PCM_IOCTL_CHANNEL_PARAMS, params) < 0)
                return -errno;
        return 0;
 }
 
-static int snd_pcm_hw_channel_setup(void *private, snd_pcm_channel_setup_t * setup)
+static int snd_pcm_hw_channel_setup(snd_pcm_t *pcm, snd_pcm_channel_setup_t * setup)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
        if (ioctl(fd, SND_PCM_IOCTL_CHANNEL_SETUP, setup) < 0)
                return -errno;
@@ -132,18 +131,18 @@ static int snd_pcm_hw_channel_setup(void *private, snd_pcm_channel_setup_t * set
        return 0;
 }
 
-static int snd_pcm_hw_status(void *private, snd_pcm_status_t * status)
+static int snd_pcm_hw_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
        if (ioctl(fd, SND_PCM_IOCTL_STATUS, status) < 0)
                return -errno;
        return 0;
 }
 
-static int snd_pcm_hw_state(void *private)
+static int snd_pcm_hw_state(snd_pcm_t *pcm)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
        snd_pcm_status_t status;
        if (ioctl(fd, SND_PCM_IOCTL_STATUS, status) < 0)
@@ -151,9 +150,9 @@ static int snd_pcm_hw_state(void *private)
        return status.state;
 }
 
-static ssize_t snd_pcm_hw_frame_io(void *private, int update ATTRIBUTE_UNUSED)
+static ssize_t snd_pcm_hw_frame_io(snd_pcm_t *pcm, int update ATTRIBUTE_UNUSED)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
        ssize_t pos = ioctl(fd, SND_PCM_IOCTL_FRAME_IO);
        if (pos < 0)
@@ -161,69 +160,68 @@ static ssize_t snd_pcm_hw_frame_io(void *private, int update ATTRIBUTE_UNUSED)
        return pos;
 }
 
-static int snd_pcm_hw_prepare(void *private)
+static int snd_pcm_hw_prepare(snd_pcm_t *pcm)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
        if (ioctl(fd, SND_PCM_IOCTL_PREPARE) < 0)
                return -errno;
        return 0;
 }
 
-static int snd_pcm_hw_go(void *private)
+static int snd_pcm_hw_go(snd_pcm_t *pcm)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
        if (ioctl(fd, SND_PCM_IOCTL_GO) < 0)
                return -errno;
        return 0;
 }
 
-static int snd_pcm_hw_drain(void *private)
+static int snd_pcm_hw_drain(snd_pcm_t *pcm)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
        if (ioctl(fd, SND_PCM_IOCTL_DRAIN) < 0)
                return -errno;
        return 0;
 }
 
-static int snd_pcm_hw_flush(void *private)
+static int snd_pcm_hw_flush(snd_pcm_t *pcm)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
        if (ioctl(fd, SND_PCM_IOCTL_FLUSH) < 0)
                return -errno;
        return 0;
 }
 
-static int snd_pcm_hw_pause(void *private, int enable)
+static int snd_pcm_hw_pause(snd_pcm_t *pcm, int enable)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
        if (ioctl(fd, SND_PCM_IOCTL_PAUSE, enable) < 0)
                return -errno;
        return 0;
 }
 
-static ssize_t snd_pcm_hw_frame_data(void *private, off_t offset)
+static ssize_t snd_pcm_hw_frame_data(snd_pcm_t *pcm, off_t offset)
 {
        ssize_t result;
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
-       snd_pcm_t *handle = hw->handle;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
-       if (handle->mmap_status && handle->mmap_control)
-               return snd_pcm_mmap_frame_data(handle, offset);
+       if (pcm->mmap_status && pcm->mmap_control)
+               return snd_pcm_mmap_frame_data(pcm, offset);
        result = ioctl(fd, SND_PCM_IOCTL_FRAME_DATA, offset);
        if (result < 0)
                return -errno;
        return result;
 }
 
-static ssize_t snd_pcm_hw_write(void *private, snd_timestamp_t *tstamp, const void *buffer, size_t size)
+static ssize_t snd_pcm_hw_write(snd_pcm_t *pcm, snd_timestamp_t *tstamp, const void *buffer, size_t size)
 {
        ssize_t result;
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
        snd_xfer_t xfer;
        if (tstamp)
@@ -238,10 +236,10 @@ static ssize_t snd_pcm_hw_write(void *private, snd_timestamp_t *tstamp, const vo
        return result;
 }
 
-static ssize_t snd_pcm_hw_writev(void *private, snd_timestamp_t *tstamp, const struct iovec *vector, unsigned long count)
+static ssize_t snd_pcm_hw_writev(snd_pcm_t *pcm, snd_timestamp_t *tstamp, const struct iovec *vector, unsigned long count)
 {
        ssize_t result;
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
        snd_xferv_t xferv;
        if (tstamp)
@@ -256,10 +254,10 @@ static ssize_t snd_pcm_hw_writev(void *private, snd_timestamp_t *tstamp, const s
        return result;
 }
 
-static ssize_t snd_pcm_hw_read(void *private, snd_timestamp_t *tstamp, void *buffer, size_t size)
+static ssize_t snd_pcm_hw_read(snd_pcm_t *pcm, snd_timestamp_t *tstamp, void *buffer, size_t size)
 {
        ssize_t result;
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
        snd_xfer_t xfer;
        if (tstamp)
@@ -274,10 +272,10 @@ static ssize_t snd_pcm_hw_read(void *private, snd_timestamp_t *tstamp, void *buf
        return result;
 }
 
-ssize_t snd_pcm_hw_readv(void *private, snd_timestamp_t *tstamp, const struct iovec *vector, unsigned long count)
+ssize_t snd_pcm_hw_readv(snd_pcm_t *pcm, snd_timestamp_t *tstamp, const struct iovec *vector, unsigned long count)
 {
        ssize_t result;
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        int fd = hw->fd;
        snd_xferv_t xferv;
        if (tstamp)
@@ -292,9 +290,9 @@ ssize_t snd_pcm_hw_readv(void *private, snd_timestamp_t *tstamp, const struct io
        return result;
 }
 
-static int snd_pcm_hw_mmap_status(void *private, snd_pcm_mmap_status_t **status)
+static int snd_pcm_hw_mmap_status(snd_pcm_t *pcm, snd_pcm_mmap_status_t **status)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        void *ptr;
        ptr = mmap(NULL, sizeof(snd_pcm_mmap_status_t), PROT_READ, MAP_FILE|MAP_SHARED, 
                   hw->fd, SND_PCM_MMAP_OFFSET_STATUS);
@@ -304,9 +302,9 @@ static int snd_pcm_hw_mmap_status(void *private, snd_pcm_mmap_status_t **status)
        return 0;
 }
 
-static int snd_pcm_hw_mmap_control(void *private, snd_pcm_mmap_control_t **control)
+static int snd_pcm_hw_mmap_control(snd_pcm_t *pcm, snd_pcm_mmap_control_t **control)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        void *ptr;
        ptr = mmap(NULL, sizeof(snd_pcm_mmap_control_t), PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, 
                   hw->fd, SND_PCM_MMAP_OFFSET_CONTROL);
@@ -316,12 +314,12 @@ static int snd_pcm_hw_mmap_control(void *private, snd_pcm_mmap_control_t **contr
        return 0;
 }
 
-static int snd_pcm_hw_mmap_data(void *private, void **buffer, size_t bsize)
+static int snd_pcm_hw_mmap_data(snd_pcm_t *pcm, void **buffer, size_t bsize)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        void *ptr;
        int prot;
-       prot = hw->handle->stream == SND_PCM_STREAM_PLAYBACK ? PROT_WRITE : PROT_READ;
+       prot = pcm->stream == SND_PCM_STREAM_PLAYBACK ? PROT_WRITE : PROT_READ;
        ptr = mmap(NULL, bsize, prot, MAP_FILE|MAP_SHARED, 
                     hw->fd, SND_PCM_MMAP_OFFSET_DATA);
        if (ptr == MAP_FAILED || ptr == NULL)
@@ -330,53 +328,52 @@ static int snd_pcm_hw_mmap_data(void *private, void **buffer, size_t bsize)
        return 0;
 }
 
-static int snd_pcm_hw_munmap_status(void *private ATTRIBUTE_UNUSED, snd_pcm_mmap_status_t *status)
+static int snd_pcm_hw_munmap_status(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_mmap_status_t *status)
 {
        if (munmap(status, sizeof(*status)) < 0)
                return -errno;
        return 0;
 }
 
-static int snd_pcm_hw_munmap_control(void *private ATTRIBUTE_UNUSED, snd_pcm_mmap_control_t *control)
+static int snd_pcm_hw_munmap_control(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_mmap_control_t *control)
 {
        if (munmap(control, sizeof(*control)) < 0)
                return -errno;
        return 0;
 }
 
-static int snd_pcm_hw_munmap_data(void *private, void *buffer, size_t bsize)
+static int snd_pcm_hw_munmap_data(snd_pcm_t *pcm, void *buffer, size_t bsize)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        if (munmap(buffer, bsize) < 0)
                return -errno;
        hw->mmap_data_ptr = NULL;
        return 0;
 }
 
-static int snd_pcm_hw_file_descriptor(void *private)
+static int snd_pcm_hw_file_descriptor(snd_pcm_t *pcm)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+       snd_pcm_hw_t *hw = pcm->private;
        return hw->fd;
 }
 
-static int snd_pcm_hw_channels_mask(void *private ATTRIBUTE_UNUSED,
+static int snd_pcm_hw_channels_mask(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
                                    bitset_t *client_vmask ATTRIBUTE_UNUSED)
 {
        return 0;
 }
 
-static void snd_pcm_hw_dump(void *private, FILE *fp)
+static void snd_pcm_hw_dump(snd_pcm_t *pcm, FILE *fp)
 {
-       snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
-       snd_pcm_t *handle = hw->handle;
+       snd_pcm_hw_t *hw = pcm->private;
        char *name = "Unknown";
        snd_card_get_name(hw->card, &name);
        fprintf(fp, "Hardware PCM card %d '%s' device %d subdevice %d\n",
                hw->card, name, hw->device, hw->subdevice);
        free(name);
-       if (handle->valid_setup) {
+       if (pcm->valid_setup) {
                fprintf(fp, "\nIts setup is:\n");
-               snd_pcm_dump_setup(handle, fp);
+               snd_pcm_dump_setup(pcm, fp);
        }
 }
 
@@ -433,7 +430,7 @@ int snd_pcm_hw_open_subdevice(snd_pcm_t **handlep, int card, int device, int sub
        assert(handlep);
        *handlep = 0;
 
-       if ((ret = snd_ctl_open(&ctl, card)) < 0)
+       if ((ret = snd_ctl_hw_open(&ctl, card)) < 0)
                return ret;
 
        switch (stream) {
@@ -492,7 +489,6 @@ int snd_pcm_hw_open_subdevice(snd_pcm_t **handlep, int card, int device, int sub
                ret = -ENOMEM;
                goto __end;
        }
-       hw->handle = handle;
        hw->card = card;
        hw->device = device;
        hw->subdevice = subdevice;
@@ -500,9 +496,9 @@ int snd_pcm_hw_open_subdevice(snd_pcm_t **handlep, int card, int device, int sub
        handle->type = SND_PCM_TYPE_HW;
        handle->stream = stream;
        handle->ops = &snd_pcm_hw_ops;
-       handle->op_arg = hw;
+       handle->op_arg = handle;
        handle->fast_ops = &snd_pcm_hw_fast_ops;
-       handle->fast_op_arg = hw;
+       handle->fast_op_arg = handle;
        handle->mode = mode;
        handle->private = hw;
        *handlep = handle;
index 3ab5d8ece35db16394b64ca6c600864a3872742b..4511af852495c408d5f68c18a42d4a9e1f7b1f0c 100644 (file)
 #include "asoundlib.h"
 
 struct snd_pcm_ops {
-       int (*close)(void *private);
-       int (*info)(void *private, snd_pcm_info_t *info);
-       int (*params_info)(void *private, snd_pcm_params_info_t *info);
-       int (*params)(void *private, snd_pcm_params_t *params);
-       int (*setup)(void *private, snd_pcm_setup_t *setup);
-       void (*dump)(void *private, FILE *fp);
+       int (*close)(snd_pcm_t *pcm);
+       int (*info)(snd_pcm_t *pcm, snd_pcm_info_t *info);
+       int (*params_info)(snd_pcm_t *pcm, snd_pcm_params_info_t *info);
+       int (*params)(snd_pcm_t *pcm, snd_pcm_params_t *params);
+       int (*setup)(snd_pcm_t *pcm, snd_pcm_setup_t *setup);
+       void (*dump)(snd_pcm_t *pcm, FILE *fp);
 };
 
 struct snd_pcm_fast_ops {
-       int (*nonblock)(void *private, int nonblock);
-       int (*status)(void *private, snd_pcm_status_t *status);
-       int (*channel_info)(void *private, snd_pcm_channel_info_t *info);
-       int (*channel_params)(void *private, snd_pcm_channel_params_t *params);
-       int (*channel_setup)(void *private, snd_pcm_channel_setup_t *setup);
-       int (*prepare)(void *private);
-       int (*go)(void *private);
-       int (*drain)(void *private);
-       int (*flush)(void *private);
-       int (*pause)(void *private, int enable);
-       int (*state)(void *private);
-       ssize_t (*frame_io)(void *private, int update);
-       ssize_t (*frame_data)(void *private, off_t offset);
-       ssize_t (*write)(void *private, snd_timestamp_t *tstamp, const void *buffer, size_t size);
-       ssize_t (*writev)(void *private, snd_timestamp_t *tstamp, const struct iovec *vector, unsigned long count);
-       ssize_t (*read)(void *private, snd_timestamp_t *tstamp, void *buffer, size_t size);
-       ssize_t (*readv)(void *private, snd_timestamp_t *tstamp, const struct iovec *vector, unsigned long count);
-       int (*file_descriptor)(void *private);
-       int (*channels_mask)(void *private, bitset_t *client_vmask);
-       int (*mmap_status)(void *private, snd_pcm_mmap_status_t **status);
-       int (*mmap_control)(void *private, snd_pcm_mmap_control_t **control);
-       int (*mmap_data)(void *private, void **buffer, size_t bsize);
-       int (*munmap_status)(void *private, snd_pcm_mmap_status_t *status);
-       int (*munmap_control)(void *private, snd_pcm_mmap_control_t *control);
-       int (*munmap_data)(void *private, void *buffer, size_t bsize);
+       int (*nonblock)(snd_pcm_t *pcm, int nonblock);
+       int (*status)(snd_pcm_t *pcm, snd_pcm_status_t *status);
+       int (*channel_info)(snd_pcm_t *pcm, snd_pcm_channel_info_t *info);
+       int (*channel_params)(snd_pcm_t *pcm, snd_pcm_channel_params_t *params);
+       int (*channel_setup)(snd_pcm_t *pcm, snd_pcm_channel_setup_t *setup);
+       int (*prepare)(snd_pcm_t *pcm);
+       int (*go)(snd_pcm_t *pcm);
+       int (*drain)(snd_pcm_t *pcm);
+       int (*flush)(snd_pcm_t *pcm);
+       int (*pause)(snd_pcm_t *pcm, int enable);
+       int (*state)(snd_pcm_t *pcm);
+       ssize_t (*frame_io)(snd_pcm_t *pcm, int update);
+       ssize_t (*frame_data)(snd_pcm_t *pcm, off_t offset);
+       ssize_t (*write)(snd_pcm_t *pcm, snd_timestamp_t *tstamp, const void *buffer, size_t size);
+       ssize_t (*writev)(snd_pcm_t *pcm, snd_timestamp_t *tstamp, const struct iovec *vector, unsigned long count);
+       ssize_t (*read)(snd_pcm_t *pcm, snd_timestamp_t *tstamp, void *buffer, size_t size);
+       ssize_t (*readv)(snd_pcm_t *pcm, snd_timestamp_t *tstamp, const struct iovec *vector, unsigned long count);
+       int (*file_descriptor)(snd_pcm_t *pcm);
+       int (*channels_mask)(snd_pcm_t *pcm, bitset_t *client_vmask);
+       int (*mmap_status)(snd_pcm_t *pcm, snd_pcm_mmap_status_t **status);
+       int (*mmap_control)(snd_pcm_t *pcm, snd_pcm_mmap_control_t **control);
+       int (*mmap_data)(snd_pcm_t *pcm, void **buffer, size_t bsize);
+       int (*munmap_status)(snd_pcm_t *pcm, snd_pcm_mmap_status_t *status);
+       int (*munmap_control)(snd_pcm_t *pcm, snd_pcm_mmap_control_t *control);
+       int (*munmap_data)(snd_pcm_t *pcm, void *buffer, size_t bsize);
 };
 
 struct snd_pcm {
@@ -73,9 +73,9 @@ struct snd_pcm {
        char *mmap_data;
        enum { _INTERLEAVED, _NONINTERLEAVED, _COMPLEX } mmap_type;
        struct snd_pcm_ops *ops;
-       void *op_arg;
        struct snd_pcm_fast_ops *fast_ops;
-       void *fast_op_arg;
+       snd_pcm_t *op_arg;
+       snd_pcm_t *fast_op_arg;
        void *private;
 };
 
index 6a84dd859d0cd8faa8427910cb84904a081b7dca..41c19e7440145e223e716094e12d6597e75ab2b5 100644 (file)
@@ -44,7 +44,6 @@ typedef struct {
 } snd_pcm_multi_bind_t;
 
 typedef struct {
-       snd_pcm_t *handle;
        size_t slaves_count;
        snd_pcm_multi_slave_t *slaves;
        size_t bindings_count;
@@ -55,9 +54,9 @@ typedef struct {
        int one_to_many;
 } snd_pcm_multi_t;
 
-static int snd_pcm_multi_close(void *private)
+static int snd_pcm_multi_close(snd_pcm_t *pcm)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        unsigned int i;
        int ret = 0;
        for (i = 0; i < multi->slaves_count; ++i) {
@@ -78,20 +77,20 @@ static int snd_pcm_multi_close(void *private)
        }
        free(multi->slaves);
        free(multi->bindings);
-       free(private);
+       free(multi);
        return ret;
 }
 
-static int snd_pcm_multi_nonblock(void *private, int nonblock)
+static int snd_pcm_multi_nonblock(snd_pcm_t *pcm, int nonblock)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        snd_pcm_t *handle = multi->slaves[0].handle;
        return snd_pcm_nonblock(handle, nonblock);
 }
 
-static int snd_pcm_multi_info(void *private, snd_pcm_info_t *info)
+static int snd_pcm_multi_info(snd_pcm_t *pcm, snd_pcm_info_t *info)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        unsigned int i;
        int err;
        snd_pcm_t *handle_0 = multi->slaves[0].handle;
@@ -112,9 +111,9 @@ static int snd_pcm_multi_info(void *private, snd_pcm_info_t *info)
        return 0;
 }
 
-static int snd_pcm_multi_params_info(void *private, snd_pcm_params_info_t *info)
+static int snd_pcm_multi_params_info(snd_pcm_t *pcm, snd_pcm_params_info_t *info)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        unsigned int i;
        int err;
        snd_pcm_t *handle_0 = multi->slaves[0].handle;
@@ -153,9 +152,9 @@ static int snd_pcm_multi_params_info(void *private, snd_pcm_params_info_t *info)
        return 0;
 }
 
-static int snd_pcm_multi_params(void *private, snd_pcm_params_t *params)
+static int snd_pcm_multi_params(snd_pcm_t *pcm, snd_pcm_params_t *params)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        unsigned int i;
        snd_pcm_params_t p;
        if (params->format.channels != multi->channels_count)
@@ -193,9 +192,9 @@ static int snd_pcm_multi_params(void *private, snd_pcm_params_t *params)
        return 0;
 }
 
-static int snd_pcm_multi_setup(void *private, snd_pcm_setup_t *setup)
+static int snd_pcm_multi_setup(snd_pcm_t *pcm, snd_pcm_setup_t *setup)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        unsigned int i;
        int err;
        size_t frames_alloc;
@@ -231,7 +230,7 @@ static int snd_pcm_multi_setup(void *private, snd_pcm_setup_t *setup)
                        free(s->iovec);
                if (!sh->setup.format.interleave) {
                        s->iovec = calloc(s->channels_total, sizeof(*s->iovec));
-                       if (!multi->handle->setup.format.interleave)
+                       if (!pcm->setup.format.interleave)
                                continue;
                }
                s->buf = malloc(frames_alloc * sh->bits_per_frame / 8);
@@ -262,61 +261,61 @@ static int snd_pcm_multi_setup(void *private, snd_pcm_setup_t *setup)
        return 0;
 }
 
-static int snd_pcm_multi_status(void *private, snd_pcm_status_t *status)
+static int snd_pcm_multi_status(snd_pcm_t *pcm, snd_pcm_status_t *status)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        snd_pcm_t *handle = multi->slaves[0].handle;
        return snd_pcm_status(handle, status);
 }
 
-static int snd_pcm_multi_state(void *private)
+static int snd_pcm_multi_state(snd_pcm_t *pcm)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        snd_pcm_t *handle = multi->slaves[0].handle;
        return snd_pcm_state(handle);
 }
 
-static ssize_t snd_pcm_multi_frame_io(void *private, int update)
+static ssize_t snd_pcm_multi_frame_io(snd_pcm_t *pcm, int update)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        snd_pcm_t *handle = multi->slaves[0].handle;
        return snd_pcm_frame_io(handle, update);
 }
 
-static int snd_pcm_multi_prepare(void *private)
+static int snd_pcm_multi_prepare(snd_pcm_t *pcm)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        return snd_pcm_prepare(multi->slaves[0].handle);
 }
 
-static int snd_pcm_multi_go(void *private)
+static int snd_pcm_multi_go(snd_pcm_t *pcm)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        return snd_pcm_go(multi->slaves[0].handle);
 }
 
-static int snd_pcm_multi_drain(void *private)
+static int snd_pcm_multi_drain(snd_pcm_t *pcm)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        return snd_pcm_drain(multi->slaves[0].handle);
 }
 
-static int snd_pcm_multi_flush(void *private)
+static int snd_pcm_multi_flush(snd_pcm_t *pcm)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        return snd_pcm_flush(multi->slaves[0].handle);
 }
 
-static int snd_pcm_multi_pause(void *private, int enable)
+static int snd_pcm_multi_pause(snd_pcm_t *pcm, int enable)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        return snd_pcm_pause(multi->slaves[0].handle, enable);
 }
 
-static int snd_pcm_multi_channel_info(void *private, snd_pcm_channel_info_t *info)
+static int snd_pcm_multi_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *info)
 {
        int err;
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        unsigned int channel = info->channel;
        unsigned int i;
        for (i = 0; i < multi->bindings_count; ++i) {
@@ -331,10 +330,10 @@ static int snd_pcm_multi_channel_info(void *private, snd_pcm_channel_info_t *inf
        return -EINVAL;
 }
 
-static int snd_pcm_multi_channel_params(void *private, snd_pcm_channel_params_t *params)
+static int snd_pcm_multi_channel_params(snd_pcm_t *pcm, snd_pcm_channel_params_t *params)
 {
        int err;
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        unsigned int channel = params->channel;
        unsigned int i;
        for (i = 0; i < multi->bindings_count; ++i) {
@@ -349,10 +348,10 @@ static int snd_pcm_multi_channel_params(void *private, snd_pcm_channel_params_t
        return -EINVAL;
 }
 
-static int snd_pcm_multi_channel_setup(void *private, snd_pcm_channel_setup_t *setup)
+static int snd_pcm_multi_channel_setup(snd_pcm_t *pcm, snd_pcm_channel_setup_t *setup)
 {
        int err;
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        unsigned int channel = setup->channel;
        unsigned int i;
        for (i = 0; i < multi->bindings_count; ++i) {
@@ -368,9 +367,9 @@ static int snd_pcm_multi_channel_setup(void *private, snd_pcm_channel_setup_t *s
        return 0;
 }
 
-static ssize_t snd_pcm_multi_frame_data(void *private, off_t offset)
+static ssize_t snd_pcm_multi_frame_data(snd_pcm_t *pcm, off_t offset)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        ssize_t pos, newpos;
        unsigned int i;
        snd_pcm_t *handle_0 = multi->slaves[0].handle;
@@ -395,21 +394,21 @@ static ssize_t snd_pcm_multi_frame_data(void *private, off_t offset)
        return newpos;
 }
 
-static int snd_pcm_multi_write_copy(snd_pcm_multi_t *multi, const void *buf,
+static int snd_pcm_multi_write_copy(snd_pcm_t *pcm, const void *buf,
                                    size_t offset, size_t count)
 {
+       snd_pcm_multi_t *multi = pcm->private;
        unsigned int i;
        snd_pcm_channel_area_t area;
-       snd_pcm_t *handle = multi->handle;
-       area.addr = (void *) buf + offset * handle->bits_per_frame;
-       area.step = handle->bits_per_frame;
+       area.addr = (void *) buf + offset * pcm->bits_per_frame;
+       area.step = pcm->bits_per_frame;
        for (i = 0; i < multi->bindings_count; ++i) {
                snd_pcm_multi_bind_t *bind = &multi->bindings[i];
                snd_pcm_multi_slave_t *slave = &multi->slaves[bind->slave];
                int err;
                assert(slave->buf);
-               area.first = handle->bits_per_sample * bind->client_channel;
-               err = snd_pcm_area_copy(&area, 0, &slave->areas[bind->slave_channel], 0, count, handle->setup.format.format);
+               area.first = pcm->bits_per_sample * bind->client_channel;
+               err = snd_pcm_area_copy(&area, 0, &slave->areas[bind->slave_channel], 0, count, pcm->setup.format.format);
                if (err < 0)
                        return err;
                if (!slave->handle->setup.format.interleave) {
@@ -420,23 +419,23 @@ static int snd_pcm_multi_write_copy(snd_pcm_multi_t *multi, const void *buf,
        return 0;
 }
 
-static int snd_pcm_multi_writev_copy(snd_pcm_multi_t *multi, const struct iovec *vec,
+static int snd_pcm_multi_writev_copy(snd_pcm_t *pcm, const struct iovec *vec,
                                     size_t offset, size_t count)
 {
+       snd_pcm_multi_t *multi = pcm->private;
        unsigned int i;
        snd_pcm_channel_area_t area;
-       snd_pcm_t *handle = multi->handle;
        area.first = 0;
-       area.step = handle->bits_per_sample;
+       area.step = pcm->bits_per_sample;
        for (i = 0; i < multi->bindings_count; ++i) {
                snd_pcm_multi_bind_t *bind = &multi->bindings[i];
                snd_pcm_multi_slave_t *slave = &multi->slaves[bind->slave];
                int err;
                area.addr = vec[bind->client_channel].iov_base + 
-                       offset * handle->bits_per_sample;
+                       offset * pcm->bits_per_sample;
                if (slave->handle->setup.format.interleave) {
                        assert(slave->buf);
-                       err = snd_pcm_area_copy(&area, 0, &slave->areas[bind->slave_channel], 0, count, handle->setup.format.format);
+                       err = snd_pcm_area_copy(&area, 0, &slave->areas[bind->slave_channel], 0, count, pcm->setup.format.format);
                        if (err < 0)
                                return err;
                } else {
@@ -448,8 +447,9 @@ static int snd_pcm_multi_writev_copy(snd_pcm_multi_t *multi, const struct iovec
        return 0;
 }
 
-static ssize_t snd_pcm_multi_write_io(snd_pcm_multi_t *multi, size_t count)
+static ssize_t snd_pcm_multi_write_io(snd_pcm_t *pcm, size_t count)
 {
+       snd_pcm_multi_t *multi = pcm->private;
        unsigned int i;
        ssize_t frames = count;
        for (i = 0; i < multi->slaves_count; ++i) {
@@ -467,9 +467,9 @@ static ssize_t snd_pcm_multi_write_io(snd_pcm_multi_t *multi, size_t count)
        return frames;
 }
 
-static ssize_t snd_pcm_multi_write(void *private, snd_timestamp_t *timestamp ATTRIBUTE_UNUSED, const void *buf, size_t count)
+static ssize_t snd_pcm_multi_write(snd_pcm_t *pcm, snd_timestamp_t *timestamp ATTRIBUTE_UNUSED, const void *buf, size_t count)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        size_t result = 0;
        while (count > 0) {
                int err;
@@ -477,10 +477,10 @@ static ssize_t snd_pcm_multi_write(void *private, snd_timestamp_t *timestamp ATT
                size_t frames = count;
                if (frames > multi->frames_alloc)
                        frames = multi->frames_alloc;
-               err = snd_pcm_multi_write_copy(multi, buf, result, frames);
+               err = snd_pcm_multi_write_copy(pcm, buf, result, frames);
                if (err < 0)
                        return err;
-               ret = snd_pcm_multi_write_io(multi, frames);
+               ret = snd_pcm_multi_write_io(pcm, frames);
                if (ret > 0)
                        result += ret;
                if (ret != (ssize_t)frames) {
@@ -493,8 +493,9 @@ static ssize_t snd_pcm_multi_write(void *private, snd_timestamp_t *timestamp ATT
        return result;
 }
 
-static ssize_t snd_pcm_multi_writev1(snd_pcm_multi_t *multi, const struct iovec *vector, size_t count)
+static ssize_t snd_pcm_multi_writev1(snd_pcm_t *pcm, const struct iovec *vector, size_t count)
 {
+       snd_pcm_multi_t *multi = pcm->private;
        size_t result = 0;
        while (count > 0) {
                int err;
@@ -502,10 +503,10 @@ static ssize_t snd_pcm_multi_writev1(snd_pcm_multi_t *multi, const struct iovec
                size_t frames = count;
                if (frames > multi->frames_alloc)
                        frames = multi->frames_alloc;
-               err = snd_pcm_multi_writev_copy(multi, vector, result, frames);
+               err = snd_pcm_multi_writev_copy(pcm, vector, result, frames);
                if (err < 0)
                        return err;
-               ret = snd_pcm_multi_write_io(multi, frames);
+               ret = snd_pcm_multi_write_io(pcm, frames);
                if (ret > 0)
                        result += ret;
                if (ret != (ssize_t) frames) {
@@ -518,22 +519,20 @@ static ssize_t snd_pcm_multi_writev1(snd_pcm_multi_t *multi, const struct iovec
        return result;
 }
 
-static ssize_t snd_pcm_multi_writev(void *private, snd_timestamp_t *timestamp ATTRIBUTE_UNUSED, const struct iovec *vector, unsigned long count)
+static ssize_t snd_pcm_multi_writev(snd_pcm_t *pcm, snd_timestamp_t *timestamp ATTRIBUTE_UNUSED, const struct iovec *vector, unsigned long count)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
-       snd_pcm_t *handle = multi->handle;
        unsigned int k, step;
        size_t result = 0;
-       if (handle->setup.format.interleave)
+       if (pcm->setup.format.interleave)
                step = 1;
        else
-               step = handle->setup.format.channels;
+               step = pcm->setup.format.channels;
        for (k = 0; k < count; k += step) {
                ssize_t ret;
-               if (handle->setup.format.interleave)
-                       ret = snd_pcm_multi_write(private, timestamp, vector->iov_base, vector->iov_len);
+               if (pcm->setup.format.interleave)
+                       ret = snd_pcm_multi_write(pcm, timestamp, vector->iov_base, vector->iov_len);
                else
-                       ret = snd_pcm_multi_writev1(multi, vector, vector->iov_len);
+                       ret = snd_pcm_multi_writev1(pcm, vector, vector->iov_len);
                if (ret > 0)
                        result += ret;
                if (ret != (ssize_t) vector->iov_len) {
@@ -546,21 +545,21 @@ static ssize_t snd_pcm_multi_writev(void *private, snd_timestamp_t *timestamp AT
        return result;
 }
 
-static ssize_t snd_pcm_multi_read(void *private ATTRIBUTE_UNUSED, snd_timestamp_t *timestamp ATTRIBUTE_UNUSED, void *buf ATTRIBUTE_UNUSED, size_t count ATTRIBUTE_UNUSED)
+static ssize_t snd_pcm_multi_read(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_timestamp_t *timestamp ATTRIBUTE_UNUSED, void *buf ATTRIBUTE_UNUSED, size_t count ATTRIBUTE_UNUSED)
 {
-       // snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       // snd_pcm_multi_t *multi = pcm->private;
        return -ENOSYS;
 }
 
-static ssize_t snd_pcm_multi_readv(void *private ATTRIBUTE_UNUSED, snd_timestamp_t *timestamp ATTRIBUTE_UNUSED, const struct iovec *vector ATTRIBUTE_UNUSED, unsigned long count ATTRIBUTE_UNUSED)
+static ssize_t snd_pcm_multi_readv(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_timestamp_t *timestamp ATTRIBUTE_UNUSED, const struct iovec *vector ATTRIBUTE_UNUSED, unsigned long count ATTRIBUTE_UNUSED)
 {
-       // snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       // snd_pcm_multi_t *multi = pcm->private;
        return -ENOSYS;
 }
 
-static int snd_pcm_multi_mmap_status(void *private, snd_pcm_mmap_status_t **status)
+static int snd_pcm_multi_mmap_status(snd_pcm_t *pcm, snd_pcm_mmap_status_t **status)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        unsigned int i;
        for (i = 0; i < multi->slaves_count; ++i) {
                snd_pcm_t *handle = multi->slaves[i].handle;
@@ -572,9 +571,9 @@ static int snd_pcm_multi_mmap_status(void *private, snd_pcm_mmap_status_t **stat
        return 0;
 }
 
-static int snd_pcm_multi_mmap_control(void *private, snd_pcm_mmap_control_t **control)
+static int snd_pcm_multi_mmap_control(snd_pcm_t *pcm, snd_pcm_mmap_control_t **control)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        snd_pcm_setup_t *setup_0 = &multi->slaves[0].handle->setup;
        unsigned int i;
        for (i = 1; i < multi->slaves_count; ++i) {
@@ -594,9 +593,9 @@ static int snd_pcm_multi_mmap_control(void *private, snd_pcm_mmap_control_t **co
        return 0;
 }
 
-static int snd_pcm_multi_mmap_data(void *private, void **buffer, size_t bsize ATTRIBUTE_UNUSED)
+static int snd_pcm_multi_mmap_data(snd_pcm_t *pcm, void **buffer, size_t bsize ATTRIBUTE_UNUSED)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        unsigned int i;
        for (i = 0; i < multi->slaves_count; ++i) {
                snd_pcm_t *handle = multi->slaves[i].handle;
@@ -619,9 +618,9 @@ static int snd_pcm_multi_mmap_data(void *private, void **buffer, size_t bsize AT
        return 0;
 }
 
-static int snd_pcm_multi_munmap_status(void *private, snd_pcm_mmap_status_t *status ATTRIBUTE_UNUSED)
+static int snd_pcm_multi_munmap_status(snd_pcm_t *pcm, snd_pcm_mmap_status_t *status ATTRIBUTE_UNUSED)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        unsigned int i;
        int ret = 0;
        for (i = 0; i < multi->slaves_count; ++i) {
@@ -633,9 +632,9 @@ static int snd_pcm_multi_munmap_status(void *private, snd_pcm_mmap_status_t *sta
        return ret;
 }
                
-static int snd_pcm_multi_munmap_control(void *private, snd_pcm_mmap_control_t *control ATTRIBUTE_UNUSED)
+static int snd_pcm_multi_munmap_control(snd_pcm_t *pcm, snd_pcm_mmap_control_t *control ATTRIBUTE_UNUSED)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        unsigned int i;
        int ret = 0;
        for (i = 0; i < multi->slaves_count; ++i) {
@@ -647,9 +646,9 @@ static int snd_pcm_multi_munmap_control(void *private, snd_pcm_mmap_control_t *c
        return ret;
 }
                
-static int snd_pcm_multi_munmap_data(void *private, void *buffer ATTRIBUTE_UNUSED, size_t size ATTRIBUTE_UNUSED)
+static int snd_pcm_multi_munmap_data(snd_pcm_t *pcm, void *buffer ATTRIBUTE_UNUSED, size_t size ATTRIBUTE_UNUSED)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        unsigned int i;
        int ret = 0;
        for (i = 0; i < multi->slaves_count; ++i) {
@@ -661,9 +660,9 @@ static int snd_pcm_multi_munmap_data(void *private, void *buffer ATTRIBUTE_UNUSE
        return ret;
 }
                
-static int snd_pcm_multi_channels_mask(void *private, bitset_t *client_vmask)
+static int snd_pcm_multi_channels_mask(snd_pcm_t *pcm, bitset_t *client_vmask)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        unsigned int i;
        bitset_t *vmasks[multi->slaves_count];
        int err;
@@ -683,7 +682,7 @@ static int snd_pcm_multi_channels_mask(void *private, bitset_t *client_vmask)
                        return err;
                }
        }
-       bitset_zero(client_vmask, multi->handle->setup.format.channels);
+       bitset_zero(client_vmask, pcm->setup.format.channels);
        for (i = 0; i < multi->bindings_count; ++i) {
                snd_pcm_multi_bind_t *b = &multi->bindings[i];
                if (bitset_get(vmasks[b->slave], b->slave_channel))
@@ -694,22 +693,21 @@ static int snd_pcm_multi_channels_mask(void *private, bitset_t *client_vmask)
        return 0;
 }
                
-int snd_pcm_multi_file_descriptor(void *private)
+int snd_pcm_multi_file_descriptor(snd_pcm_t *pcm)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+       snd_pcm_multi_t *multi = pcm->private;
        snd_pcm_t *handle = multi->slaves[0].handle;
        return snd_pcm_file_descriptor(handle);
 }
 
-static void snd_pcm_multi_dump(void *private, FILE *fp)
+static void snd_pcm_multi_dump(snd_pcm_t *pcm, FILE *fp)
 {
-       snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
-       snd_pcm_t *handle = multi->handle;
+       snd_pcm_multi_t *multi = pcm->private;
        unsigned int k;
        fprintf(fp, "Multi PCM\n");
-       if (handle->valid_setup) {
+       if (pcm->valid_setup) {
                fprintf(fp, "\nIts setup is:\n");
-               snd_pcm_dump_setup(handle, fp);
+               snd_pcm_dump_setup(pcm, fp);
        }
        for (k = 0; k < multi->slaves_count; ++k) {
                fprintf(fp, "\nSlave #%d: ", k);
@@ -790,7 +788,6 @@ int snd_pcm_multi_create(snd_pcm_t **handlep, size_t slaves_count,
 
        stream = slaves_handle[0]->stream;
        
-       multi->handle = handle;
        multi->slaves_count = slaves_count;
        multi->slaves = calloc(slaves_count, sizeof(*multi->slaves));
        multi->bindings_count = bindings_count;
@@ -830,9 +827,9 @@ int snd_pcm_multi_create(snd_pcm_t **handlep, size_t slaves_count,
        handle->stream = stream;
        handle->mode = multi->slaves[0].handle->mode;
        handle->ops = &snd_pcm_multi_ops;
-       handle->op_arg = multi;
+       handle->op_arg = handle;
        handle->fast_ops = &snd_pcm_multi_fast_ops;
-       handle->fast_op_arg = multi;
+       handle->fast_op_arg = handle;
        handle->private = multi;
        *handlep = handle;
        return 0;
index a7d03e1c8fc2caf8fcac086b9285a086399bbde1..a4387e92e05d952853aa40903156c938b4fdcf80 100644 (file)
@@ -129,27 +129,27 @@ snd_pcm_plugin_t *snd_pcm_plug_last(snd_pcm_plug_t *plug)
  *
  */
 
-static int snd_pcm_plug_close(void *private)
+static int snd_pcm_plug_close(snd_pcm_t *pcm)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
        snd_pcm_plug_clear(plug);
        free(plug->handle->fast_ops);
        if (plug->close_slave)
                return snd_pcm_close(plug->slave);
-       free(private);
+       free(plug);
        return 0;
 }
 
-static int snd_pcm_plug_nonblock(void *private, int nonblock)
+static int snd_pcm_plug_nonblock(snd_pcm_t *pcm, int nonblock)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
        return snd_pcm_nonblock(plug->slave, nonblock);
 }
 
-static int snd_pcm_plug_info(void *private, snd_pcm_info_t *info)
+static int snd_pcm_plug_info(snd_pcm_t *pcm, snd_pcm_info_t *info)
 {
        int err;
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
        
        if ((err = snd_pcm_info(plug->slave, info)) < 0)
                return err;
@@ -158,10 +158,10 @@ static int snd_pcm_plug_info(void *private, snd_pcm_info_t *info)
        return 0;
 }
 
-static int snd_pcm_plug_params_info(void *private, snd_pcm_params_info_t *info)
+static int snd_pcm_plug_params_info(snd_pcm_t *pcm, snd_pcm_params_info_t *info)
 {
        int err;
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
        snd_pcm_params_info_t slave_info;
        int rate;
        int slave_format, slave_rate;
@@ -260,10 +260,10 @@ static int snd_pcm_plug_action(snd_pcm_plug_t *plug, int action,
        return 0;
 }
 
-static int snd_pcm_plug_setup(void *private, snd_pcm_setup_t *setup)
+static int snd_pcm_plug_setup(snd_pcm_t *pcm, snd_pcm_setup_t *setup)
 {
        int err;
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
 
        err = snd_pcm_setup(plug->slave, setup);
        if (err < 0)
@@ -292,10 +292,10 @@ static int snd_pcm_plug_setup(void *private, snd_pcm_setup_t *setup)
        return 0;       
 }
 
-static int snd_pcm_plug_status(void *private, snd_pcm_status_t *status)
+static int snd_pcm_plug_status(snd_pcm_t *pcm, snd_pcm_status_t *status)
 {
        int err;
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
 
        err = snd_pcm_status(plug->slave, status);
        if (err < 0)
@@ -308,24 +308,24 @@ static int snd_pcm_plug_status(void *private, snd_pcm_status_t *status)
        return 0;       
 }
 
-static int snd_pcm_plug_state(void *private)
+static int snd_pcm_plug_state(snd_pcm_t *pcm)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
        return snd_pcm_state(plug->slave);
 }
 
-static ssize_t snd_pcm_plug_frame_io(void *private, int update)
+static ssize_t snd_pcm_plug_frame_io(snd_pcm_t *pcm, int update)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
        ssize_t frame_io = snd_pcm_frame_io(plug->slave, update);
        if (frame_io < 0)
                return frame_io;
        return snd_pcm_plug_client_size(plug, frame_io);
 }
 
-static int snd_pcm_plug_prepare(void *private)
+static int snd_pcm_plug_prepare(snd_pcm_t *pcm)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
        int err;
        err = snd_pcm_prepare(plug->slave);
        if (err < 0)
@@ -335,15 +335,15 @@ static int snd_pcm_plug_prepare(void *private)
        return 0;
 }
 
-static int snd_pcm_plug_go(void *private)
+static int snd_pcm_plug_go(snd_pcm_t *pcm)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
        return snd_pcm_go(plug->slave);
 }
 
-static int snd_pcm_plug_drain(void *private)
+static int snd_pcm_plug_drain(snd_pcm_t *pcm)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
        int err;
 
        if ((err = snd_pcm_drain(plug->slave)) < 0)
@@ -353,9 +353,9 @@ static int snd_pcm_plug_drain(void *private)
        return 0;
 }
 
-static int snd_pcm_plug_flush(void *private)
+static int snd_pcm_plug_flush(snd_pcm_t *pcm)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
        int err;
 
        if ((err = snd_pcm_flush(plug->slave)) < 0)
@@ -365,9 +365,9 @@ static int snd_pcm_plug_flush(void *private)
        return 0;
 }
 
-static int snd_pcm_plug_pause(void *private, int enable)
+static int snd_pcm_plug_pause(snd_pcm_t *pcm, int enable)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
        int err;
        
        if ((err = snd_pcm_pause(plug->slave, enable)) < 0)
@@ -377,31 +377,31 @@ static int snd_pcm_plug_pause(void *private, int enable)
        return 0;
 }
 
-static int snd_pcm_plug_channel_info(void *private ATTRIBUTE_UNUSED, snd_pcm_channel_info_t *info ATTRIBUTE_UNUSED)
+static int snd_pcm_plug_channel_info(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_channel_info_t *info ATTRIBUTE_UNUSED)
 {
        /* FIXME: if route plugin is not inserted or its ttable is trivial
           this should be implemented */
        return -ENOSYS;
 }
 
-static int snd_pcm_plug_channel_params(void *private ATTRIBUTE_UNUSED, snd_pcm_channel_params_t *params ATTRIBUTE_UNUSED)
+static int snd_pcm_plug_channel_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_channel_params_t *params ATTRIBUTE_UNUSED)
 {
        /* FIXME: if route plugin is not inserted or its ttable is trivial
           this should be implemented */
        return -ENOSYS;
 }
 
-static int snd_pcm_plug_channel_setup(void *private ATTRIBUTE_UNUSED, snd_pcm_channel_setup_t *setup ATTRIBUTE_UNUSED)
+static int snd_pcm_plug_channel_setup(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_channel_setup_t *setup ATTRIBUTE_UNUSED)
 {
        /* FIXME: if route plugin is not inserted or its ttable is trivial
           this should be implemented for non mmap setups */
        return -ENOSYS;
 }
 
-static ssize_t snd_pcm_plug_frame_data(void *private, off_t offset)
+static ssize_t snd_pcm_plug_frame_data(snd_pcm_t *pcm, off_t offset)
 {
        ssize_t ret;
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
        if (offset < 0) {
                offset = snd_pcm_plug_slave_size(plug, -offset);
                if (offset < 0)
@@ -418,9 +418,9 @@ static ssize_t snd_pcm_plug_frame_data(void *private, off_t offset)
        return snd_pcm_plug_client_size(plug, ret);
 }
   
-ssize_t snd_pcm_plug_writev(void *private, snd_timestamp_t *tstamp ATTRIBUTE_UNUSED, const struct iovec *vector, unsigned long count)
+ssize_t snd_pcm_plug_writev(snd_pcm_t *pcm, snd_timestamp_t *tstamp ATTRIBUTE_UNUSED, const struct iovec *vector, unsigned long count)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
        snd_pcm_t *handle = plug->handle;
        unsigned int k, step;
        size_t result = 0;
@@ -462,9 +462,9 @@ ssize_t snd_pcm_plug_writev(void *private, snd_timestamp_t *tstamp ATTRIBUTE_UNU
        return result;
 }
 
-ssize_t snd_pcm_plug_readv(void *private, snd_timestamp_t *tstamp ATTRIBUTE_UNUSED, const struct iovec *vector, unsigned long count)
+ssize_t snd_pcm_plug_readv(snd_pcm_t *pcm, snd_timestamp_t *tstamp ATTRIBUTE_UNUSED, const struct iovec *vector, unsigned long count)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
        snd_pcm_t *handle = plug->handle;
        unsigned int k, step;
        size_t result = 0;
@@ -506,9 +506,9 @@ ssize_t snd_pcm_plug_readv(void *private, snd_timestamp_t *tstamp ATTRIBUTE_UNUS
        return result;
 }
 
-ssize_t snd_pcm_plug_write(void *private, snd_timestamp_t *tstamp ATTRIBUTE_UNUSED, const void *buf, size_t count)
+ssize_t snd_pcm_plug_write(snd_pcm_t *pcm, snd_timestamp_t *tstamp ATTRIBUTE_UNUSED, const void *buf, size_t count)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
        snd_pcm_t *handle = plug->handle;
        ssize_t frames;
        snd_pcm_plugin_channel_t *channels;
@@ -540,9 +540,9 @@ ssize_t snd_pcm_plug_write(void *private, snd_timestamp_t *tstamp ATTRIBUTE_UNUS
        return size;
 }
 
-ssize_t snd_pcm_plug_read(void *private, snd_timestamp_t *tstamp ATTRIBUTE_UNUSED, void *buf, size_t count)
+ssize_t snd_pcm_plug_read(snd_pcm_t *pcm, snd_timestamp_t *tstamp ATTRIBUTE_UNUSED, void *buf, size_t count)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
        snd_pcm_t *handle = plug->handle;
        ssize_t frames;
        snd_pcm_plugin_channel_t *channels;
@@ -574,55 +574,55 @@ ssize_t snd_pcm_plug_read(void *private, snd_timestamp_t *tstamp ATTRIBUTE_UNUSE
        return size;
 }
 
-static int snd_pcm_plug_mmap_status(void *private ATTRIBUTE_UNUSED, snd_pcm_mmap_status_t **status ATTRIBUTE_UNUSED)
+static int snd_pcm_plug_mmap_status(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_mmap_status_t **status ATTRIBUTE_UNUSED)
 {
        return -EBADFD;
 }
 
-static int snd_pcm_plug_mmap_control(void *private ATTRIBUTE_UNUSED, snd_pcm_mmap_control_t **control ATTRIBUTE_UNUSED)
+static int snd_pcm_plug_mmap_control(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_mmap_control_t **control ATTRIBUTE_UNUSED)
 {
        return -EBADFD;
 }
 
-static int snd_pcm_plug_mmap_data(void *private ATTRIBUTE_UNUSED, void **buffer ATTRIBUTE_UNUSED, size_t bsize ATTRIBUTE_UNUSED)
+static int snd_pcm_plug_mmap_data(snd_pcm_t *pcm ATTRIBUTE_UNUSED, void **buffer ATTRIBUTE_UNUSED, size_t bsize ATTRIBUTE_UNUSED)
 {
        return -EBADFD;
 }
 
-static int snd_pcm_plug_munmap_status(void *private ATTRIBUTE_UNUSED, snd_pcm_mmap_status_t *status ATTRIBUTE_UNUSED)
+static int snd_pcm_plug_munmap_status(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_mmap_status_t *status ATTRIBUTE_UNUSED)
 {
        return -EBADFD;
 }
                
-static int snd_pcm_plug_munmap_control(void *private ATTRIBUTE_UNUSED, snd_pcm_mmap_control_t *control ATTRIBUTE_UNUSED)
+static int snd_pcm_plug_munmap_control(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_mmap_control_t *control ATTRIBUTE_UNUSED)
 {
        return -EBADFD;
 }
                
-static int snd_pcm_plug_munmap_data(void *private ATTRIBUTE_UNUSED, void *buffer ATTRIBUTE_UNUSED, size_t size ATTRIBUTE_UNUSED)
+static int snd_pcm_plug_munmap_data(snd_pcm_t *pcm ATTRIBUTE_UNUSED, void *buffer ATTRIBUTE_UNUSED, size_t size ATTRIBUTE_UNUSED)
 {
        return -EBADFD;
 }
                
-static int snd_pcm_plug_channels_mask(void *private,
+static int snd_pcm_plug_channels_mask(snd_pcm_t *pcm,
                                    bitset_t *client_vmask)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
        if (plug->handle->stream == SND_PCM_STREAM_PLAYBACK)
                return snd_pcm_plug_playback_channels_mask(plug, client_vmask);
        else
                return snd_pcm_plug_capture_channels_mask(plug, client_vmask);
 }
 
-int snd_pcm_plug_file_descriptor(void *private)
+int snd_pcm_plug_file_descriptor(snd_pcm_t *pcm)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
        return snd_pcm_file_descriptor(plug->slave);
 }
 
-static void snd_pcm_plug_dump(void *private, FILE *fp)
+static void snd_pcm_plug_dump(snd_pcm_t *pcm, FILE *fp)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_t *plug = pcm->private;
        snd_pcm_t *handle = plug->handle;
        snd_pcm_plugin_t *plugin;
        if (!plug->first) {
@@ -644,7 +644,7 @@ static void snd_pcm_plug_dump(void *private, FILE *fp)
        fprintf(fp, "\n");
 }
 
-static int snd_pcm_plug_params(void *private, snd_pcm_params_t *params);
+static int snd_pcm_plug_params(snd_pcm_t *pcm, snd_pcm_params_t *params);
 
 struct snd_pcm_ops snd_pcm_plug_ops = {
        close: snd_pcm_plug_close,
@@ -706,7 +706,7 @@ static void snd_pcm_plug_slave_params(snd_pcm_plug_t *plug,
 
 
 
-static int snd_pcm_plug_params(void *private, snd_pcm_params_t *params)
+static int snd_pcm_plug_params(snd_pcm_t *pcm, snd_pcm_params_t *params)
 {
        snd_pcm_params_t slave_params;
        snd_pcm_info_t slave_info;
@@ -717,7 +717,7 @@ static int snd_pcm_plug_params(void *private, snd_pcm_params_t *params)
        int err;
        int first = 1;
        
-       plug = (snd_pcm_plug_t*) private;
+       plug = pcm->private;
 
        /*
         *  try to decide, if a conversion is required
@@ -776,7 +776,7 @@ static int snd_pcm_plug_params(void *private, snd_pcm_params_t *params)
        }
 
        *plug->handle->fast_ops = snd_pcm_plug_fast_ops;
-       plug->handle->fast_op_arg = plug;
+       plug->handle->fast_op_arg = pcm;
 
        /*
         *  I/O plugins
@@ -826,10 +826,10 @@ int snd_pcm_plug_create(snd_pcm_t **handlep, snd_pcm_t *slave, int close_slave)
        handle->type = SND_PCM_TYPE_PLUG;
        handle->stream = slave->stream;
        handle->ops = &snd_pcm_plug_ops;
-       handle->op_arg = plug;
+       handle->op_arg = handle;
        handle->fast_ops = malloc(sizeof(*handle->fast_ops));
        *handle->fast_ops = snd_pcm_plug_fast_ops;
-       handle->fast_op_arg = plug;
+       handle->fast_op_arg = handle;
        handle->mode = slave->mode;
        handle->private = plug;
        *handlep = handle;