]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Fixed mmap wrt shm. Renamed pcm_client, control_client to shm. More error messages...
authorAbramo Bagnara <abramo@alsa-project.org>
Sat, 14 Oct 2000 10:31:34 +0000 (10:31 +0000)
committerAbramo Bagnara <abramo@alsa-project.org>
Sat, 14 Oct 2000 10:31:34 +0000 (10:31 +0000)
30 files changed:
TODO
aserver/aserver.c
include/aserver.h
include/control.h
include/pcm.h
src/control/Makefile.am
src/control/cards.c
src/control/control.c
src/control/control_client.c [deleted file]
src/control/control_hw.c
src/control/control_local.h
src/control/control_shm.c [new file with mode: 0644]
src/pcm/Makefile.am
src/pcm/pcm.c
src/pcm/pcm_adpcm.c
src/pcm/pcm_alaw.c
src/pcm/pcm_client.c [deleted file]
src/pcm/pcm_file.c
src/pcm/pcm_hw.c
src/pcm/pcm_linear.c
src/pcm/pcm_local.h
src/pcm/pcm_mmap.c
src/pcm/pcm_mulaw.c
src/pcm/pcm_multi.c
src/pcm/pcm_plug.c
src/pcm/pcm_plugin.c
src/pcm/pcm_plugin.h
src/pcm/pcm_rate.c
src/pcm/pcm_route.c
src/pcm/pcm_share.c

diff --git a/TODO b/TODO
index 201b441b4c563282c0271e5b805297cc2e8a450e..c50d46bece443fe2b484edafda65672db89bd434 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,3 +1,2 @@
-H solve multi/server mmap'ing problem
 M add abstraction layer to timer, rawmidi, hwdep, seq
 L move OSS emulation to user space? (pseudo device driver and daemon)
index 7f54885e0f450b0f26481b846942af1f7a3f1519..a35570c4da8c75f5184b3fe17f62be29013ed5e4 100644 (file)
 #include <stddef.h>
 #include <getopt.h>
 #include <netinet/in.h>
+#include <netdb.h>
 
 #include "asoundlib.h"
-#include "pcm_local.h"
 #include "aserver.h"
 #include "list.h"
 
 char *command;
 
 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
-#define error(...) do {\
-       fprintf(stderr, "%s: %s:%d: ", command, __FUNCTION__, __LINE__); \
+#define ERROR(...) do {\
+       fprintf(stderr, "%s %s:%i:(%s) ", command, __FILE__, __LINE__, __FUNCTION__); \
        fprintf(stderr, __VA_ARGS__); \
        putc('\n', stderr); \
 } while (0)
 #else
-#define error(args...) do {\
-       fprintf(stderr, "%s: %s:%d: ", command, __FUNCTION__, __LINE__); \
+#define ERROR(args...) do {\
+       fprintf(stderr, "%s %s:%i:(%s) ", command, __FILE__, __LINE__, __FUNCTION__); \
        fprintf(stderr, ##args); \
        putc('\n', stderr); \
 } while (0)
 #endif 
 
-#define perrno(string) error("%s", strerror(errno))
+#define SYSERR(string) ERROR(string ": %s", strerror(errno))
 
 int make_local_socket(const char *filename)
 {
@@ -65,7 +65,7 @@ int make_local_socket(const char *filename)
        sock = socket(PF_LOCAL, SOCK_STREAM, 0);
        if (sock < 0) {
                int result = -errno;
-               perrno("socket");
+               SYSERR("socket");
                return result;
        }
        
@@ -76,7 +76,7 @@ int make_local_socket(const char *filename)
 
        if (bind(sock, (struct sockaddr *) addr, size) < 0) {
                int result = -errno;
-               perrno("bind");
+               SYSERR("bind");
                return result;
        }
 
@@ -91,7 +91,7 @@ int make_inet_socket(int port)
        sock = socket(PF_INET, SOCK_STREAM, 0);
        if (sock < 0) {
                int result = -errno;
-               perrno("socket");
+               SYSERR("socket");
                return result;
        }
        
@@ -101,7 +101,7 @@ int make_inet_socket(int port)
 
        if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
                int result = -errno;
-               perrno("bind");
+               SYSERR("bind");
                return result;
        }
 
@@ -135,7 +135,7 @@ int send_fd(int socket, void *data, size_t len, int fd)
 
     ret = sendmsg(socket, &msghdr, 0 );
     if (ret < 0) {
-           perrno("sendmsg");
+           SYSERR("sendmsg");
            return -errno;
     }
     return ret;
@@ -182,13 +182,6 @@ void del_waiter(int fd)
        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 {
@@ -199,10 +192,9 @@ typedef struct {
 
 struct client {
        struct list_head list;
-       struct socket {
-               int fd;
-               int local;
-       } data, ctrl;
+       int poll_fd;
+       int ctrl_fd;
+       int local;
        int transport_type;
        int dev_type;
        char name[256];
@@ -250,9 +242,8 @@ typedef struct {
        struct list_head list;
        int fd;
        uint32_t cookie;
-       int local;
-} pending_t;
-LIST_HEAD(pendings);
+} inet_pending_t;
+LIST_HEAD(inet_pendings);
 
 int pcm_handler(waiter_t *waiter, unsigned short events)
 {
@@ -260,15 +251,15 @@ int pcm_handler(waiter_t *waiter, unsigned short events)
        char buf[1];
        ssize_t n;
        if (events & POLLIN) {
-               n = write(client->data.fd, buf, 1);
+               n = write(client->poll_fd, buf, 1);
                if (n != 1) {
-                       perrno("write");
+                       SYSERR("write");
                        return -errno;
                }
        } else if (events & POLLOUT) {
-               n = read(client->data.fd, buf, 1);
+               n = read(client->poll_fd, buf, 1);
                if (n != 1) {
-                       perrno("read");
+                       SYSERR("read");
                        return -errno;
                }
        }
@@ -283,7 +274,7 @@ int pcm_shm_open(client_t *client, int *cookie)
        snd_pcm_t *pcm;
        int err;
        int result;
-       err = snd_pcm_open(&pcm, client->name, client->stream, client->mode);
+       err = snd_pcm_open(&pcm, client->name, client->stream, SND_PCM_NONBLOCK);
        if (err < 0)
                return err;
        client->device.pcm.handle = pcm;
@@ -292,7 +283,7 @@ int pcm_shm_open(client_t *client, int *cookie)
        shmid = shmget(IPC_PRIVATE, PCM_SHM_SIZE, 0666);
        if (shmid < 0) {
                result = -errno;
-               perrno("shmget");
+               SYSERR("shmget");
                goto _err;
        }
        client->transport.shm.ctrl_id = shmid;
@@ -300,7 +291,7 @@ int pcm_shm_open(client_t *client, int *cookie)
        if (!client->transport.shm.ctrl) {
                result = -errno;
                shmctl(shmid, IPC_RMID, 0);
-               perrno("shmat");
+               SYSERR("shmat");
                goto _err;
        }
        *cookie = shmid;
@@ -315,38 +306,66 @@ int pcm_shm_open(client_t *client, int *cookie)
 int pcm_shm_close(client_t *client)
 {
        int err;
-       snd_pcm_client_shm_t *ctrl = client->transport.shm.ctrl;
+       snd_pcm_shm_ctrl_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;
        if (err < 0) 
-               perrno("snd_pcm_close");
+               SYSERR("snd_pcm_close");
        if (client->transport.shm.ctrl) {
                err = shmdt((void *)client->transport.shm.ctrl);
                if (err < 0)
-                       perrno("shmdt");
+                       SYSERR("shmdt");
                err = shmctl(client->transport.shm.ctrl_id, IPC_RMID, 0);
                if (err < 0)
-                       perrno("shmctl");
+                       SYSERR("shmctl");
                client->transport.shm.ctrl = 0;
        }
        client->open = 0;
        return 0;
 }
 
-int pcm_shm_cmd(client_t *client)
+int shm_ack(client_t *client)
 {
-       snd_pcm_client_shm_t *ctrl = client->transport.shm.ctrl;
        struct pollfd pfd;
+       int err;
+       char buf[1];
+       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;
+       return 0;
+}
+
+int shm_ack_fd(client_t *client, int fd)
+{
+       struct pollfd pfd;
+       int err;
+       char buf[1];
+       pfd.fd = client->ctrl_fd;
+       pfd.events = POLLHUP;
+       if (poll(&pfd, 1, 0) == 1)
+               return -EBADFD;
+       err = send_fd(client->ctrl_fd, buf, 1, fd);
+       if (err != 1)
+               return -EBADFD;
+       return 0;
+}
+
+int pcm_shm_cmd(client_t *client)
+{
+       snd_pcm_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
        char buf[1];
        int err;
        int cmd;
        snd_pcm_t *pcm;
-       err = read(client->ctrl.fd, buf, 1);
+       err = read(client->ctrl_fd, buf, 1);
        if (err != 1)
                return -EBADFD;
        cmd = ctrl->cmd;
@@ -409,63 +428,74 @@ int pcm_shm_cmd(client_t *client)
                break;
        case SND_PCM_IOCTL_LINK:
        {
-               struct list_head *item;
-               list_for_each(item, &clients) {
-                       client_t *client = list_entry(item, client_t, list);
-                       if (!client->open)
-                               continue;
-                       if (client->data.fd == ctrl->u.link) {
-                               ctrl->result = snd_pcm_link(pcm, client->device.pcm.handle);
-                               break;
-                       }
-               }
-               ctrl->result = -EBADFD;
+               /* FIXME */
+               ctrl->result = -ENOSYS;
                break;
        }
        case SND_PCM_IOCTL_UNLINK:
                ctrl->result = snd_pcm_unlink(pcm);
                break;
-       case SND_PCM_IOCTL_MMAP_DATA:
-       case SND_PCM_IOCTL_MMAP_CONTROL:
-       case SND_PCM_IOCTL_MMAP_STATUS:
+       case SND_PCM_IOCTL_MMAP:
        {
-               pfd.fd = client->ctrl.fd;
-               pfd.events = POLLHUP;
-               if (poll(&pfd, 1, 0) == 1)
-                       return -EBADFD;
-               err = send_fd(client->ctrl.fd, buf, 1, client->device.pcm.fd);
-               if (err != 1)
-                       return -EBADFD;
-               ctrl->result = 0;
-               return 0;
+               err = snd_pcm_mmap(pcm);
+               if (err < 0)
+                       ctrl->result = err;
+               else
+                       ctrl->result = pcm->mmap_info_count;
+               break;
        }
-       case SND_PCM_IOCTL_MUNMAP_DATA:
-       case SND_PCM_IOCTL_MUNMAP_CONTROL:
-       case SND_PCM_IOCTL_MUNMAP_STATUS:
+       case SND_PCM_IOCTL_MMAP_INFO:
+       {
+               snd_pcm_mmap_info_t *i;
+               unsigned int index = ctrl->u.mmap_info.index;
+               if (index >= pcm->mmap_info_count) {
+                       ctrl->result = -EINVAL;
+                       break;
+               }
+               i = &pcm->mmap_info[index];
+               if (i->type == SND_PCM_MMAP_USER) {
+                       i->u.user.shmid = shmget(IPC_PRIVATE, i->size, 0666);
+                       if (i->u.user.shmid < 0) {
+                               SYSERR("shmget");
+                               return -EINVAL;
+                       }
+               }
+               ctrl->u.mmap_info = *i;
+               ctrl->u.mmap_info.index = index;
                ctrl->result = 0;
+               if (i->type == SND_PCM_MMAP_USER)
+                       break;
+               return shm_ack_fd(client, i->u.kernel.fd);
+       }
+       case SND_PCM_IOCTL_MUNMAP:
+       {
+               size_t k;
+               ctrl->result = snd_pcm_munmap(pcm);
+               if (ctrl->result < 0)
+                       break;
+               for (k = 0; k < pcm->mmap_info_count; ++k) {
+                       snd_pcm_mmap_info_t *i = &pcm->mmap_info[k];
+                       if (i->type == SND_PCM_MMAP_USER) {
+                               int err = shmdt(i->addr);
+                               assert(err >= 0);
+                       }
+               }
                break;
+       }
        case SND_PCM_IOCTL_MMAP_FORWARD:
                ctrl->result = snd_pcm_mmap_forward(pcm, ctrl->u.mmap_forward);
                break;
+       case SND_PCM_IOCTL_POLL_DESCRIPTOR:
+               ctrl->result = 0;
+               return shm_ack_fd(client, snd_pcm_poll_descriptor(pcm));
        case SND_PCM_IOCTL_CLOSE:
                client->ops->close(client);
                break;
        default:
-               fprintf(stderr, "Bogus cmd: %x\n", ctrl->cmd);
+               ERROR("Bogus cmd: %x", 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.pcm.fd, POLLIN | POLLOUT, pcm_handler, client);
-               client->polling = 1;
-       }
-       return 0;
+       return shm_ack(client);
 }
 
 transport_ops_t pcm_shm_ops = {
@@ -480,9 +510,9 @@ int ctl_handler(waiter_t *waiter, unsigned short events)
        char buf[1];
        ssize_t n;
        if (events & POLLIN) {
-               n = write(client->data.fd, buf, 1);
+               n = write(client->poll_fd, buf, 1);
                if (n != 1) {
-                       perrno("write");
+                       SYSERR("write");
                        return -errno;
                }
        }
@@ -506,7 +536,7 @@ int ctl_shm_open(client_t *client, int *cookie)
        shmid = shmget(IPC_PRIVATE, CTL_SHM_SIZE, 0666);
        if (shmid < 0) {
                result = -errno;
-               perrno("shmget");
+               SYSERR("shmget");
                goto _err;
        }
        client->transport.shm.ctrl_id = shmid;
@@ -514,7 +544,7 @@ int ctl_shm_open(client_t *client, int *cookie)
        if (!client->transport.shm.ctrl) {
                result = -errno;
                shmctl(shmid, IPC_RMID, 0);
-               perrno("shmat");
+               SYSERR("shmat");
                goto _err;
        }
        *cookie = shmid;
@@ -531,23 +561,22 @@ int ctl_shm_open(client_t *client, int *cookie)
 int ctl_shm_close(client_t *client)
 {
        int err;
-       snd_ctl_client_shm_t *ctrl = client->transport.shm.ctrl;
+       snd_ctl_shm_ctrl_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");
+               SYSERR("snd_ctl_close");
        if (client->transport.shm.ctrl) {
                err = shmdt((void *)client->transport.shm.ctrl);
                if (err < 0)
-                       perrno("shmdt");
+                       SYSERR("shmdt");
                err = shmctl(client->transport.shm.ctrl_id, IPC_RMID, 0);
                if (err < 0)
-                       perrno("shmctl");
+                       SYSERR("shmctl");
                client->transport.shm.ctrl = 0;
        }
        client->open = 0;
@@ -558,13 +587,12 @@ 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;
+       snd_ctl_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
        char buf[1];
        int err;
        int cmd;
        snd_ctl_t *ctl;
-       err = read(client->ctrl.fd, buf, 1);
+       err = read(client->ctrl_fd, buf, 1);
        if (err != 1)
                return -EBADFD;
        cmd = ctrl->cmd;
@@ -612,22 +640,14 @@ int ctl_shm_cmd(client_t *client)
        case SND_CTL_IOCTL_CLOSE:
                client->ops->close(client);
                break;
+       case SND_PCM_IOCTL_POLL_DESCRIPTOR:
+               ctrl->result = 0;
+               return shm_ack_fd(client, snd_ctl_poll_descriptor(ctl));
        default:
-               fprintf(stderr, "Bogus cmd: %x\n", ctrl->cmd);
+               ERROR("Bogus cmd: %x", 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;
+       return shm_ack(client);
 }
 
 transport_ops_t ctl_shm_ops = {
@@ -643,9 +663,9 @@ int snd_client_open(client_t *client)
        snd_client_open_answer_t ans;
        char *name;
        memset(&ans, 0, sizeof(ans));
-       err = read(client->ctrl.fd, &req, sizeof(req));
+       err = read(client->ctrl_fd, &req, sizeof(req));
        if (err < 0) {
-               perrno("read");
+               SYSERR("read");
                exit(1);
        }
        if (err != sizeof(req)) {
@@ -653,9 +673,9 @@ int snd_client_open(client_t *client)
                goto _answer;
        }
        name = alloca(req.namelen);
-       err = read(client->ctrl.fd, name, req.namelen);
+       err = read(client->ctrl_fd, name, req.namelen);
        if (err < 0) {
-               perrno("read");
+               SYSERR("read");
                exit(1);
        }
        if (err != req.namelen) {
@@ -663,20 +683,17 @@ int snd_client_open(client_t *client)
                goto _answer;
        }
 
-       switch (req.dev_type) {
-       case SND_DEV_TYPE_PCM:
-               switch (req.transport_type) {
-               case SND_TRANSPORT_TYPE_SHM:
-                       client->ops = &pcm_shm_ops;
-                       break;
-               default:
+       switch (req.transport_type) {
+       case SND_TRANSPORT_TYPE_SHM:
+               if (!client->local) {
                        ans.result = -EINVAL;
                        goto _answer;
                }
-               break;
-       case SND_DEV_TYPE_CONTROL:
-               switch (req.transport_type) {
-               case SND_TRANSPORT_TYPE_SHM:
+               switch (req.dev_type) {
+               case SND_DEV_TYPE_PCM:
+                       client->ops = &pcm_shm_ops;
+                       break;
+               case SND_DEV_TYPE_CONTROL:
                        client->ops = &ctl_shm_ops;
                        break;
                default:
@@ -701,27 +718,27 @@ int snd_client_open(client_t *client)
                ans.result = err;
        } else {
                client->open = 1;
-               ans.result = client->data.fd;
+               ans.result = 0;
        }
 
  _answer:
-       err = write(client->ctrl.fd, &ans, sizeof(ans));
+       err = write(client->ctrl_fd, &ans, sizeof(ans));
        if (err != sizeof(ans)) {
-               perrno("write");
+               SYSERR("write");
                exit(1);
        }
        return 0;
 }
 
-int client_data_handler(waiter_t *waiter, unsigned short events ATTRIBUTE_UNUSED)
+int client_poll_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);
+       close(client->poll_fd);
+       close(client->ctrl_fd);
+       del_waiter(client->poll_fd);
+       del_waiter(client->ctrl_fd);
        list_del(&client->list);
        free(client);
        return 0;
@@ -730,18 +747,25 @@ int client_data_handler(waiter_t *waiter, unsigned short events ATTRIBUTE_UNUSED
 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 (events & POLLHUP) {
+               if (client->open)
+                       client->ops->close(client);
+               close(client->ctrl_fd);
+               del_waiter(client->ctrl_fd);
+               list_del(&client->list);
+               free(client);
+               return 0;
+       }
        if (client->open)
                return client->ops->cmd(client);
        else
                return snd_client_open(client);
 }
 
-int pending_handler(waiter_t *waiter, unsigned short events)
+int inet_pending_handler(waiter_t *waiter, unsigned short events)
 {
-       pending_t *pending = waiter->private_data;
-       pending_t *pdata;
+       inet_pending_t *pending = waiter->private_data;
+       inet_pending_t *pdata;
        client_t *client;
        uint32_t cookie;
        struct list_head *item;
@@ -766,8 +790,8 @@ int pending_handler(waiter_t *waiter, unsigned short events)
                return 0;
        }
 
-       list_for_each(item, &pendings) {
-               pdata = list_entry(item, pending_t, list);
+       list_for_each(item, &inet_pendings) {
+               pdata = list_entry(item, inet_pending_t, list);
                if (pdata->cookie == cookie)
                        goto found;
        }
@@ -775,13 +799,12 @@ int pending_handler(waiter_t *waiter, unsigned short events)
        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 = calloc(1, sizeof(*client));
+       client->local = 0;
+       client->poll_fd = pdata->fd;
+       client->ctrl_fd = waiter->fd;
+       add_waiter(client->ctrl_fd, POLLIN | POLLHUP, client_ctrl_handler, client);
+       add_waiter(client->poll_fd, POLLHUP, client_poll_handler, client);
        client->open = 0;
        list_add_tail(&client->list, &clients);
        list_del(&pending->list);
@@ -791,70 +814,81 @@ int pending_handler(waiter_t *waiter, unsigned short events)
        return 0;
 }
 
-int master_handler(waiter_t *waiter, unsigned short events ATTRIBUTE_UNUSED)
+int local_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");
+               SYSERR("accept");
                return result;
        } else {
-               pending_t *pending = calloc(sizeof(*pending), 1);
+               client_t *client = calloc(1, sizeof(*client));
+               client->ctrl_fd = sock;
+               client->local = 1;
+               client->open = 0;
+               add_waiter(sock, POLLIN | POLLHUP, client_ctrl_handler, client);
+               list_add_tail(&client->list, &clients);
+       }
+       return 0;
+}
+
+int inet_handler(waiter_t *waiter, unsigned short events ATTRIBUTE_UNUSED)
+{
+       int sock;
+       sock = accept(waiter->fd, 0, 0);
+       if (sock < 0) {
+               int result = -errno;
+               SYSERR("accept");
+               return result;
+       } else {
+               inet_pending_t *pending = calloc(1, sizeof(*pending));
                pending->fd = sock;
-               pending->local = master->local;
                pending->cookie = 0;
-               add_waiter(sock, POLLIN, pending_handler, pending);
-               list_add_tail(&pending->list, &pendings);
+               add_waiter(sock, POLLIN, inet_pending_handler, pending);
+               list_add_tail(&pending->list, &inet_pendings);
        }
        return 0;
 }
 
 int server(char *sockname, int port)
 {
-       struct list_head *item;
        int err;
        unsigned int k;
 
+       if (!sockname && port < 0)
+               return -EINVAL;
        if (sockname) {
                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 (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
+                       int result = -errno;
+                       SYSERR("fcntl");
+                       return result;
+               }
+               if (listen(sock, 4) < 0) {
+                       int result = -errno;
+                       SYSERR("listen");
+                       return result;
+               }
+               add_waiter(sock, POLLIN, local_handler, NULL);
        }
        if (port >= 0) {
                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 (list_empty(&masters))
-               return -EINVAL;
-
-       list_for_each(item, &masters) {
-               master_t *master = list_entry(item, master_t, list);
-               if (fcntl(master->fd, F_SETFL, O_NONBLOCK) < 0) {
+               if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
                        int result = -errno;
-                       perrno("fcntl");
+                       SYSERR("fcntl");
                        return result;
                }
-               if (listen(master->fd, 4) < 0) {
+               if (listen(sock, 4) < 0) {
                        int result = -errno;
-                       perrno("listen");
+                       SYSERR("listen");
                        return result;
                }
+               add_waiter(sock, POLLIN, inet_handler, NULL);
        }
 
        while (1) {
@@ -864,7 +898,7 @@ int server(char *sockname, int port)
                        err = poll(pollfds, pollfds_count, 1000);
                } while (err == 0);
                if (err < 0) {
-                       perrno("poll");
+                       SYSERR("poll");
                        continue;
                }
 
@@ -878,7 +912,7 @@ int server(char *sockname, int port)
                                        continue;
                                err = w->handler(w, pfd->revents);
                                if (err < 0)
-                                       perrno("handler");
+                                       SYSERR("handler");
                        }
                }
        }
@@ -889,47 +923,102 @@ int server(char *sockname, int port)
 void usage()
 {
        fprintf(stderr, "\
-Usage: %s [OPTIONS]
+Usage: %s [OPTIONS] server
 
 --help                 help
---version              print current version
--l,--local SOCKNAME    local socket name
--p,--port PORT         port number
 ", command);
 }
 
+extern int is_local(struct hostent *hent);
+
 int main(int argc, char **argv)
 {
        static struct option long_options[] = {
-               {"local", 1, 0, 'l'},
-               {"port", 1, 0, 'p'},
                {"help", 0, 0, 'h'}
        };
        int c;
-       char *local = NULL;
-       int port = -1;
+       snd_config_t *conf;
+       snd_config_iterator_t i;
+       char *socket = NULL;
+       char *host = NULL;
+       long port = -1;
+       int err;
+       char *srvname;
+       struct hostent *h;
        command = argv[0];
-       while ((c = getopt_long(argc, argv, "hl:p:", long_options, 0)) != -1) {
+       while ((c = getopt_long(argc, argv, "h", long_options, 0)) != -1) {
                switch (c) {
                case 'h':
                        usage();
                        return 0;
-               case 'l':
-                       local = optarg;
-                       break;
-               case 'p':
-                       port = atoi(optarg);
-                       break;
                default:
                        fprintf(stderr, "Try `%s --help' for more information\n", command);
                        return 1;
                }
        }
-       if (!local && port == -1) {
-               fprintf(stderr, "%s: you need to specify at least one master socket\n", command);
+       if (argc - optind != 1) {
+               ERROR("you need to specify server name");
                return 1;
        }
-
-       server(local, port);
+       err = snd_config_update();
+       if (err < 0) {
+               ERROR("cannot read configuration file");
+               return 1;
+       }
+       srvname = argv[optind];
+       err = snd_config_searchv(snd_config, &conf, "server", srvname, 0);
+       if (err < 0) {
+               ERROR("unknown server %s", srvname);
+               return 1;
+       }
+       snd_config_foreach(i, conf) {
+               snd_config_t *n = snd_config_entry(i);
+               if (strcmp(n->id, "comment") == 0)
+                       continue;
+               if (strcmp(n->id, "host") == 0) {
+                       err = snd_config_string_get(n, &host);
+                       if (err < 0) {
+                               ERROR("Invalid type for host");
+                               return 1;
+                       }
+                       continue;
+               }
+               if (strcmp(n->id, "socket") == 0) {
+                       err = snd_config_string_get(n, &socket);
+                       if (err < 0) {
+                               ERROR("Invalid type for socket");
+                               return 1;
+                       }
+                       continue;
+               }
+               if (strcmp(n->id, "port") == 0) {
+                       err = snd_config_integer_get(n, &port);
+                       if (err < 0) {
+                               ERROR("Invalid type for port");
+                               return 1;
+                       }
+                       continue;
+               }
+               ERROR("Unknown field: %s", n->id);
+               return 1;
+       }
+       if (!host) {
+               ERROR("host is not defined");
+               return 1;
+       }
+       h = gethostbyname(host);
+       if (!h) {
+               ERROR("Cannot resolve %s", host);
+               return 1;
+       }
+       if (!is_local(h)) {
+               ERROR("%s is not the local host", host);
+               return 1;
+       }
+       if (!socket && port < 0) {
+               ERROR("either socket or port need to be defined");
+               return 1;
+       }
+       server(socket, port);
        return 0;
 }
index d48caf52ba85809d52e2089fe8e5d2b0dab3f53e..9a68b0d766d4d03d0f232abe738fd8783d1e05ca 100644 (file)
  */
   
 
+#include "../src/pcm/pcm_local.h"
+
 #define SND_PCM_IOCTL_STATE            _IO ('A', 0xf0)
-#define SND_PCM_IOCTL_MMAP_DATA                _IO ('A', 0xf1)
-#define SND_PCM_IOCTL_MMAP_CONTROL     _IO ('A', 0xf2)
-#define SND_PCM_IOCTL_MMAP_STATUS      _IO ('A', 0xf3)
-#define SND_PCM_IOCTL_MUNMAP_DATA      _IO ('A', 0xf4)
-#define SND_PCM_IOCTL_MUNMAP_CONTROL   _IO ('A', 0xf5)
-#define SND_PCM_IOCTL_MUNMAP_STATUS    _IO ('A', 0xf6)
+#define SND_PCM_IOCTL_MMAP             _IO ('A', 0xf1)
+#define SND_PCM_IOCTL_MUNMAP           _IO ('A', 0xf4)
 #define SND_PCM_IOCTL_MMAP_FORWARD     _IO ('A', 0xf7)
 #define SND_PCM_IOCTL_AVAIL_UPDATE     _IO ('A', 0xf8)
 #define SND_PCM_IOCTL_ASYNC            _IO ('A', 0xf9)
 #define SND_PCM_IOCTL_CLOSE            _IO ('A', 0xfa)
+#define SND_PCM_IOCTL_MMAP_INFO                _IO ('A', 0xfb)
+#define SND_PCM_IOCTL_POLL_DESCRIPTOR  _IO ('A', 0xfc)
 
 typedef struct {
        long result;
@@ -39,6 +39,7 @@ typedef struct {
                        int sig;
                        pid_t pid;
                } async;
+               snd_pcm_mmap_info_t mmap_info;
                snd_pcm_info_t info;
                snd_pcm_params_t params;
                snd_pcm_params_info_t params_info;
@@ -54,13 +55,13 @@ typedef struct {
                size_t mmap_forward;
        } u;
        char data[0];
-} snd_pcm_client_shm_t;
+} snd_pcm_shm_ctrl_t;
 
-#define PCM_SHM_SIZE 65536
-#define PCM_SHM_DATA_MAXLEN (PCM_SHM_SIZE - offsetof(snd_pcm_client_shm_t, data))
+#define PCM_SHM_SIZE sizeof(snd_pcm_shm_ctrl_t)
                
 #define SND_CTL_IOCTL_READ             _IOR('U', 0xf0, snd_ctl_event_t)
 #define SND_CTL_IOCTL_CLOSE            _IO ('U', 0xf1)
+#define SND_CTL_IOCTL_POLL_DESCRIPTOR  _IO ('U', 0xf2)
 
 typedef struct {
        int result;
@@ -78,10 +79,10 @@ typedef struct {
                snd_ctl_event_t read;
        } u;
        char data[0];
-} snd_ctl_client_shm_t;
+} snd_ctl_shm_ctrl_t;
 
 #define CTL_SHM_SIZE 65536
-#define CTL_SHM_DATA_MAXLEN (CTL_SHM_SIZE - offsetof(snd_ctl_client_shm_t, data))
+#define CTL_SHM_DATA_MAXLEN (CTL_SHM_SIZE - offsetof(snd_ctl_shm_ctrl_t, data))
 
 typedef struct {
        unsigned char dev_type;
index 07ad251ebfc8928c11185bbdd8b2d1ecbf10c551..e1221a76744a1ed4bae502967436b3697416991b 100644 (file)
@@ -7,7 +7,10 @@
 
 typedef struct snd_ctl snd_ctl_t;
 
-typedef enum { SND_CTL_TYPE_HW, SND_CTL_TYPE_CLIENT } snd_ctl_type_t;
+typedef enum { SND_CTL_TYPE_HW,
+              SND_CTL_TYPE_SHM,
+              SND_CTL_TYPE_INET
+ } snd_ctl_type_t;
 
 typedef struct snd_ctl_callbacks {
        void *private_data;     /* may be used by an application */
@@ -37,8 +40,8 @@ int snd_defaults_pcm_device(void);
 int snd_defaults_rawmidi_card(void);
 int snd_defaults_rawmidi_device(void);
 
-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);
+int snd_ctl_hw_open(snd_ctl_t **handle, char *name, int card);
+int snd_ctl_shm_open(snd_ctl_t **handlep, char *name, char *socket, char *sname);
 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);
index 1671d9e2195dbd932779457b312b32d82bdab3bb..d04149436f0654267115fff90777de8e04b6d421 100644 (file)
@@ -104,7 +104,8 @@ typedef enum {
        SND_PCM_TYPE_MULTI,
        SND_PCM_TYPE_FILE,
        SND_PCM_TYPE_NULL,
-       SND_PCM_TYPE_CLIENT,
+       SND_PCM_TYPE_SHM,
+       SND_PCM_TYPE_INET,
        SND_PCM_TYPE_LINEAR,
        SND_PCM_TYPE_ALAW,
        SND_PCM_TYPE_MULAW,
@@ -118,16 +119,16 @@ typedef enum {
        SND_PCM_TYPE_LBSERVER,
 } snd_pcm_type_t;
 
-extern void (*snd_pcm_error)(const char *file, int line, const char *function, const char *fmt, ...);
+extern void snd_pcm_error(const char *file, int line, const char *function, const char *fmt, ...)  __attribute__ ((weak, format (printf, 4, 5)));
 
-int snd_pcm_open(snd_pcm_t **handle, char *name, 
+int snd_pcm_open(snd_pcm_t **pcm, char *name, 
                 int stream, int mode);
 
 /* Obsolete functions */
-int snd_pcm_hw_open_subdevice(snd_pcm_t **handle, int card, int device, int subdevice, int stream, int mode);
-int snd_pcm_hw_open_device(snd_pcm_t **handle, int card, int device, int stream, int mode);
-int snd_pcm_plug_open_subdevice(snd_pcm_t **handle, int card, int device, int subdevice, int stream, int mode);
-int snd_pcm_plug_open_device(snd_pcm_t **handle, int card, int device, int stream, int mode);
+int snd_pcm_hw_open_subdevice(snd_pcm_t **pcm, int card, int device, int subdevice, int stream, int mode);
+int snd_pcm_hw_open_device(snd_pcm_t **pcm, int card, int device, int stream, int mode);
+int snd_pcm_plug_open_subdevice(snd_pcm_t **pcm, int card, int device, int subdevice, int stream, int mode);
+int snd_pcm_plug_open_device(snd_pcm_t **pcm, int card, int device, int stream, int mode);
 #define snd_pcm_write snd_pcm_writei
 #define snd_pcm_read snd_pcm_readi
 ssize_t snd_pcm_writev(snd_pcm_t *pcm, const struct iovec *vector, int count);
@@ -171,7 +172,7 @@ ssize_t snd_pcm_avail_update(snd_pcm_t *pcm);
 
 
 /* mmap */
-int snd_pcm_mmap(snd_pcm_t *pcm, void **buffer);
+int snd_pcm_mmap(snd_pcm_t *pcm);
 int snd_pcm_munmap(snd_pcm_t *pcm);
 snd_pcm_channel_area_t *snd_pcm_mmap_areas(snd_pcm_t *pcm);
 int snd_pcm_mmap_get_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *stopped_areas, snd_pcm_channel_area_t *running_areas);
index 8592e654d4f8e5af6d028379353fda239b032309..4bfbf2603c870dcbe59b4c31d2c364a20cbce2fd 100644 (file)
@@ -1,7 +1,7 @@
 EXTRA_LTLIBRARIES = libcontrol.la
 
 libcontrol_la_SOURCES = cards.c controls.c bag.c defaults.c \
-                        control.c control_hw.c control_client.c
+                        control.c control_hw.c control_shm.c
 
 all: libcontrol.la
 
index e3dabdc63d46a8d70da18150583af21c1420c18e..b139e0c89b2d9348e92cca1ce0a31df521ba6f8c 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_hw_open(&handle, card) < 0)
+               if (snd_ctl_hw_open(&handle, NULL, 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_hw_open(&handle, card)) < 0)
+       if ((err = snd_ctl_hw_open(&handle, NULL, 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_hw_open(&handle, card)) < 0)
+       if ((err = snd_ctl_hw_open(&handle, NULL, card)) < 0)
                return err;
        if ((err = snd_ctl_hw_info(handle, &info)) < 0) {
                snd_ctl_close(handle);
index 2ed0f38b8ffa607d1e659177b085b6a93656d66d..e0b6c058eef2c39da47798d84b58fa10ad7960e0 100644 (file)
@@ -26,6 +26,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <assert.h>
+#include <dlfcn.h>
 #include "asoundlib.h"
 #include "control_local.h"
 
@@ -148,106 +149,22 @@ int snd_ctl_read(snd_ctl_t *ctl, snd_ctl_callbacks_t * callbacks)
        return result >= 0 ? count : -errno;
 }
 
-static int _snd_ctl_open_hw(snd_ctl_t **handlep, snd_config_t *conf)
+int snd_ctl_open(snd_ctl_t **ctlp, char *name)
 {
-       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_t *ctl_conf, *conf, *type_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);
+       char *lib = NULL, *open = NULL;
+       int (*open_func)(snd_ctl_t **ctlp, char *name, snd_config_t *conf);
+       void *h;
+       assert(ctlp && 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 (err < 0)
+               return err;
        if (snd_config_type(ctl_conf) != SND_CONFIG_TYPE_COMPOUND)
                return -EINVAL;
        err = snd_config_search(ctl_conf, "type", &conf);
@@ -256,10 +173,37 @@ int snd_ctl_open(snd_ctl_t **handlep, char *name)
        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
+       err = snd_config_searchv(snd_config, &type_conf, "ctltype", str, 0);
+       if (err < 0)
+               return err;
+       snd_config_foreach(i, type_conf) {
+               snd_config_t *n = snd_config_entry(i);
+               if (strcmp(n->id, "comment") == 0)
+                       continue;
+               if (strcmp(n->id, "lib") == 0) {
+                       err = snd_config_string_get(n, &lib);
+                       if (err < 0)
+                               return -EINVAL;
+                       continue;
+               }
+               if (strcmp(n->id, "open") == 0) {
+                       err = snd_config_string_get(n, &open);
+                       if (err < 0)
+                               return -EINVAL;
+                       continue;
+                       return -EINVAL;
+               }
+       }
+       if (!open)
                return -EINVAL;
+       if (!lib)
+               lib = "libasound.so";
+       h = dlopen(lib, RTLD_NOW);
+       if (!h)
+               return -ENOENT;
+       open_func = dlsym(h, open);
+       dlclose(h);
+       if (!open_func)
+               return -ENXIO;
+       return open_func(ctlp, name, ctl_conf);
 }
diff --git a/src/control/control_client.c b/src/control/control_client.c
deleted file mode 100644 (file)
index ef323e6..0000000
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
- *  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_poll_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,
-       poll_descriptor: snd_ctl_client_poll_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;
-}
-
index 8ca8b8b518501064df5a56988acfc45b6ad4b85a..5d58ab12fac995d7d7f769e4f4aa9219f7a46b96 100644 (file)
@@ -147,7 +147,7 @@ struct snd_ctl_ops snd_ctl_hw_ops = {
        read: snd_ctl_hw_read,
 };
 
-int snd_ctl_hw_open(snd_ctl_t **handle, int card)
+int snd_ctl_hw_open(snd_ctl_t **handle, char *name, int card)
 {
        int fd, ver;
        char filename[32];
@@ -185,6 +185,9 @@ int snd_ctl_hw_open(snd_ctl_t **handle, int card)
        }
        hw->card = card;
        hw->fd = fd;
+       if (name)
+               ctl->name = strdup(name);
+       ctl->type = SND_CTL_TYPE_HW;
        ctl->ops = &snd_ctl_hw_ops;
        ctl->private = hw;
        INIT_LIST_HEAD(&ctl->hlist);
@@ -192,3 +195,34 @@ int snd_ctl_hw_open(snd_ctl_t **handle, int card)
        return 0;
 }
 
+int _snd_ctl_hw_open(snd_ctl_t **handlep, char *name, 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, name, card);
+}
+                               
index cf1a5828127f2ad5395b2a8a03e97ec659f26236..34f302d49841c170f4492a424f4c62a44ea221ce 100644 (file)
@@ -40,6 +40,7 @@ struct snd_ctl_ops {
 
 
 struct snd_ctl {
+       char *name;
        snd_ctl_type_t type;
        struct snd_ctl_ops *ops;
        void *private;
diff --git a/src/control/control_shm.c b/src/control/control_shm.c
new file mode 100644 (file)
index 0000000..968e146
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ *  Control - SHM 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 socket;
+       void *ctrl;
+} snd_ctl_shm_t;
+
+extern int receive_fd(int socket, void *data, size_t len, int *fd);
+
+static int snd_ctl_shm_action(snd_ctl_t *ctl)
+{
+       snd_ctl_shm_t *shm = ctl->private;
+       int err;
+       char buf[1];
+       snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
+       err = write(shm->socket, buf, 1);
+       if (err != 1)
+               return -EBADFD;
+       err = read(shm->socket, buf, 1);
+       if (err != 1)
+               return -EBADFD;
+       if (ctrl->cmd) {
+               fprintf(stderr, "Server has not done the cmd\n");
+               return -EBADFD;
+       }
+       return ctrl->result;
+}
+
+static int snd_ctl_shm_action_fd(snd_ctl_t *ctl, int *fd)
+{
+       snd_ctl_shm_t *shm = ctl->private;
+       int err;
+       char buf[1];
+       snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
+       err = write(shm->socket, buf, 1);
+       if (err != 1)
+               return -EBADFD;
+       err = receive_fd(shm->socket, buf, 1, fd);
+       if (err != 1)
+               return -EBADFD;
+       if (ctrl->cmd) {
+               fprintf(stderr, "Server has not done the cmd\n");
+               return -EBADFD;
+       }
+       return ctrl->result;
+}
+
+static int snd_ctl_shm_close(snd_ctl_t *ctl)
+{
+       snd_ctl_shm_t *shm = ctl->private;
+       snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
+       int result;
+       ctrl->cmd = SND_CTL_IOCTL_CLOSE;
+       result = snd_ctl_shm_action(ctl);
+       shmdt((void *)ctrl);
+       close(shm->socket);
+       free(shm);
+       return result;
+}
+
+static int snd_ctl_shm_poll_descriptor(snd_ctl_t *ctl)
+{
+       snd_ctl_shm_t *shm = ctl->private;
+       snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
+       int fd, err;
+       ctrl->cmd = SND_CTL_IOCTL_POLL_DESCRIPTOR;
+       err = snd_ctl_shm_action_fd(ctl, &fd);
+       if (err < 0)
+               return err;
+       return fd;
+}
+
+static int snd_ctl_shm_hw_info(snd_ctl_t *ctl, snd_ctl_hw_info_t *info)
+{
+       snd_ctl_shm_t *shm = ctl->private;
+       snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
+       int err;
+//     ctrl->u.hw_info = *info;
+       ctrl->cmd = SND_CTL_IOCTL_HW_INFO;
+       err = snd_ctl_shm_action(ctl);
+       if (err < 0)
+               return err;
+       *info = ctrl->u.hw_info;
+       return err;
+}
+
+static int snd_ctl_shm_clist(snd_ctl_t *ctl, snd_control_list_t *list)
+{
+       snd_ctl_shm_t *shm = ctl->private;
+       snd_ctl_shm_ctrl_t *ctrl = 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_shm_action(ctl);
+       if (err < 0)
+               return err;
+       *list = ctrl->u.clist;
+       list->pids = pids;
+       memcpy(pids, ctrl->data, bytes);
+       return err;
+}
+
+static int snd_ctl_shm_cinfo(snd_ctl_t *ctl, snd_control_info_t *info)
+{
+       snd_ctl_shm_t *shm = ctl->private;
+       snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
+       int err;
+       ctrl->u.cinfo = *info;
+       ctrl->cmd = SND_CTL_IOCTL_CONTROL_INFO;
+       err = snd_ctl_shm_action(ctl);
+       if (err < 0)
+               return err;
+       *info = ctrl->u.cinfo;
+       return err;
+}
+
+static int snd_ctl_shm_cread(snd_ctl_t *ctl, snd_control_t *control)
+{
+       snd_ctl_shm_t *shm = ctl->private;
+       snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
+       int err;
+       ctrl->u.cread = *control;
+       ctrl->cmd = SND_CTL_IOCTL_CONTROL_READ;
+       err = snd_ctl_shm_action(ctl);
+       if (err < 0)
+               return err;
+       *control = ctrl->u.cread;
+       return err;
+}
+
+static int snd_ctl_shm_cwrite(snd_ctl_t *ctl, snd_control_t *control)
+{
+       snd_ctl_shm_t *shm = ctl->private;
+       snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
+       int err;
+       ctrl->u.cwrite = *control;
+       ctrl->cmd = SND_CTL_IOCTL_CONTROL_WRITE;
+       err = snd_ctl_shm_action(ctl);
+       if (err < 0)
+               return err;
+       *control = ctrl->u.cwrite;
+       return err;
+}
+
+static int snd_ctl_shm_hwdep_info(snd_ctl_t *ctl, snd_hwdep_info_t * info)
+{
+       snd_ctl_shm_t *shm = ctl->private;
+       snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
+       int err;
+       ctrl->u.hwdep_info = *info;
+       ctrl->cmd = SND_CTL_IOCTL_HWDEP_INFO;
+       err = snd_ctl_shm_action(ctl);
+       if (err < 0)
+               return err;
+       *info = ctrl->u.hwdep_info;
+       return err;
+}
+
+static int snd_ctl_shm_pcm_info(snd_ctl_t *ctl, snd_pcm_info_t * info)
+{
+       snd_ctl_shm_t *shm = ctl->private;
+       snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
+       int err;
+       ctrl->u.pcm_info = *info;
+       ctrl->cmd = SND_CTL_IOCTL_PCM_INFO;
+       err = snd_ctl_shm_action(ctl);
+       if (err < 0)
+               return err;
+       *info = ctrl->u.pcm_info;
+       return err;
+}
+
+static int snd_ctl_shm_pcm_prefer_subdevice(snd_ctl_t *ctl, int subdev)
+{
+       snd_ctl_shm_t *shm = ctl->private;
+       snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
+       int err;
+       ctrl->u.pcm_prefer_subdevice = subdev;
+       ctrl->cmd = SND_CTL_IOCTL_PCM_PREFER_SUBDEVICE;
+       err = snd_ctl_shm_action(ctl);
+       if (err < 0)
+               return err;
+       return err;
+}
+
+static int snd_ctl_shm_rawmidi_info(snd_ctl_t *ctl, snd_rawmidi_info_t * info)
+{
+       snd_ctl_shm_t *shm = ctl->private;
+       snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
+       int err;
+       ctrl->u.rawmidi_info = *info;
+       ctrl->cmd = SND_CTL_IOCTL_RAWMIDI_INFO;
+       err = snd_ctl_shm_action(ctl);
+       if (err < 0)
+               return err;
+       *info = ctrl->u.rawmidi_info;
+       return err;
+}
+
+static int snd_ctl_shm_read(snd_ctl_t *ctl, snd_ctl_event_t *event)
+{
+       snd_ctl_shm_t *shm = ctl->private;
+       snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
+       int err;
+       ctrl->u.read = *event;
+       ctrl->cmd = SND_CTL_IOCTL_READ;
+       err = snd_ctl_shm_action(ctl);
+       if (err < 0)
+               return err;
+       *event = ctrl->u.read;
+       return err;
+}
+
+struct snd_ctl_ops snd_ctl_shm_ops = {
+       close: snd_ctl_shm_close,
+       poll_descriptor: snd_ctl_shm_poll_descriptor,
+       hw_info: snd_ctl_shm_hw_info,
+       clist: snd_ctl_shm_clist,
+       cinfo: snd_ctl_shm_cinfo,
+       cread: snd_ctl_shm_cread,
+       cwrite: snd_ctl_shm_cwrite,
+       hwdep_info: snd_ctl_shm_hwdep_info,
+       pcm_info: snd_ctl_shm_pcm_info,
+       pcm_prefer_subdevice: snd_ctl_shm_pcm_prefer_subdevice,
+       rawmidi_info: snd_ctl_shm_rawmidi_info,
+       read: snd_ctl_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;
+}
+
+#if 0
+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;
+}
+#endif
+
+int snd_ctl_shm_open(snd_ctl_t **handlep, char *name, char *socket, char *sname)
+{
+       snd_ctl_t *ctl;
+       snd_ctl_shm_t *shm = NULL;
+       snd_client_open_request_t *req;
+       snd_client_open_answer_t ans;
+       size_t snamelen, reqlen;
+       int err;
+       int result;
+       int sock = -1;
+       snd_ctl_shm_ctrl_t *ctrl = NULL;
+       snamelen = strlen(sname);
+       if (snamelen > 255)
+               return -EINVAL;
+
+       result = make_local_socket(socket);
+       if (result < 0) {
+               ERR("server for socket %s is not running", socket);
+               goto _err;
+       }
+       sock = result;
+
+       reqlen = sizeof(*req) + snamelen;
+       req = alloca(reqlen);
+       memcpy(req->name, sname, snamelen);
+       req->dev_type = SND_DEV_TYPE_CONTROL;
+       req->transport_type = SND_TRANSPORT_TYPE_SHM;
+       req->stream = 0;
+       req->mode = 0;
+       req->namelen = snamelen;
+       err = write(sock, req, reqlen);
+       if (err < 0) {
+               ERR("write error");
+               result = -errno;
+               goto _err;
+       }
+       if ((size_t) err != reqlen) {
+               ERR("write size error");
+               result = -EINVAL;
+               goto _err;
+       }
+       err = read(sock, &ans, sizeof(ans));
+       if (err < 0) {
+               ERR("read error");
+               result = -errno;
+               goto _err;
+       }
+       if (err != sizeof(ans)) {
+               ERR("read size error");
+               result = -EINVAL;
+               goto _err;
+       }
+       result = ans.result;
+       if (result < 0)
+               goto _err;
+
+       ctrl = shmat(ans.cookie, 0, 0);
+       if (!ctrl) {
+               result = -errno;
+               goto _err;
+       }
+               
+       ctl = calloc(1, sizeof(snd_ctl_t));
+       if (!ctl) {
+               result = -ENOMEM;
+               goto _err;
+       }
+       shm = calloc(1, sizeof(snd_ctl_shm_t));
+       if (!ctl) {
+               free(ctl);
+               result = -ENOMEM;
+               goto _err;
+       }
+
+       shm->socket = sock;
+       shm->ctrl = ctrl;
+
+       if (name)
+               ctl->name = strdup(name);
+       ctl->type = SND_CTL_TYPE_SHM;
+       ctl->ops = &snd_ctl_shm_ops;
+       ctl->private = shm;
+       INIT_LIST_HEAD(&ctl->hlist);
+       *handlep = ctl;
+       return 0;
+
+ _err:
+       close(sock);
+       if (ctrl)
+               shmdt(ctrl);
+       if (shm)
+               free(shm);
+       return result;
+}
+
+extern int is_local(struct hostent *hent);
+
+int _snd_ctl_shm_open(snd_ctl_t **handlep, char *name, snd_config_t *conf)
+{
+       snd_config_iterator_t i;
+       char *server = NULL;
+       char *sname = NULL;
+       snd_config_t *sconfig;
+       char *host = NULL;
+       char *socket = NULL;
+       long port = -1;
+       int err;
+       int local;
+       struct hostent *h;
+       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, "server") == 0) {
+                       err = snd_config_string_get(n, &server);
+                       if (err < 0) {
+                               ERR("Invalid type for server");
+                               return -EINVAL;
+                       }
+                       continue;
+               }
+               if (strcmp(n->id, "sname") == 0) {
+                       err = snd_config_string_get(n, &sname);
+                       if (err < 0) {
+                               ERR("Invalid type for sname");
+                               return -EINVAL;
+                       }
+                       continue;
+               }
+               ERR("Unknown field: %s", n->id);
+               return -EINVAL;
+       }
+       if (!sname) {
+               ERR("sname is not defined");
+               return -EINVAL;
+       }
+       if (!server) {
+               ERR("server is not defined");
+               return -EINVAL;
+       }
+       err = snd_config_searchv(snd_config, &sconfig, "server", server, 0);
+       if (err < 0) {
+               ERR("Unknown server %s", server);
+               return -EINVAL;
+       }
+       snd_config_foreach(i, conf) {
+               snd_config_t *n = snd_config_entry(i);
+               if (strcmp(n->id, "comment") == 0)
+                       continue;
+               if (strcmp(n->id, "host") == 0) {
+                       err = snd_config_string_get(n, &host);
+                       if (err < 0) {
+                               ERR("Invalid type for host");
+                               return -EINVAL;
+                       }
+                       continue;
+               }
+               if (strcmp(n->id, "socket") == 0) {
+                       err = snd_config_string_get(n, &socket);
+                       if (err < 0) {
+                               ERR("Invalid type for socket");
+                               return -EINVAL;
+                       }
+                       continue;
+               }
+               if (strcmp(n->id, "port") == 0) {
+                       err = snd_config_integer_get(n, &port);
+                       if (err < 0) {
+                               ERR("Invalid type for port");
+                               return -EINVAL;
+                       }
+                       continue;
+               }
+               ERR("Unknown field: %s", n->id);
+               return -EINVAL;
+       }
+
+       if (!host) {
+               ERR("host is not defined");
+               return -EINVAL;
+       }
+       if (!socket) {
+               ERR("socket is not defined");
+               return -EINVAL;
+       }
+       h = gethostbyname(host);
+       if (!h) {
+               ERR("Cannot resolve %s", host);
+               return -EINVAL;
+       }
+       local = is_local(h);
+       if (!local) {
+               ERR("%s is not the local host", host);
+               return -EINVAL;
+       }
+       return snd_ctl_shm_open(handlep, name, socket, sname);
+}
+                               
index e932d5195ee3180c857c58e1a59d56eb6f5b6cec..30baaf1899b61d1eb3f10eebdd701a7b27df4d3c 100644 (file)
@@ -3,7 +3,7 @@ EXTRA_LTLIBRARIES = libpcm.la
 
 libpcm_la_SOURCES = pcm.c pcm_hw.c pcm_plugin.c pcm_linear.c pcm_route.c \
                    pcm_mulaw.c pcm_alaw.c pcm_adpcm.c pcm_rate.c pcm_plug.c \
-                   pcm_misc.c pcm_mmap.c pcm_multi.c pcm_client.c pcm_file.c \
+                   pcm_misc.c pcm_mmap.c pcm_multi.c pcm_shm.c pcm_file.c \
                    pcm_share.c
 noinst_HEADERS = pcm_local.h pcm_plugin.h
 
index 4288d3d56b78d3ddd9e75ec26c7cefa13fa72deb..5c85320c5cfff693500b7e94fa93b5387a87153c 100644 (file)
 #include "pcm_local.h"
 #include "list.h"
 
-int snd_pcm_init(snd_pcm_t *pcm)
-{
-       int err;
-       err = snd_pcm_mmap_status(pcm, NULL);
-       if (err < 0)
-               return err;
-       err = snd_pcm_mmap_control(pcm, NULL);
-       if (err < 0)
-               return err;
-       return 0;
-}
-
 snd_pcm_type_t snd_pcm_type(snd_pcm_t *pcm)
 {
        assert(pcm);
@@ -59,16 +47,8 @@ int snd_pcm_close(snd_pcm_t *pcm)
        int ret = 0;
        int err;
        assert(pcm);
-       if (pcm->mmap_status) {
-               if ((err = snd_pcm_munmap_status(pcm)) < 0)
-                       ret = err;
-       }
-       if (pcm->mmap_control) {
-               if ((err = snd_pcm_munmap_control(pcm)) < 0)
-                       ret = err;
-       }
-       if (pcm->mmap_data) {
-               if ((err = snd_pcm_munmap_data(pcm)) < 0)
+       if (pcm->mmap_info) {
+               if ((err = snd_pcm_munmap(pcm)) < 0)
                        ret = err;
        }
        if ((err = pcm->ops->close(pcm->op_arg)) < 0)
@@ -156,12 +136,21 @@ int snd_pcm_params(snd_pcm_t *pcm, snd_pcm_params_t *params)
 {
        int err;
        snd_pcm_setup_t setup;
+       int mmap = 0;
        assert(pcm && params);
-       assert(!pcm->mmap_data);
+       if (pcm->mmap_info) {
+               mmap = 1;
+               err = snd_pcm_munmap(pcm);
+               if (err < 0)
+                       return err;
+       }
        if ((err = pcm->ops->params(pcm->op_arg, params)) < 0)
                return err;
        pcm->valid_setup = 0;
-       return snd_pcm_setup(pcm, &setup);
+       err = snd_pcm_setup(pcm, &setup);
+       if (pcm->mmap_auto || mmap)
+               snd_pcm_mmap(pcm);
+       return err;
 }
 
 int snd_pcm_status(snd_pcm_t *pcm, snd_pcm_status_t *status)
@@ -233,7 +222,7 @@ ssize_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, size_t size)
        assert(size == 0 || buffer);
        assert(pcm->valid_setup);
        assert(pcm->setup.xfer_mode == SND_PCM_XFER_INTERLEAVED);
-       assert(!pcm->mmap_data);
+       assert(!pcm->mmap_info || pcm->mmap_auto);
        return _snd_pcm_writei(pcm, buffer, size);
 }
 
@@ -243,7 +232,7 @@ ssize_t snd_pcm_writen(snd_pcm_t *pcm, void **bufs, size_t size)
        assert(size == 0 || bufs);
        assert(pcm->valid_setup);
        assert(pcm->setup.xfer_mode == SND_PCM_XFER_NONINTERLEAVED);
-       assert(!pcm->mmap_data);
+       assert(!pcm->mmap_info || pcm->mmap_auto);
        return _snd_pcm_writen(pcm, bufs, size);
 }
 
@@ -253,7 +242,7 @@ ssize_t snd_pcm_readi(snd_pcm_t *pcm, void *buffer, size_t size)
        assert(size == 0 || buffer);
        assert(pcm->valid_setup);
        assert(pcm->setup.xfer_mode == SND_PCM_XFER_INTERLEAVED);
-       assert(!pcm->mmap_data);
+       assert(!pcm->mmap_info || pcm->mmap_auto);
        return _snd_pcm_readi(pcm, buffer, size);
 }
 
@@ -263,7 +252,7 @@ ssize_t snd_pcm_readn(snd_pcm_t *pcm, void **bufs, size_t size)
        assert(size == 0 || bufs);
        assert(pcm->valid_setup);
        assert(pcm->setup.xfer_mode == SND_PCM_XFER_NONINTERLEAVED);
-       assert(!pcm->mmap_data);
+       assert(!pcm->mmap_info || pcm->mmap_auto);
        return _snd_pcm_readn(pcm, bufs, size);
 }
 
@@ -331,7 +320,7 @@ int snd_pcm_unlink(snd_pcm_t *pcm)
 int snd_pcm_poll_descriptor(snd_pcm_t *pcm)
 {
        assert(pcm);
-       return pcm->fast_ops->poll_descriptor(pcm->fast_op_arg);
+       return pcm->poll_fd;
 }
 
 int snd_pcm_channels_mask(snd_pcm_t *pcm, bitset_t *cmask)
@@ -547,62 +536,87 @@ int snd_pcm_open(snd_pcm_t **pcmp, char *name,
        if (err < 0)
                return err;
        err = snd_config_searchv(snd_config, &pcm_conf, "pcm", name, 0);
-       if (err < 0)
+       if (err < 0) {
+               ERR("Unknown PCM %s", name);
                return err;
-       if (snd_config_type(pcm_conf) != SND_CONFIG_TYPE_COMPOUND)
+       }
+       if (snd_config_type(pcm_conf) != SND_CONFIG_TYPE_COMPOUND) {
+               ERR("Invalid type for PCM definition");
                return -EINVAL;
+       }
        err = snd_config_search(pcm_conf, "stream", &conf);
        if (err >= 0) {
                err = snd_config_string_get(conf, &str);
-               if (err < 0)
+               if (err < 0) {
+                       ERR("Invalid type for stream");
                        return err;
+               }
                if (strcmp(str, "playback") == 0) {
                        if (stream != SND_PCM_STREAM_PLAYBACK)
                                return -EINVAL;
                } else if (strcmp(str, "capture") == 0) {
                        if (stream != SND_PCM_STREAM_CAPTURE)
                                return -EINVAL;
-               } else
+               } else {
+                       ERR("Invalid value for stream");
                        return -EINVAL;
+               }
        }
        err = snd_config_search(pcm_conf, "type", &conf);
-       if (err < 0)
+       if (err < 0) {
+               ERR("type is not defined");
                return err;
+       }
        err = snd_config_string_get(conf, &str);
-       if (err < 0)
+       if (err < 0) {
+               ERR("Invalid type for type");
                return err;
+       }
        err = snd_config_searchv(snd_config, &type_conf, "pcmtype", str, 0);
-       if (err < 0)
+       if (err < 0) {
+               ERR("Unknown PCM type %s", str);
                return err;
+       }
        snd_config_foreach(i, type_conf) {
                snd_config_t *n = snd_config_entry(i);
                if (strcmp(n->id, "comment") == 0)
                        continue;
                if (strcmp(n->id, "lib") == 0) {
                        err = snd_config_string_get(n, &lib);
-                       if (err < 0)
+                       if (err < 0) {
+                               ERR("Invalid type for lib");
                                return -EINVAL;
+                       }
                        continue;
                }
                if (strcmp(n->id, "open") == 0) {
                        err = snd_config_string_get(n, &open);
-                       if (err < 0)
+                       if (err < 0) {
+                               ERR("Invalid type for open");
                                return -EINVAL;
+                       }
                        continue;
+                       ERR("Unknown field: %s", n->id);
                        return -EINVAL;
                }
        }
-       if (!open)
+       if (!open) {
+               ERR("open is not defined");
                return -EINVAL;
+       }
        if (!lib)
                lib = "libasound.so";
        h = dlopen(lib, RTLD_NOW);
-       if (!h)
+       if (!h) {
+               ERR("Cannot open shared library %s", lib);
                return -ENOENT;
+       }
        open_func = dlsym(h, open);
        dlclose(h);
-       if (!open_func)
+       if (!open_func) {
+               ERR("symbol %s is not defined inside %s", open, lib);
                return -ENXIO;
+       }
        return open_func(pcmp, name, pcm_conf, stream, mode);
 }
 
@@ -634,23 +648,11 @@ int snd_pcm_wait(snd_pcm_t *pcm, int timeout)
 {
        struct pollfd pfd;
        int err;
-#if 0
-       size_t bavail, aavail;
-       struct timeval before, after, diff;
-       bavail = snd_pcm_avail_update(pcm);
-       gettimeofday(&before, 0);
-#endif
        pfd.fd = snd_pcm_poll_descriptor(pcm);
        pfd.events = pcm->stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN;
        err = poll(&pfd, 1, timeout);
        if (err < 0)
                return err;
-#if 0
-       aavail = snd_pcm_avail_update(pcm);
-       gettimeofday(&after, 0);
-       timersub(&after, &before, &diff);
-       fprintf(stderr, "%s %ld.%06ld: get=%d (%d-%d)\n", pcm->stream == SND_PCM_STREAM_PLAYBACK ? "playback" : "capture", diff.tv_sec, diff.tv_usec, aavail - bavail, aavail, bavail);
-#endif
        return 0;
 }
 
@@ -1044,7 +1046,7 @@ ssize_t snd_pcm_write_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *areas,
        return err;
 }
 
-void snd_pcm_error_default(const char *file, int line, const char *function, const char *fmt, ...)
+void snd_pcm_error(const char *file, int line, const char *function, const char *fmt, ...)
 {
        va_list arg;
        va_start(arg, fmt);
@@ -1053,5 +1055,3 @@ void snd_pcm_error_default(const char *file, int line, const char *function, con
        putc('\n', stderr);
        va_end(arg);
 }
-
-void (*snd_pcm_error)(const char *file, int line, const char *function, const char *fmt, ...) = snd_pcm_error_default;
index 56d9e76f93edaba330fbcc829ae198dfd9790385..4834fe595757403772c9fb59806852f562ad312a 100644 (file)
@@ -377,11 +377,6 @@ static int snd_pcm_adpcm_params(snd_pcm_t *pcm, snd_pcm_params_t * params)
                params->fail_reason = SND_PCM_PARAMS_FAIL_INVAL;
                return -EINVAL;
        }
-       if (slave->mmap_data) {
-               err = snd_pcm_munmap_data(slave);
-               if (err < 0)
-                       return err;
-       }
        adpcm->cformat = params->format.sfmt;
        adpcm->cxfer_mode = params->xfer_mode;
        adpcm->cmmap_shape = params->mmap_shape;
@@ -392,10 +387,6 @@ static int snd_pcm_adpcm_params(snd_pcm_t *pcm, snd_pcm_params_t * params)
        params->format.sfmt = adpcm->cformat;
        params->xfer_mode = adpcm->cxfer_mode;
        params->mmap_shape = adpcm->cmmap_shape;
-       if (slave->valid_setup) {
-               int r = snd_pcm_mmap_data(slave, NULL);
-               assert(r >= 0);
-       }
        return err;
 }
 
@@ -533,7 +524,7 @@ static void snd_pcm_adpcm_dump(snd_pcm_t *pcm, FILE *fp)
        snd_pcm_dump(adpcm->plug.slave, fp);
 }
 
-struct snd_pcm_ops snd_pcm_adpcm_ops = {
+snd_pcm_ops_t snd_pcm_adpcm_ops = {
        close: snd_pcm_adpcm_close,
        info: snd_pcm_plugin_info,
        params_info: snd_pcm_adpcm_params_info,
@@ -545,20 +536,15 @@ struct snd_pcm_ops snd_pcm_adpcm_ops = {
        dump: snd_pcm_adpcm_dump,
        nonblock: snd_pcm_plugin_nonblock,
        async: snd_pcm_plugin_async,
-       mmap_status: snd_pcm_plugin_mmap_status,
-       mmap_control: snd_pcm_plugin_mmap_control,
-       mmap_data: snd_pcm_plugin_mmap_data,
-       munmap_status: snd_pcm_plugin_munmap_status,
-       munmap_control: snd_pcm_plugin_munmap_control,
-       munmap_data: snd_pcm_plugin_munmap_data,
+       mmap: snd_pcm_plugin_mmap,
+       munmap: snd_pcm_plugin_munmap,
 };
 
-int snd_pcm_adpcm_open(snd_pcm_t **handlep, char *name, int sformat, snd_pcm_t *slave, int close_slave)
+int snd_pcm_adpcm_open(snd_pcm_t **pcmp, char *name, int sformat, snd_pcm_t *slave, int close_slave)
 {
-       snd_pcm_t *handle;
+       snd_pcm_t *pcm;
        snd_pcm_adpcm_t *adpcm;
-       int err;
-       assert(handlep && slave);
+       assert(pcmp && slave);
        if (snd_pcm_format_linear(sformat) != 1 &&
            sformat != SND_PCM_SFMT_IMA_ADPCM)
                return -EINVAL;
@@ -573,27 +559,25 @@ int snd_pcm_adpcm_open(snd_pcm_t **handlep, char *name, int sformat, snd_pcm_t *
        adpcm->plug.slave = slave;
        adpcm->plug.close_slave = close_slave;
 
-       handle = calloc(1, sizeof(snd_pcm_t));
-       if (!handle) {
+       pcm = calloc(1, sizeof(snd_pcm_t));
+       if (!pcm) {
                free(adpcm);
                return -ENOMEM;
        }
        if (name)
-               handle->name = strdup(name);
-       handle->type = SND_PCM_TYPE_ADPCM;
-       handle->stream = slave->stream;
-       handle->ops = &snd_pcm_adpcm_ops;
-       handle->op_arg = handle;
-       handle->fast_ops = &snd_pcm_plugin_fast_ops;
-       handle->fast_op_arg = handle;
-       handle->mode = slave->mode;
-       handle->private = adpcm;
-       err = snd_pcm_init(handle);
-       if (err < 0) {
-               snd_pcm_close(handle);
-               return err;
-       }
-       *handlep = handle;
+               pcm->name = strdup(name);
+       pcm->type = SND_PCM_TYPE_ADPCM;
+       pcm->stream = slave->stream;
+       pcm->mode = slave->mode;
+       pcm->ops = &snd_pcm_adpcm_ops;
+       pcm->op_arg = pcm;
+       pcm->fast_ops = &snd_pcm_plugin_fast_ops;
+       pcm->fast_op_arg = pcm;
+       pcm->private = adpcm;
+       pcm->poll_fd = slave->poll_fd;
+       pcm->hw_ptr = &adpcm->plug.hw_ptr;
+       pcm->appl_ptr = &adpcm->plug.appl_ptr;
+       *pcmp = pcm;
 
        return 0;
 }
index 7fae5be0727187a1010765f495fd3181aeadb7db..33913b2607efcc104abea361d2d3792f0cffcb89 100644 (file)
@@ -259,11 +259,6 @@ static int snd_pcm_alaw_params(snd_pcm_t *pcm, snd_pcm_params_t * params)
                params->fail_reason = SND_PCM_PARAMS_FAIL_INVAL;
                return -EINVAL;
        }
-       if (slave->mmap_data) {
-               err = snd_pcm_munmap_data(slave);
-               if (err < 0)
-                       return err;
-       }
        alaw->cformat = params->format.sfmt;
        alaw->cxfer_mode = params->xfer_mode;
        alaw->cmmap_shape = params->mmap_shape;
@@ -274,10 +269,6 @@ static int snd_pcm_alaw_params(snd_pcm_t *pcm, snd_pcm_params_t * params)
        params->format.sfmt = alaw->cformat;
        params->xfer_mode = alaw->cxfer_mode;
        params->mmap_shape = alaw->cmmap_shape;
-       if (slave->valid_setup) {
-               int r = snd_pcm_mmap_data(slave, NULL);
-               assert(r >= 0);
-       }
        return err;
 }
 
@@ -401,7 +392,7 @@ static void snd_pcm_alaw_dump(snd_pcm_t *pcm, FILE *fp)
        snd_pcm_dump(alaw->plug.slave, fp);
 }
 
-struct snd_pcm_ops snd_pcm_alaw_ops = {
+snd_pcm_ops_t snd_pcm_alaw_ops = {
        close: snd_pcm_plugin_close,
        info: snd_pcm_plugin_info,
        params_info: snd_pcm_alaw_params_info,
@@ -413,20 +404,15 @@ struct snd_pcm_ops snd_pcm_alaw_ops = {
        dump: snd_pcm_alaw_dump,
        nonblock: snd_pcm_plugin_nonblock,
        async: snd_pcm_plugin_async,
-       mmap_status: snd_pcm_plugin_mmap_status,
-       mmap_control: snd_pcm_plugin_mmap_control,
-       mmap_data: snd_pcm_plugin_mmap_data,
-       munmap_status: snd_pcm_plugin_munmap_status,
-       munmap_control: snd_pcm_plugin_munmap_control,
-       munmap_data: snd_pcm_plugin_munmap_data,
+       mmap: snd_pcm_plugin_mmap,
+       munmap: snd_pcm_plugin_munmap,
 };
 
-int snd_pcm_alaw_open(snd_pcm_t **handlep, char *name, int sformat, snd_pcm_t *slave, int close_slave)
+int snd_pcm_alaw_open(snd_pcm_t **pcmp, char *name, int sformat, snd_pcm_t *slave, int close_slave)
 {
-       snd_pcm_t *handle;
+       snd_pcm_t *pcm;
        snd_pcm_alaw_t *alaw;
-       int err;
-       assert(handlep && slave);
+       assert(pcmp && slave);
        if (snd_pcm_format_linear(sformat) != 1 &&
            sformat != SND_PCM_SFMT_A_LAW)
                return -EINVAL;
@@ -440,27 +426,25 @@ int snd_pcm_alaw_open(snd_pcm_t **handlep, char *name, int sformat, snd_pcm_t *s
        alaw->plug.slave = slave;
        alaw->plug.close_slave = close_slave;
 
-       handle = calloc(1, sizeof(snd_pcm_t));
-       if (!handle) {
+       pcm = calloc(1, sizeof(snd_pcm_t));
+       if (!pcm) {
                free(alaw);
                return -ENOMEM;
        }
        if (name)
-               handle->name = strdup(name);
-       handle->type = SND_PCM_TYPE_ALAW;
-       handle->stream = slave->stream;
-       handle->ops = &snd_pcm_alaw_ops;
-       handle->op_arg = handle;
-       handle->fast_ops = &snd_pcm_plugin_fast_ops;
-       handle->fast_op_arg = handle;
-       handle->mode = slave->mode;
-       handle->private = alaw;
-       err = snd_pcm_init(handle);
-       if (err < 0) {
-               snd_pcm_close(handle);
-               return err;
-       }
-       *handlep = handle;
+               pcm->name = strdup(name);
+       pcm->type = SND_PCM_TYPE_ALAW;
+       pcm->stream = slave->stream;
+       pcm->mode = slave->mode;
+       pcm->ops = &snd_pcm_alaw_ops;
+       pcm->op_arg = pcm;
+       pcm->fast_ops = &snd_pcm_plugin_fast_ops;
+       pcm->fast_op_arg = pcm;
+       pcm->private = alaw;
+       pcm->poll_fd = slave->poll_fd;
+       pcm->hw_ptr = &alaw->plug.hw_ptr;
+       pcm->appl_ptr = &alaw->plug.appl_ptr;
+       *pcmp = pcm;
 
        return 0;
 }
diff --git a/src/pcm/pcm_client.c b/src/pcm/pcm_client.c
deleted file mode 100644 (file)
index 0222891..0000000
+++ /dev/null
@@ -1,857 +0,0 @@
-/*
- *  PCM - 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/mman.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include "pcm_local.h"
-#include "aserver.h"
-
-typedef struct {
-       int data_fd;
-       int ctrl_fd;
-       union {
-               struct {
-                       void *ctrl;
-               } shm;
-       } u;
-} snd_pcm_client_t;
-
-int receive_fd(int socket, void *data, size_t len, int *fd)
-{
-    int ret;
-    size_t cmsg_len = CMSG_LEN(sizeof(int));
-    struct cmsghdr *cmsg = alloca(cmsg_len);
-    int *fds = (int *) CMSG_DATA(cmsg);
-    struct msghdr msghdr;
-    struct iovec vec;
-
-    vec.iov_base = (void *)&data;
-    vec.iov_len = len;
-
-    cmsg->cmsg_len = cmsg_len;
-    cmsg->cmsg_level = SOL_SOCKET;
-    cmsg->cmsg_type = SCM_RIGHTS;
-    *fds = -1;
-
-    msghdr.msg_name = NULL;
-    msghdr.msg_namelen = 0;
-    msghdr.msg_iov = &vec;
-    msghdr.msg_iovlen = 1;
-    msghdr.msg_control = cmsg;
-    msghdr.msg_controllen = cmsg_len;
-    msghdr.msg_flags = 0;
-
-    ret = recvmsg(socket, &msghdr, 0);
-    if (ret < 0)
-           return -errno;
-    *fd = *fds;
-    return ret;
-}
-
-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 (pcm->stream) {
-       case SND_PCM_STREAM_PLAYBACK:
-               pfd.events = POLLOUT;
-               while (1) {
-                       err = poll(&pfd, 1, 0);
-                       if (err == 0)
-                               break;
-                       assert(err > 0);
-                       err = write(client->data_fd, buf, 1);
-                       assert(err == 1);
-               }
-               break;
-       case SND_PCM_STREAM_CAPTURE:
-               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);
-               }
-               break;
-       }
-}
-
-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;
-       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_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;
-       err = receive_fd(client->ctrl_fd, buf, 1, &fd);
-       if (err != 1)
-               return -EBADFD;
-       if (ctrl->cmd) {
-               fprintf(stderr, "Server has not done the cmd\n");
-               return -EBADFD;
-       }
-       if (ctrl->result < 0)
-               return ctrl->result;
-       return fd;
-}
-
-static int snd_pcm_client_shm_close(snd_pcm_t *pcm)
-{
-       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(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(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED)
-{
-       return 0;
-}
-
-static int snd_pcm_client_async(snd_pcm_t *pcm, int sig, pid_t pid)
-{
-       snd_pcm_client_t *client = pcm->private;
-       snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
-       int err;
-       ctrl->cmd = SND_PCM_IOCTL_ASYNC;
-       ctrl->u.async.sig = sig;
-       if (pid == 0)
-               pid = getpid();
-       ctrl->u.async.pid = pid;
-       err = snd_pcm_client_shm_action(pcm);
-       if (err < 0)
-               return err;
-       return ctrl->result;
-}
-
-static int snd_pcm_client_shm_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
-{
-       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(pcm);
-       if (err < 0)
-               return err;
-       *info = ctrl->u.info;
-       return ctrl->result;
-}
-
-static int snd_pcm_client_shm_params_info(snd_pcm_t *pcm, snd_pcm_params_info_t * info)
-{
-       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(pcm);
-       if (err < 0)
-               return err;
-       *info = ctrl->u.params_info;
-       return ctrl->result;
-}
-
-static int snd_pcm_client_shm_params(snd_pcm_t *pcm, snd_pcm_params_t * params)
-{
-       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(pcm);
-       if (err < 0)
-               return err;
-       *params = ctrl->u.params;
-       return ctrl->result;
-}
-
-static int snd_pcm_client_shm_setup(snd_pcm_t *pcm, snd_pcm_setup_t * setup)
-{
-       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(pcm);
-       if (err < 0)
-               return err;
-       *setup = ctrl->u.setup;
-       return ctrl->result;
-}
-
-static int snd_pcm_client_shm_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info)
-{
-       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(pcm);
-       if (err < 0)
-               return err;
-       *info = ctrl->u.channel_info;
-       return ctrl->result;
-}
-
-static int snd_pcm_client_shm_channel_params(snd_pcm_t *pcm, snd_pcm_channel_params_t * params)
-{
-       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(pcm);
-       if (err < 0)
-               return err;
-       *params = ctrl->u.channel_params;
-       return ctrl->result;
-}
-
-static int snd_pcm_client_shm_channel_setup(snd_pcm_t *pcm, snd_pcm_channel_setup_t * setup)
-{
-       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(pcm);
-       if (err < 0)
-               return err;
-       *setup = ctrl->u.channel_setup;
-       return ctrl->result;
-}
-
-static int snd_pcm_client_shm_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
-{
-       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(pcm);
-       if (err < 0)
-               return err;
-       *status = ctrl->u.status;
-       return ctrl->result;
-}
-
-static int snd_pcm_client_shm_state(snd_pcm_t *pcm)
-{
-       snd_pcm_client_t *client = pcm->private;
-       snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
-       int err;
-       ctrl->cmd = SND_PCM_IOCTL_STATE;
-       err = snd_pcm_client_shm_action(pcm);
-       if (err < 0)
-               return err;
-       return ctrl->result;
-}
-
-static int snd_pcm_client_shm_delay(snd_pcm_t *pcm, ssize_t *delayp)
-{
-       snd_pcm_client_t *client = pcm->private;
-       snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
-       int err;
-       ctrl->cmd = SND_PCM_IOCTL_DELAY;
-       err = snd_pcm_client_shm_action(pcm);
-       if (err < 0)
-               return err;
-       *delayp = ctrl->u.delay;
-       return ctrl->result;
-}
-
-static ssize_t snd_pcm_client_avail_update(snd_pcm_t *pcm)
-{
-       snd_pcm_client_t *client = pcm->private;
-       snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
-       int err;
-       ctrl->cmd = SND_PCM_IOCTL_AVAIL_UPDATE;
-       err = snd_pcm_client_shm_action(pcm);
-       if (err < 0)
-               return err;
-       return ctrl->result;
-}
-
-static int snd_pcm_client_shm_prepare(snd_pcm_t *pcm)
-{
-       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(pcm);
-       if (err < 0)
-               return err;
-       return ctrl->result;
-}
-
-static int snd_pcm_client_shm_start(snd_pcm_t *pcm)
-{
-       snd_pcm_client_t *client = pcm->private;
-       snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
-       int err;
-       ctrl->cmd = SND_PCM_IOCTL_START;
-       err = snd_pcm_client_shm_action(pcm);
-       if (err < 0)
-               return err;
-       return ctrl->result;
-}
-
-static int snd_pcm_client_shm_drop(snd_pcm_t *pcm)
-{
-       snd_pcm_client_t *client = pcm->private;
-       snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
-       int err;
-       ctrl->cmd = SND_PCM_IOCTL_DROP;
-       err = snd_pcm_client_shm_action(pcm);
-       if (err < 0)
-               return err;
-       return ctrl->result;
-}
-
-static int snd_pcm_client_shm_drain(snd_pcm_t *pcm)
-{
-       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(pcm);
-       if (err < 0)
-               return err;
-       return ctrl->result;
-}
-
-static int snd_pcm_client_shm_pause(snd_pcm_t *pcm, int enable)
-{
-       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(pcm);
-       if (err < 0)
-               return err;
-       return ctrl->result;
-}
-
-static ssize_t snd_pcm_client_shm_rewind(snd_pcm_t *pcm, size_t frames)
-{
-       snd_pcm_client_t *client = pcm->private;
-       snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
-       int err;
-       ctrl->cmd = SND_PCM_IOCTL_REWIND;
-       ctrl->u.rewind = frames;
-       err = snd_pcm_client_shm_action(pcm);
-       if (err < 0)
-               return err;
-       return ctrl->result;
-}
-
-static int snd_pcm_client_shm_mmap_status(snd_pcm_t *pcm)
-{
-       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(pcm);
-       if (fd < 0)
-               return fd;
-       /* FIXME: not mmap */
-       ptr = mmap(NULL, sizeof(snd_pcm_mmap_status_t), PROT_READ, MAP_FILE|MAP_SHARED, 
-                  fd, SND_PCM_MMAP_OFFSET_STATUS);
-       close(fd);
-       if (ptr == MAP_FAILED || ptr == NULL)
-               return -errno;
-       pcm->mmap_status = ptr;
-       return 0;
-}
-
-static int snd_pcm_client_shm_mmap_control(snd_pcm_t *pcm)
-{
-       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(pcm);
-       if (fd < 0)
-               return fd;
-       /* FIXME: not mmap */
-       ptr = mmap(NULL, sizeof(snd_pcm_mmap_control_t), PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, 
-                  fd, SND_PCM_MMAP_OFFSET_CONTROL);
-       close(fd);
-       if (ptr == MAP_FAILED || ptr == NULL)
-               return -errno;
-       pcm->mmap_control = ptr;
-       return 0;
-}
-
-static int snd_pcm_client_shm_mmap_data(snd_pcm_t *pcm)
-{
-       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(pcm);
-       if (fd < 0)
-               return fd;
-       /* FIXME: not mmap */
-       prot = pcm->stream == SND_PCM_STREAM_PLAYBACK ? PROT_WRITE : PROT_READ;
-       ptr = mmap(NULL, pcm->setup.mmap_bytes, prot, MAP_FILE|MAP_SHARED, 
-                    fd, SND_PCM_MMAP_OFFSET_DATA);
-       close(fd);
-       if (ptr == MAP_FAILED || ptr == NULL)
-               return -errno;
-       pcm->mmap_data = ptr;
-       return 0;
-}
-
-static int snd_pcm_client_shm_munmap_status(snd_pcm_t *pcm)
-{
-       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(pcm);
-       if (err < 0)
-               return err;
-       /* FIXME: not mmap */
-       if (munmap((void*)pcm->mmap_status, sizeof(*pcm->mmap_status)) < 0)
-               return -errno;
-       return ctrl->result;
-}
-
-static int snd_pcm_client_shm_munmap_control(snd_pcm_t *pcm)
-{
-       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(pcm);
-       if (err < 0)
-               return err;
-       /* FIXME: not mmap */
-       if (munmap(pcm->mmap_control, sizeof(*pcm->mmap_control)) < 0)
-               return -errno;
-       return ctrl->result;
-}
-
-static int snd_pcm_client_shm_munmap_data(snd_pcm_t *pcm)
-{
-       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(pcm);
-       if (err < 0)
-               return err;
-       /* FIXME: not mmap */
-       if (munmap(pcm->mmap_data, pcm->setup.mmap_bytes) < 0)
-               return -errno;
-       return ctrl->result;
-}
-
-static ssize_t snd_pcm_client_mmap_forward(snd_pcm_t *pcm, size_t size)
-{
-       snd_pcm_client_t *client = pcm->private;
-       snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
-       int err;
-       ctrl->cmd = SND_PCM_IOCTL_MMAP_FORWARD;
-       ctrl->u.mmap_forward = size;
-       err = snd_pcm_client_shm_action(pcm);
-       if (err < 0)
-               return err;
-       return ctrl->result;
-}
-
-static int snd_pcm_client_poll_descriptor(snd_pcm_t *pcm)
-{
-       snd_pcm_client_t *client = pcm->private;
-       return client->data_fd;
-}
-
-static int snd_pcm_client_channels_mask(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
-                                       bitset_t *cmask ATTRIBUTE_UNUSED)
-{
-       return 0;
-}
-
-static void snd_pcm_client_dump(snd_pcm_t *pcm, FILE *fp)
-{
-       fprintf(fp, "Client PCM\n");
-       if (pcm->valid_setup) {
-               fprintf(fp, "\nIts setup is:\n");
-               snd_pcm_dump_setup(pcm, fp);
-       }
-}
-
-struct snd_pcm_ops snd_pcm_client_ops = {
-       close: snd_pcm_client_shm_close,
-       info: snd_pcm_client_shm_info,
-       params_info: snd_pcm_client_shm_params_info,
-       params: snd_pcm_client_shm_params,
-       setup: snd_pcm_client_shm_setup,
-       channel_info: snd_pcm_client_shm_channel_info,
-       channel_params: snd_pcm_client_shm_channel_params,
-       channel_setup: snd_pcm_client_shm_channel_setup,
-       dump: snd_pcm_client_dump,
-       nonblock: snd_pcm_client_shm_nonblock,
-       async: snd_pcm_client_async,
-       mmap_status: snd_pcm_client_shm_mmap_status,
-       mmap_control: snd_pcm_client_shm_mmap_control,
-       mmap_data: snd_pcm_client_shm_mmap_data,
-       munmap_status: snd_pcm_client_shm_munmap_status,
-       munmap_control: snd_pcm_client_shm_munmap_control,
-       munmap_data: snd_pcm_client_shm_munmap_data,
-};
-
-struct snd_pcm_fast_ops snd_pcm_client_fast_ops = {
-       status: snd_pcm_client_shm_status,
-       state: snd_pcm_client_shm_state,
-       delay: snd_pcm_client_shm_delay,
-       prepare: snd_pcm_client_shm_prepare,
-       start: snd_pcm_client_shm_start,
-       drop: snd_pcm_client_shm_drop,
-       drain: snd_pcm_client_shm_drain,
-       pause: snd_pcm_client_shm_pause,
-       rewind: snd_pcm_client_shm_rewind,
-       writei: snd_pcm_mmap_writei,
-       writen: snd_pcm_mmap_writen,
-       readi: snd_pcm_mmap_readi,
-       readn: snd_pcm_mmap_readn,
-       poll_descriptor: snd_pcm_client_poll_descriptor,
-       channels_mask: snd_pcm_client_channels_mask,
-       avail_update: snd_pcm_client_avail_update,
-       mmap_forward: snd_pcm_client_mmap_forward,
-};
-
-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_pcm_client_create(snd_pcm_t **handlep, char *host, int port, int transport, char *name, int stream, int mode)
-{
-       snd_pcm_t *handle;
-       snd_pcm_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_pcm_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_PCM;
-       req->transport_type = transport;
-       req->stream = stream;
-       req->mode = mode;
-       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;
-       }
-               
-       if (stream == SND_PCM_STREAM_PLAYBACK) {
-               struct pollfd pfd;
-               char buf[1];
-               int bufsize = 1;
-               pfd.fd = fds[0];
-               pfd.events = POLLOUT;
-               err = setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
-               if (err < 0) {
-                       result = -errno;
-                       goto _err;
-               }
-               if (poll(&pfd, 1, 0) != 1) {
-                       result = -errno;
-                       goto _err;
-               }
-               while (1) {
-                       err = write(fds[0], buf, 1);
-                       if (err != 1) {
-                               result = -errno;
-                               goto _err;
-                       }
-                       err = poll(&pfd, 1, 0);
-                       if (err < 0) {
-                               result = -errno;
-                               goto _err;
-                       }
-                       if (err == 0)
-                               break;
-               }
-       }
-
-       client = calloc(1, sizeof(snd_pcm_client_t));
-       if (!client) {
-               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;
-       }
-
-       handle = calloc(1, sizeof(snd_pcm_t));
-       if (!handle) {
-               free(client);
-               result = -ENOMEM;
-               goto _err;
-       }
-       handle->type = SND_PCM_TYPE_CLIENT;
-       handle->stream = stream;
-       handle->ops = &snd_pcm_client_ops;
-       handle->op_arg = handle;
-       handle->fast_ops = &snd_pcm_client_fast_ops;
-       handle->fast_op_arg = handle;
-       handle->mode = mode;
-       handle->private = client;
-       err = snd_pcm_init(handle);
-       if (err < 0) {
-               snd_pcm_close(handle);
-               return err;
-       }
-       *handlep = handle;
-       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;
-}
-
-int _snd_pcm_client_open(snd_pcm_t **pcmp, char *name, snd_config_t *conf,
-                        int stream, int mode)
-{
-       snd_config_iterator_t i;
-       char *socket = NULL;
-       char *sname = 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, "stream") == 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, "sname") == 0) {
-                       err = snd_config_string_get(n, &sname);
-                       if (err < 0)
-                               return -EINVAL;
-                       continue;
-               }
-               return -EINVAL;
-       }
-       if (!sname)
-               return -EINVAL;
-       if (socket) {
-               if (port >= 0 || host)
-                       return -EINVAL;
-               return snd_pcm_client_create(pcmp, socket, -1, SND_TRANSPORT_TYPE_SHM, sname, stream, mode);
-       } else  {
-               if (port < 0 || !name)
-                       return -EINVAL;
-               return snd_pcm_client_create(pcmp, host, port, SND_TRANSPORT_TYPE_TCP, sname, stream, mode);
-       }
-}
-                               
index 0391554b24c6aaf5ed08bc5fe2ab2c694f6b876b..602773004687b6d0b7783d97d5881e578002a7a9 100644 (file)
@@ -219,7 +219,7 @@ static ssize_t snd_pcm_file_readn(snd_pcm_t *pcm, void **bufs, size_t size)
 static ssize_t snd_pcm_file_mmap_forward(snd_pcm_t *pcm, size_t size)
 {
        snd_pcm_file_t *file = pcm->private;
-       size_t ofs = pcm->mmap_control->appl_ptr % pcm->setup.buffer_size;
+       size_t ofs = snd_pcm_mmap_offset(pcm);
        ssize_t n = snd_pcm_mmap_forward(file->slave, size);
        size_t xfer = 0;
        if (n <= 0)
@@ -244,60 +244,28 @@ static ssize_t snd_pcm_file_avail_update(snd_pcm_t *pcm)
        return snd_pcm_avail_update(file->slave);
 }
 
-static int snd_pcm_file_mmap_status(snd_pcm_t *pcm)
+static int snd_pcm_file_mmap(snd_pcm_t *pcm)
 {
        snd_pcm_file_t *file = pcm->private;
-       int err = snd_pcm_mmap_status(file->slave, &pcm->mmap_status);
+       int err = snd_pcm_mmap(file->slave);
        if (err < 0)
                return err;
-       pcm->mmap_status = file->slave->mmap_status;
+       pcm->mmap_info_count = file->slave->mmap_info_count;
+       pcm->mmap_info = file->slave->mmap_info;
        return 0;
 }
 
-static int snd_pcm_file_mmap_control(snd_pcm_t *pcm)
+static int snd_pcm_file_munmap(snd_pcm_t *pcm)
 {
        snd_pcm_file_t *file = pcm->private;
-       int err = snd_pcm_mmap_control(file->slave, &pcm->mmap_control);
+       int err = snd_pcm_munmap(file->slave);
        if (err < 0)
                return err;
-       pcm->mmap_control = file->slave->mmap_control;
+       pcm->mmap_info_count = 0;
+       pcm->mmap_info = 0;
        return 0;
 }
 
-static int snd_pcm_file_mmap_data(snd_pcm_t *pcm)
-{
-       snd_pcm_file_t *file = pcm->private;
-       int err = snd_pcm_mmap_data(file->slave, &pcm->mmap_data);
-       if (err < 0)
-               return err;
-       pcm->mmap_data = file->slave->mmap_data;
-       return 0;
-}
-
-static int snd_pcm_file_munmap_status(snd_pcm_t *pcm)
-{
-       snd_pcm_file_t *file = pcm->private;
-       return snd_pcm_munmap_status(file->slave);
-}
-
-static int snd_pcm_file_munmap_control(snd_pcm_t *pcm)
-{
-       snd_pcm_file_t *file = pcm->private;
-       return snd_pcm_munmap_control(file->slave);
-}
-
-static int snd_pcm_file_munmap_data(snd_pcm_t *pcm)
-{
-       snd_pcm_file_t *file = pcm->private;
-       return snd_pcm_munmap_data(file->slave);
-}
-
-static int snd_pcm_file_poll_descriptor(snd_pcm_t *pcm)
-{
-       snd_pcm_file_t *file = pcm->private;
-       return snd_pcm_poll_descriptor(file->slave);
-}
-
 static int snd_pcm_file_channels_mask(snd_pcm_t *pcm, bitset_t *cmask)
 {
        snd_pcm_file_t *file = pcm->private;
@@ -337,7 +305,7 @@ static void snd_pcm_file_dump(snd_pcm_t *pcm, FILE *fp)
        snd_pcm_dump(file->slave, fp);
 }
 
-struct snd_pcm_ops snd_pcm_file_ops = {
+snd_pcm_ops_t snd_pcm_file_ops = {
        close: snd_pcm_file_close,
        info: snd_pcm_file_info,
        params_info: snd_pcm_file_params_info,
@@ -349,15 +317,11 @@ struct snd_pcm_ops snd_pcm_file_ops = {
        dump: snd_pcm_file_dump,
        nonblock: snd_pcm_file_nonblock,
        async: snd_pcm_file_async,
-       mmap_status: snd_pcm_file_mmap_status,
-       mmap_control: snd_pcm_file_mmap_control,
-       mmap_data: snd_pcm_file_mmap_data,
-       munmap_status: snd_pcm_file_munmap_status,
-       munmap_control: snd_pcm_file_munmap_control,
-       munmap_data: snd_pcm_file_munmap_data,
+       mmap: snd_pcm_file_mmap,
+       munmap: snd_pcm_file_munmap,
 };
 
-struct snd_pcm_fast_ops snd_pcm_file_fast_ops = {
+snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
        status: snd_pcm_file_status,
        state: snd_pcm_file_state,
        delay: snd_pcm_file_delay,
@@ -371,18 +335,16 @@ struct snd_pcm_fast_ops snd_pcm_file_fast_ops = {
        writen: snd_pcm_file_writen,
        readi: snd_pcm_file_readi,
        readn: snd_pcm_file_readn,
-       poll_descriptor: snd_pcm_file_poll_descriptor,
        channels_mask: snd_pcm_file_channels_mask,
        avail_update: snd_pcm_file_avail_update,
        mmap_forward: snd_pcm_file_mmap_forward,
 };
 
-int snd_pcm_file_open(snd_pcm_t **handlep, char *name, char *fname, int fd, snd_pcm_t *slave, int close_slave)
+int snd_pcm_file_open(snd_pcm_t **pcmp, char *name, char *fname, int fd, snd_pcm_t *slave, int close_slave)
 {
-       snd_pcm_t *handle;
+       snd_pcm_t *pcm;
        snd_pcm_file_t *file;
-       int err;
-       assert(handlep && slave);
+       assert(pcmp && slave);
        if (fname) {
                fd = open(fname, O_WRONLY|O_CREAT, 0666);
                if (fd < 0)
@@ -397,27 +359,25 @@ int snd_pcm_file_open(snd_pcm_t **handlep, char *name, char *fname, int fd, snd_
        file->slave = slave;
        file->close_slave = close_slave;
 
-       handle = calloc(1, sizeof(snd_pcm_t));
-       if (!handle) {
+       pcm = calloc(1, sizeof(snd_pcm_t));
+       if (!pcm) {
                free(file);
                return -ENOMEM;
        }
        if (name)
-               handle->name = strdup(name);
-       handle->type = SND_PCM_TYPE_FILE;
-       handle->stream = slave->stream;
-       handle->ops = &snd_pcm_file_ops;
-       handle->op_arg = handle;
-       handle->fast_ops = &snd_pcm_file_fast_ops;
-       handle->fast_op_arg = handle;
-       handle->mode = slave->mode;
-       handle->private = file;
-       err = snd_pcm_init(handle);
-       if (err < 0) {
-               snd_pcm_close(handle);
-               return err;
-       }
-       *handlep = handle;
+               pcm->name = strdup(name);
+       pcm->type = SND_PCM_TYPE_FILE;
+       pcm->stream = slave->stream;
+       pcm->mode = slave->mode;
+       pcm->ops = &snd_pcm_file_ops;
+       pcm->op_arg = pcm;
+       pcm->fast_ops = &snd_pcm_file_fast_ops;
+       pcm->fast_op_arg = pcm;
+       pcm->private = file;
+       pcm->poll_fd = slave->poll_fd;
+       pcm->hw_ptr = slave->hw_ptr;
+       pcm->appl_ptr = slave->appl_ptr;
+       *pcmp = pcm;
 
        return 0;
 }
index 30fd375072b3936643259e4623b36b26b838b28c..3b1166a62cb8681e9820a328dc7a7be86bb72ee0 100644 (file)
 typedef struct {
        int fd;
        int card, device, subdevice;
-       int mmap_emulation;
+       volatile snd_pcm_mmap_status_t *mmap_status;
+       snd_pcm_mmap_control_t *mmap_control;
 } snd_pcm_hw_t;
 
 #define SND_FILE_PCM_STREAM_PLAYBACK           "/dev/snd/pcmC%iD%ip"
 #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(snd_pcm_t *pcm)
-{
-       snd_pcm_hw_t *hw = pcm->private;
-       int fd = hw->fd;
-       free(hw);
-       if (close(fd)) {
-               ERR("close failed\n");
-               return -errno;
-       }
-       return 0;
-}
-
 static int snd_pcm_hw_nonblock(snd_pcm_t *pcm, int nonblock)
 {
        long flags;
@@ -158,9 +147,7 @@ static int snd_pcm_hw_setup(snd_pcm_t *pcm, snd_pcm_setup_t * setup)
                        setup->mmap_shape = SND_PCM_MMAP_INTERLEAVED;
                else
                        setup->mmap_shape = SND_PCM_MMAP_NONINTERLEAVED;
-               hw->mmap_emulation = 1;
-       } else
-               hw->mmap_emulation = 0;
+       }
        return 0;
 }
 
@@ -194,19 +181,21 @@ static int snd_pcm_hw_channel_setup(snd_pcm_t *pcm, snd_pcm_channel_setup_t * se
                ERR("SND_PCM_IOCTL_CHANNEL_SETUP failed");
                return -errno;
        }
-       if (hw->mmap_emulation) {
-               if (pcm->setup.mmap_shape == SND_PCM_MMAP_INTERLEAVED) {
-                       setup->running_area.addr = pcm->mmap_data;
+       if (!pcm->mmap_info)
+               return 0;
+       if (pcm->setup.mmap_shape == SND_PCM_MMAP_UNSPECIFIED) {
+               if (pcm->setup.xfer_mode == SND_PCM_XFER_INTERLEAVED) {
+                       setup->running_area.addr = pcm->mmap_info->addr;
                        setup->running_area.first = setup->channel * pcm->bits_per_sample;
                        setup->running_area.step = pcm->bits_per_frame;
                } else {
-                       setup->running_area.addr = pcm->mmap_data + setup->channel * pcm->setup.buffer_size * pcm->bits_per_sample / 8;
+                       setup->running_area.addr = pcm->mmap_info->addr + setup->channel * pcm->setup.buffer_size * pcm->bits_per_sample / 8;
                        setup->running_area.first = 0;
                        setup->running_area.step = pcm->bits_per_sample;
                }
                setup->stopped_area = setup->running_area;
        } else {
-               setup->running_area.addr = (char *)pcm->mmap_data + (long)setup->running_area.addr;
+               setup->running_area.addr = pcm->mmap_info->addr + (long)setup->running_area.addr;
                setup->stopped_area.addr = setup->running_area.addr;
        }
        return 0;
@@ -225,7 +214,8 @@ static int snd_pcm_hw_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 
 static int snd_pcm_hw_state(snd_pcm_t *pcm)
 {
-       return pcm->mmap_status->state;
+       snd_pcm_hw_t *hw = pcm->private;
+       return hw->mmap_status->state;
 }
 
 static int snd_pcm_hw_delay(snd_pcm_t *pcm, ssize_t *delayp)
@@ -378,7 +368,8 @@ static int snd_pcm_hw_mmap_status(snd_pcm_t *pcm)
                ERR("status mmap failed");
                return -errno;
        }
-       pcm->mmap_status = ptr;
+       hw->mmap_status = ptr;
+       pcm->hw_ptr = &hw->mmap_status->hw_ptr;
        return 0;
 }
 
@@ -392,36 +383,50 @@ static int snd_pcm_hw_mmap_control(snd_pcm_t *pcm)
                ERR("control mmap failed");
                return -errno;
        }
-       pcm->mmap_control = ptr;
+       hw->mmap_control = ptr;
+       pcm->appl_ptr = &hw->mmap_control->appl_ptr;
        return 0;
 }
 
-static int snd_pcm_hw_mmap_data(snd_pcm_t *pcm)
+static int snd_pcm_hw_mmap(snd_pcm_t *pcm)
 {
        snd_pcm_hw_t *hw = pcm->private;
-       void *ptr;
-       if (hw->mmap_emulation) {
-               ptr = malloc(snd_pcm_frames_to_bytes(pcm, pcm->setup.buffer_size));
-               if (!ptr)
+       pcm->mmap_info = calloc(1, sizeof(*pcm->mmap_info));
+       if (!pcm->mmap_info)
+               return -ENOMEM;
+       pcm->mmap_info_count = 1;
+       if (pcm->setup.mmap_shape == SND_PCM_MMAP_UNSPECIFIED) {
+               pcm->mmap_info->type = SND_PCM_MMAP_USER;
+               pcm->mmap_info->size = snd_pcm_frames_to_bytes(pcm, pcm->setup.buffer_size);
+               pcm->mmap_info->addr = valloc(pcm->mmap_info->size);
+               if (!pcm->mmap_info->addr) {
+                       free(pcm->mmap_info);
+                       pcm->mmap_info = 0;
                        return -ENOMEM;
+               }
        } else {
-               int prot;
-               prot = PROT_WRITE | PROT_READ;
-               ptr = mmap(NULL, pcm->setup.mmap_bytes,
-                          prot, MAP_FILE|MAP_SHARED, 
-                          hw->fd, SND_PCM_MMAP_OFFSET_DATA);
-               if (ptr == MAP_FAILED || ptr == NULL) {
+               pcm->mmap_info->type = SND_PCM_MMAP_KERNEL;
+               pcm->mmap_info->size = pcm->setup.mmap_bytes;
+               pcm->mmap_info->addr = mmap(NULL, pcm->setup.mmap_bytes,
+                                           PROT_WRITE | PROT_READ,
+                                           MAP_FILE|MAP_SHARED, 
+                                           hw->fd, SND_PCM_MMAP_OFFSET_DATA);
+               if (pcm->mmap_info->addr == MAP_FAILED ||
+                   pcm->mmap_info->addr == NULL) {
                        ERR("data mmap failed");
+                       free(pcm->mmap_info);
+                       pcm->mmap_info = 0;
                        return -errno;
                }
+               pcm->mmap_info->u.kernel.fd = hw->fd;
        }
-       pcm->mmap_data = ptr;
        return 0;
 }
 
 static int snd_pcm_hw_munmap_status(snd_pcm_t *pcm)
 {
-       if (munmap((void*)pcm->mmap_status, sizeof(*pcm->mmap_status)) < 0) {
+       snd_pcm_hw_t *hw = pcm->private;
+       if (munmap((void*)hw->mmap_status, sizeof(*hw->mmap_status)) < 0) {
                ERR("status munmap failed");
                return -errno;
        }
@@ -430,30 +435,46 @@ static int snd_pcm_hw_munmap_status(snd_pcm_t *pcm)
 
 static int snd_pcm_hw_munmap_control(snd_pcm_t *pcm)
 {
-       if (munmap(pcm->mmap_control, sizeof(*pcm->mmap_control)) < 0) {
+       snd_pcm_hw_t *hw = pcm->private;
+       if (munmap(hw->mmap_control, sizeof(*hw->mmap_control)) < 0) {
                ERR("control munmap failed");
                return -errno;
        }
        return 0;
 }
 
-static int snd_pcm_hw_munmap_data(snd_pcm_t *pcm)
+static int snd_pcm_hw_munmap(snd_pcm_t *pcm)
 {
-       snd_pcm_hw_t *hw = pcm->private;
-       if (hw->mmap_emulation)
-               free(pcm->mmap_data);
+       if (pcm->setup.mmap_shape == SND_PCM_MMAP_UNSPECIFIED)
+               free(pcm->mmap_info->addr);
        else
-               if (munmap(pcm->mmap_data, pcm->setup.mmap_bytes) < 0) {
+               if (munmap(pcm->mmap_info->addr, pcm->mmap_info->size) < 0) {
                        ERR("data munmap failed");
                        return -errno;
                }
+       pcm->mmap_info_count = 0;
+       free(pcm->mmap_info);
+       pcm->mmap_info = 0;
        return 0;
 }
 
-static ssize_t snd_pcm_hw_mmap_forward(snd_pcm_t *pcm, size_t size)
+static int snd_pcm_hw_close(snd_pcm_t *pcm)
 {
        snd_pcm_hw_t *hw = pcm->private;
-       if (hw->mmap_emulation && pcm->stream == SND_PCM_STREAM_PLAYBACK)
+       int fd = hw->fd;
+       free(hw);
+       if (close(fd)) {
+               ERR("close failed\n");
+               return -errno;
+       }
+       snd_pcm_hw_munmap_status(pcm);
+       snd_pcm_hw_munmap_control(pcm);
+       return 0;
+}
+
+static ssize_t snd_pcm_hw_mmap_forward(snd_pcm_t *pcm, size_t size)
+{
+       if (pcm->setup.mmap_shape == SND_PCM_MMAP_UNSPECIFIED && pcm->stream == SND_PCM_STREAM_PLAYBACK)
                return snd_pcm_write_mmap(pcm, size);
        snd_pcm_mmap_appl_forward(pcm, size);
        return size;
@@ -461,7 +482,6 @@ static ssize_t snd_pcm_hw_mmap_forward(snd_pcm_t *pcm, size_t size)
 
 static ssize_t snd_pcm_hw_avail_update(snd_pcm_t *pcm)
 {
-       snd_pcm_hw_t *hw = pcm->private;
        size_t avail;
        ssize_t err;
        if (pcm->setup.ready_mode == SND_PCM_READY_ASAP ||
@@ -475,7 +495,7 @@ static ssize_t snd_pcm_hw_avail_update(snd_pcm_t *pcm)
                avail = snd_pcm_mmap_playback_avail(pcm);
        } else {
                avail = snd_pcm_mmap_capture_avail(pcm);
-               if (avail > 0 && hw->mmap_emulation) {
+               if (avail > 0 && pcm->setup.mmap_shape == SND_PCM_MMAP_UNSPECIFIED) {
                        err = snd_pcm_read_mmap(pcm, avail);
                        if (err < 0)
                                return err;
@@ -488,12 +508,6 @@ static ssize_t snd_pcm_hw_avail_update(snd_pcm_t *pcm)
        return avail;
 }
 
-static int snd_pcm_hw_poll_descriptor(snd_pcm_t *pcm)
-{
-       snd_pcm_hw_t *hw = pcm->private;
-       return hw->fd;
-}
-
 static int snd_pcm_hw_channels_mask(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
                                    bitset_t *cmask ATTRIBUTE_UNUSED)
 {
@@ -514,7 +528,7 @@ static void snd_pcm_hw_dump(snd_pcm_t *pcm, FILE *fp)
        }
 }
 
-struct snd_pcm_ops snd_pcm_hw_ops = {
+snd_pcm_ops_t snd_pcm_hw_ops = {
        close: snd_pcm_hw_close,
        info: snd_pcm_hw_info,
        params_info: snd_pcm_hw_params_info,
@@ -526,15 +540,11 @@ struct snd_pcm_ops snd_pcm_hw_ops = {
        dump: snd_pcm_hw_dump,
        nonblock: snd_pcm_hw_nonblock,
        async: snd_pcm_hw_async,
-       mmap_status: snd_pcm_hw_mmap_status,
-       mmap_control: snd_pcm_hw_mmap_control,
-       mmap_data: snd_pcm_hw_mmap_data,
-       munmap_status: snd_pcm_hw_munmap_status,
-       munmap_control: snd_pcm_hw_munmap_control,
-       munmap_data: snd_pcm_hw_munmap_data,
+       mmap: snd_pcm_hw_mmap,
+       munmap: snd_pcm_hw_munmap,
 };
 
-struct snd_pcm_fast_ops snd_pcm_hw_fast_ops = {
+snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
        status: snd_pcm_hw_status,
        state: snd_pcm_hw_state,
        delay: snd_pcm_hw_delay,
@@ -548,13 +558,12 @@ struct snd_pcm_fast_ops snd_pcm_hw_fast_ops = {
        writen: snd_pcm_hw_writen,
        readi: snd_pcm_hw_readi,
        readn: snd_pcm_hw_readn,
-       poll_descriptor: snd_pcm_hw_poll_descriptor,
        channels_mask: snd_pcm_hw_channels_mask,
        avail_update: snd_pcm_hw_avail_update,
        mmap_forward: snd_pcm_hw_mmap_forward,
 };
 
-int snd_pcm_hw_open_subdevice(snd_pcm_t **handlep, int card, int device, int subdevice, int stream, int mode)
+int snd_pcm_hw_open_subdevice(snd_pcm_t **pcmp, int card, int device, int subdevice, int stream, int mode)
 {
        char filename[32];
        char *filefmt;
@@ -564,12 +573,12 @@ int snd_pcm_hw_open_subdevice(snd_pcm_t **handlep, int card, int device, int sub
        snd_pcm_info_t info;
        int fmode;
        snd_ctl_t *ctl;
-       snd_pcm_t *handle;
-       snd_pcm_hw_t *hw;
+       snd_pcm_t *pcm = NULL;
+       snd_pcm_hw_t *hw = NULL;
 
-       assert(handlep);
+       assert(pcmp);
 
-       if ((ret = snd_ctl_hw_open(&ctl, card)) < 0)
+       if ((ret = snd_ctl_hw_open(&ctl, NULL, card)) < 0)
                return ret;
 
        switch (stream) {
@@ -582,37 +591,35 @@ int snd_pcm_hw_open_subdevice(snd_pcm_t **handlep, int card, int device, int sub
        default:
                assert(0);
        }
-       if ((ret = snd_ctl_pcm_prefer_subdevice(ctl, subdevice)) < 0)
-               goto __end;
+       ret = snd_ctl_pcm_prefer_subdevice(ctl, subdevice);
+       snd_ctl_close(ctl);
+       if (ret < 0)
+               return ret;
        sprintf(filename, filefmt, card, device);
 
       __again:
-       if (attempt++ > 3) {
-               ret = -EBUSY;
-               goto __end;
-       }
+       if (attempt++ > 3)
+               return -EBUSY;
        fmode = O_RDWR;
        if (mode & SND_PCM_NONBLOCK)
                fmode |= O_NONBLOCK;
        if (mode & SND_PCM_ASYNC)
                fmode |= O_ASYNC;
-       if ((fd = open(filename, fmode)) < 0) {
-               ret = -errno;
-               goto __end;
-       }
+       if ((fd = open(filename, fmode)) < 0)
+               return -errno;
        if (ioctl(fd, SND_PCM_IOCTL_PVERSION, &ver) < 0) {
                ret = -errno;
-               goto __end;
+               goto _err;
        }
        if (SND_PROTOCOL_INCOMPATIBLE(ver, SND_PCM_VERSION_MAX)) {
                ret = -SND_ERROR_INCOMPATIBLE_VERSION;
-               goto __end;
+               goto _err;
        }
        if (subdevice >= 0) {
                memset(&info, 0, sizeof(info));
                if (ioctl(fd, SND_PCM_IOCTL_INFO, &info) < 0) {
                        ret = -errno;
-                       goto __end;
+                       goto _err;
                }
                if (info.subdevice != subdevice) {
                        close(fd);
@@ -622,54 +629,61 @@ int snd_pcm_hw_open_subdevice(snd_pcm_t **handlep, int card, int device, int sub
        hw = calloc(1, sizeof(snd_pcm_hw_t));
        if (!hw) {
                ret = -ENOMEM;
-               goto __end;
+               goto _err;
        }
        hw->card = card;
        hw->device = device;
        hw->subdevice = subdevice;
        hw->fd = fd;
 
-       handle = calloc(1, sizeof(snd_pcm_t));
-       if (!handle) {
-               free(hw);
+       pcm = calloc(1, sizeof(snd_pcm_t));
+       if (!pcm) {
                ret = -ENOMEM;
-               goto __end;
-       }
-       handle->type = SND_PCM_TYPE_HW;
-       handle->stream = stream;
-       handle->ops = &snd_pcm_hw_ops;
-       handle->op_arg = handle;
-       handle->fast_ops = &snd_pcm_hw_fast_ops;
-       handle->fast_op_arg = handle;
-       handle->mode = mode;
-       handle->private = hw;
-       ret = snd_pcm_init(handle);
+               goto _err;
+       }
+       pcm->type = SND_PCM_TYPE_HW;
+       pcm->stream = stream;
+       pcm->mode = mode;
+       pcm->ops = &snd_pcm_hw_ops;
+       pcm->op_arg = pcm;
+       pcm->fast_ops = &snd_pcm_hw_fast_ops;
+       pcm->fast_op_arg = pcm;
+       pcm->private = hw;
+       pcm->poll_fd = fd;
+       *pcmp = pcm;
+       ret = snd_pcm_hw_mmap_status(pcm);
        if (ret < 0) {
-               snd_pcm_close(handle);
-               snd_ctl_close(ctl);
+               snd_pcm_close(pcm);
                return ret;
        }
-       *handlep = handle;
+       ret = snd_pcm_hw_mmap_control(pcm);
+       if (ret < 0) {
+               snd_pcm_close(pcm);
+               return ret;
+       }
+       return 0;
        
- __end:
-       if (ret < 0 && fd >= 0)
-               close(fd);
-       snd_ctl_close(ctl);
+ _err:
+       if (hw)
+               free(hw);
+       if (pcm)
+               free(pcm);
+       close(fd);
        return ret;
 }
 
-int snd_pcm_hw_open_device(snd_pcm_t **handlep, int card, int device, int stream, int mode)
+int snd_pcm_hw_open_device(snd_pcm_t **pcmp, int card, int device, int stream, int mode)
 {
-       return snd_pcm_hw_open_subdevice(handlep, card, device, -1, stream, mode);
+       return snd_pcm_hw_open_subdevice(pcmp, card, device, -1, stream, mode);
 }
 
-int snd_pcm_hw_open(snd_pcm_t **handlep, char *name, int card, int device, int subdevice, int stream, int mode)
+int snd_pcm_hw_open(snd_pcm_t **pcmp, char *name, int card, int device, int subdevice, int stream, int mode)
 {
-       int err = snd_pcm_hw_open_subdevice(handlep, card, device, subdevice, stream, mode);
+       int err = snd_pcm_hw_open_subdevice(pcmp, card, device, subdevice, stream, mode);
        if (err < 0)
                return err;
        if (name)
-               (*handlep)->name = strdup(name);
+               (*pcmp)->name = strdup(name);
        return 0;
 }
 
index e92e1cca3d22bfdf44fcaf7e342e3acb9829ce56..31cddbefe7daf4163f37e313f499d45e2f5236ea 100644 (file)
@@ -114,11 +114,6 @@ static int snd_pcm_linear_params(snd_pcm_t *pcm, snd_pcm_params_t * params)
                params->fail_reason = SND_PCM_PARAMS_FAIL_INVAL;
                return -EINVAL;
        }
-       if (slave->mmap_data) {
-               err = snd_pcm_munmap_data(slave);
-               if (err < 0)
-                       return err;
-       }
        linear->cformat = params->format.sfmt;
        linear->cxfer_mode = params->xfer_mode;
        linear->cmmap_shape = params->mmap_shape;
@@ -129,10 +124,6 @@ static int snd_pcm_linear_params(snd_pcm_t *pcm, snd_pcm_params_t * params)
        params->format.sfmt = linear->cformat;
        params->xfer_mode = linear->cxfer_mode;
        params->mmap_shape = linear->cmmap_shape;
-       if (slave->valid_setup) {
-               int r = snd_pcm_mmap_data(slave, NULL);
-               assert(r >= 0);
-       }
        return err;
 }
 
@@ -244,7 +235,7 @@ static void snd_pcm_linear_dump(snd_pcm_t *pcm, FILE *fp)
        snd_pcm_dump(linear->plug.slave, fp);
 }
 
-struct snd_pcm_ops snd_pcm_linear_ops = {
+snd_pcm_ops_t snd_pcm_linear_ops = {
        close: snd_pcm_plugin_close,
        info: snd_pcm_plugin_info,
        params_info: snd_pcm_linear_params_info,
@@ -256,20 +247,15 @@ struct snd_pcm_ops snd_pcm_linear_ops = {
        dump: snd_pcm_linear_dump,
        nonblock: snd_pcm_plugin_nonblock,
        async: snd_pcm_plugin_async,
-       mmap_status: snd_pcm_plugin_mmap_status,
-       mmap_control: snd_pcm_plugin_mmap_control,
-       mmap_data: snd_pcm_plugin_mmap_data,
-       munmap_status: snd_pcm_plugin_munmap_status,
-       munmap_control: snd_pcm_plugin_munmap_control,
-       munmap_data: snd_pcm_plugin_munmap_data,
+       mmap: snd_pcm_plugin_mmap,
+       munmap: snd_pcm_plugin_munmap,
 };
 
-int snd_pcm_linear_open(snd_pcm_t **handlep, char *name, int sformat, snd_pcm_t *slave, int close_slave)
+int snd_pcm_linear_open(snd_pcm_t **pcmp, char *name, int sformat, snd_pcm_t *slave, int close_slave)
 {
-       snd_pcm_t *handle;
+       snd_pcm_t *pcm;
        snd_pcm_linear_t *linear;
-       int err;
-       assert(handlep && slave);
+       assert(pcmp && slave);
        if (snd_pcm_format_linear(sformat) != 1)
                return -EINVAL;
        linear = calloc(1, sizeof(snd_pcm_linear_t));
@@ -282,27 +268,25 @@ int snd_pcm_linear_open(snd_pcm_t **handlep, char *name, int sformat, snd_pcm_t
        linear->plug.slave = slave;
        linear->plug.close_slave = close_slave;
 
-       handle = calloc(1, sizeof(snd_pcm_t));
-       if (!handle) {
+       pcm = calloc(1, sizeof(snd_pcm_t));
+       if (!pcm) {
                free(linear);
                return -ENOMEM;
        }
        if (name)
-               handle->name = strdup(name);
-       handle->type = SND_PCM_TYPE_LINEAR;
-       handle->stream = slave->stream;
-       handle->ops = &snd_pcm_linear_ops;
-       handle->op_arg = handle;
-       handle->fast_ops = &snd_pcm_plugin_fast_ops;
-       handle->fast_op_arg = handle;
-       handle->mode = slave->mode;
-       handle->private = linear;
-       err = snd_pcm_init(handle);
-       if (err < 0) {
-               snd_pcm_close(handle);
-               return err;
-       }
-       *handlep = handle;
+               pcm->name = strdup(name);
+       pcm->type = SND_PCM_TYPE_LINEAR;
+       pcm->stream = slave->stream;
+       pcm->mode = slave->mode;
+       pcm->ops = &snd_pcm_linear_ops;
+       pcm->op_arg = pcm;
+       pcm->fast_ops = &snd_pcm_plugin_fast_ops;
+       pcm->fast_op_arg = pcm;
+       pcm->private = linear;
+       pcm->poll_fd = slave->poll_fd;
+       pcm->hw_ptr = &linear->plug.hw_ptr;
+       pcm->appl_ptr = &linear->plug.appl_ptr;
+       *pcmp = pcm;
 
        return 0;
 }
index 970578c949be3ffdd21fa6ef183e508e66d7dab9..6763c85317c55831f9f942075501bdc7a278ff91 100644 (file)
@@ -32,7 +32,7 @@
 #define ERR(args...) snd_pcm_error(__FILE__, __LINE__, __FUNCTION__, ##args)
 #endif
 
-struct snd_pcm_ops {
+typedef struct {
        int (*close)(snd_pcm_t *pcm);
        int (*nonblock)(snd_pcm_t *pcm, int nonblock);
        int (*async)(snd_pcm_t *pcm, int sig, pid_t pid);
@@ -44,15 +44,11 @@ struct snd_pcm_ops {
        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);
        void (*dump)(snd_pcm_t *pcm, FILE *fp);
-       int (*mmap_status)(snd_pcm_t *pcm);
-       int (*mmap_control)(snd_pcm_t *pcm);
-       int (*mmap_data)(snd_pcm_t *pcm);
-       int (*munmap_status)(snd_pcm_t *pcm);
-       int (*munmap_control)(snd_pcm_t *pcm);
-       int (*munmap_data)(snd_pcm_t *pcm);
-};
+       int (*mmap)(snd_pcm_t *pcm);
+       int (*munmap)(snd_pcm_t *pcm);
+} snd_pcm_ops_t;
 
-struct snd_pcm_fast_ops {
+typedef struct {
        int (*status)(snd_pcm_t *pcm, snd_pcm_status_t *status);
        int (*prepare)(snd_pcm_t *pcm);
        int (*start)(snd_pcm_t *pcm);
@@ -66,43 +62,55 @@ struct snd_pcm_fast_ops {
        ssize_t (*writen)(snd_pcm_t *pcm, void **bufs, size_t size);
        ssize_t (*readi)(snd_pcm_t *pcm, void *buffer, size_t size);
        ssize_t (*readn)(snd_pcm_t *pcm, void **bufs, size_t size);
-       int (*poll_descriptor)(snd_pcm_t *pcm);
        int (*channels_mask)(snd_pcm_t *pcm, bitset_t *cmask);
        ssize_t (*avail_update)(snd_pcm_t *pcm);
        ssize_t (*mmap_forward)(snd_pcm_t *pcm, size_t size);
-};
+} snd_pcm_fast_ops_t;
+
+typedef struct {
+       unsigned int index;
+       enum { SND_PCM_MMAP_KERNEL, SND_PCM_MMAP_USER } type;
+       void *addr;
+       size_t size;
+       union {
+               struct {
+                       int shmid;
+               } user;
+               struct {
+                       int fd;
+               } kernel;
+       } u;
+} snd_pcm_mmap_info_t;
 
 struct snd_pcm {
        char *name;
        snd_pcm_type_t type;
        int stream;
        int mode;
+       int poll_fd;
        int valid_setup;
        snd_pcm_setup_t setup;
        size_t bits_per_sample;
        size_t bits_per_frame;
-       volatile snd_pcm_mmap_status_t *mmap_status;
-       snd_pcm_mmap_control_t *mmap_control;
-       void *mmap_data;
+       size_t *appl_ptr;
+       volatile size_t *hw_ptr;
+       int mmap_auto;
+       size_t mmap_info_count;
+       snd_pcm_mmap_info_t *mmap_info;
        snd_pcm_channel_area_t *running_areas;
        snd_pcm_channel_area_t *stopped_areas;
-       struct snd_pcm_ops *ops;
-       struct snd_pcm_fast_ops *fast_ops;
+       snd_pcm_ops_t *ops;
+       snd_pcm_fast_ops_t *fast_ops;
        snd_pcm_t *op_arg;
        snd_pcm_t *fast_op_arg;
        void *private;
 };
 
-int snd_pcm_init(snd_pcm_t *pcm);
 void snd_pcm_areas_from_buf(snd_pcm_t *pcm, snd_pcm_channel_area_t *areas, void *buf);
 void snd_pcm_areas_from_bufs(snd_pcm_t *pcm, snd_pcm_channel_area_t *areas, void **bufs);
 
-int snd_pcm_mmap_status(snd_pcm_t *pcm, volatile snd_pcm_mmap_status_t **status);
-int snd_pcm_mmap_control(snd_pcm_t *pcm, snd_pcm_mmap_control_t **control);
-int snd_pcm_mmap_data(snd_pcm_t *pcm, void **buffer);
-int snd_pcm_munmap_status(snd_pcm_t *pcm);
-int snd_pcm_munmap_control(snd_pcm_t *pcm);
-int snd_pcm_munmap_data(snd_pcm_t *pcm);
+int snd_pcm_mmap(snd_pcm_t *pcm);
+int snd_pcm_munmap(snd_pcm_t *pcm);
 int snd_pcm_mmap_ready(snd_pcm_t *pcm);
 ssize_t snd_pcm_mmap_appl_ptr(snd_pcm_t *pcm, off_t offset);
 void snd_pcm_mmap_appl_backward(snd_pcm_t *pcm, size_t frames);
@@ -130,7 +138,7 @@ ssize_t snd_pcm_write_mmap(snd_pcm_t *pcm, size_t size);
 static inline size_t snd_pcm_mmap_playback_avail(snd_pcm_t *pcm)
 {
        ssize_t avail;
-       avail = pcm->mmap_status->hw_ptr + pcm->setup.buffer_size - pcm->mmap_control->appl_ptr;
+       avail = *pcm->hw_ptr + pcm->setup.buffer_size - *pcm->appl_ptr;
        if (avail < 0)
                avail += pcm->setup.boundary;
        return avail;
@@ -139,7 +147,7 @@ static inline size_t snd_pcm_mmap_playback_avail(snd_pcm_t *pcm)
 static inline size_t snd_pcm_mmap_capture_avail(snd_pcm_t *pcm)
 {
        ssize_t avail;
-       avail = pcm->mmap_status->hw_ptr - pcm->mmap_control->appl_ptr;
+       avail = *pcm->hw_ptr - *pcm->appl_ptr;
        if (avail < 0)
                avail += pcm->setup.boundary;
        return avail;
@@ -156,7 +164,7 @@ static inline size_t snd_pcm_mmap_avail(snd_pcm_t *pcm)
 static inline ssize_t snd_pcm_mmap_playback_hw_avail(snd_pcm_t *pcm)
 {
        ssize_t avail;
-       avail = pcm->mmap_status->hw_ptr + pcm->setup.buffer_size - pcm->mmap_control->appl_ptr;
+       avail = *pcm->hw_ptr + pcm->setup.buffer_size - *pcm->appl_ptr;
        if (avail < 0)
                avail += pcm->setup.boundary;
        return pcm->setup.buffer_size - avail;
@@ -165,7 +173,7 @@ static inline ssize_t snd_pcm_mmap_playback_hw_avail(snd_pcm_t *pcm)
 static inline ssize_t snd_pcm_mmap_capture_hw_avail(snd_pcm_t *pcm)
 {
        ssize_t avail;
-       avail = pcm->mmap_status->hw_ptr - pcm->mmap_control->appl_ptr;
+       avail = *pcm->hw_ptr - *pcm->appl_ptr;
        if (avail < 0)
                avail += pcm->setup.boundary;
        return pcm->setup.buffer_size - avail;
index e3afe0b29572b10960bc81462dfdca7b633c546f..ffdb84558070242591988423a02ed31b59d064b4 100644 (file)
@@ -36,12 +36,11 @@ snd_pcm_channel_area_t *snd_pcm_mmap_areas(snd_pcm_t *pcm)
 
 size_t snd_pcm_mmap_playback_xfer(snd_pcm_t *pcm, size_t frames)
 {
-       snd_pcm_mmap_control_t *control = pcm->mmap_control;
        size_t cont;
        size_t avail = snd_pcm_mmap_playback_avail(pcm);
        if (avail < frames)
                frames = avail;
-       cont = pcm->setup.buffer_size - control->appl_ptr % pcm->setup.buffer_size;
+       cont = pcm->setup.buffer_size - *pcm->appl_ptr % pcm->setup.buffer_size;
        if (cont < frames)
                frames = cont;
        return frames;
@@ -49,12 +48,11 @@ size_t snd_pcm_mmap_playback_xfer(snd_pcm_t *pcm, size_t frames)
 
 size_t snd_pcm_mmap_capture_xfer(snd_pcm_t *pcm, size_t frames)
 {
-       snd_pcm_mmap_control_t *control = pcm->mmap_control;
        size_t cont;
        size_t avail = snd_pcm_mmap_capture_avail(pcm);
        if (avail < frames)
                frames = avail;
-       cont = pcm->setup.buffer_size - control->appl_ptr % pcm->setup.buffer_size;
+       cont = pcm->setup.buffer_size - *pcm->appl_ptr % pcm->setup.buffer_size;
        if (cont < frames)
                frames = cont;
        return frames;
@@ -63,7 +61,6 @@ size_t snd_pcm_mmap_capture_xfer(snd_pcm_t *pcm, size_t frames)
 size_t snd_pcm_mmap_xfer(snd_pcm_t *pcm, size_t frames)
 {
         assert(pcm);
-       assert(pcm->mmap_status && pcm->mmap_control);
        if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
                return snd_pcm_mmap_playback_xfer(pcm, frames);
        else
@@ -73,51 +70,49 @@ size_t snd_pcm_mmap_xfer(snd_pcm_t *pcm, size_t frames)
 size_t snd_pcm_mmap_offset(snd_pcm_t *pcm)
 {
         assert(pcm);
-       assert(pcm->mmap_control);
-       return pcm->mmap_control->appl_ptr % pcm->setup.buffer_size;
+       return *pcm->appl_ptr % pcm->setup.buffer_size;
 }
 
 size_t snd_pcm_mmap_hw_offset(snd_pcm_t *pcm)
 {
         assert(pcm);
-       assert(pcm->mmap_status);
-       return pcm->mmap_status->hw_ptr % pcm->setup.buffer_size;
+       return *pcm->hw_ptr % pcm->setup.buffer_size;
 }
 
 void snd_pcm_mmap_appl_backward(snd_pcm_t *pcm, size_t frames)
 {
-       ssize_t appl_ptr = pcm->mmap_control->appl_ptr;
+       ssize_t appl_ptr = *pcm->appl_ptr;
        appl_ptr -= frames;
        if (appl_ptr < 0)
                appl_ptr += pcm->setup.boundary;
-       pcm->mmap_control->appl_ptr = appl_ptr;
+       *pcm->appl_ptr = appl_ptr;
 }
 
 void snd_pcm_mmap_appl_forward(snd_pcm_t *pcm, size_t frames)
 {
-       size_t appl_ptr = pcm->mmap_control->appl_ptr;
+       size_t appl_ptr = *pcm->appl_ptr;
        appl_ptr += frames;
        if (appl_ptr >= pcm->setup.boundary)
                appl_ptr -= pcm->setup.boundary;
-       pcm->mmap_control->appl_ptr = appl_ptr;
+       *pcm->appl_ptr = appl_ptr;
 }
 
 void snd_pcm_mmap_hw_backward(snd_pcm_t *pcm, size_t frames)
 {
-       ssize_t hw_ptr = pcm->mmap_status->hw_ptr;
+       ssize_t hw_ptr = *pcm->hw_ptr;
        hw_ptr -= frames;
        if (hw_ptr < 0)
                hw_ptr += pcm->setup.boundary;
-       pcm->mmap_status->hw_ptr = hw_ptr;
+       *pcm->hw_ptr = hw_ptr;
 }
 
 void snd_pcm_mmap_hw_forward(snd_pcm_t *pcm, size_t frames)
 {
-       size_t hw_ptr = pcm->mmap_status->hw_ptr;
+       size_t hw_ptr = *pcm->hw_ptr;
        hw_ptr += frames;
        if (hw_ptr >= pcm->setup.boundary)
                hw_ptr -= pcm->setup.boundary;
-       pcm->mmap_status->hw_ptr = hw_ptr;
+       *pcm->hw_ptr = hw_ptr;
 }
 
 ssize_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm,
@@ -216,32 +211,6 @@ ssize_t snd_pcm_mmap_readn(snd_pcm_t *pcm, void **bufs, size_t size)
                                  snd_pcm_mmap_read_areas);
 }
 
-int snd_pcm_mmap_status(snd_pcm_t *pcm, volatile snd_pcm_mmap_status_t **status)
-{
-       int err;
-       assert(pcm);
-       if (!pcm->mmap_status) {
-               if ((err = pcm->ops->mmap_status(pcm->op_arg)) < 0)
-                       return err;
-       }
-       if (status)
-               *status = pcm->mmap_status;
-       return 0;
-}
-
-int snd_pcm_mmap_control(snd_pcm_t *pcm, snd_pcm_mmap_control_t **control)
-{
-       int err;
-       assert(pcm);
-       if (!pcm->mmap_control) {
-               if ((err = pcm->ops->mmap_control(pcm->op_arg)) < 0)
-                       return err;
-       }
-       if (control)
-               *control = pcm->mmap_control;
-       return 0;
-}
-
 int snd_pcm_mmap_get_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *stopped_areas, snd_pcm_channel_area_t *running_areas)
 {
        snd_pcm_channel_setup_t setup;
@@ -249,7 +218,7 @@ int snd_pcm_mmap_get_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *stopped_areas
        unsigned int channel;
        int err;
        assert(pcm);
-       assert(pcm->mmap_data);
+       assert(pcm->mmap_info);
        if (!pcm->running_areas) {
                r = calloc(pcm->setup.format.channels, sizeof(*r));
                s = calloc(pcm->setup.format.channels, sizeof(*s));
@@ -274,75 +243,36 @@ int snd_pcm_mmap_get_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *stopped_areas
        return 0;
 }
 
-int snd_pcm_mmap_data(snd_pcm_t *pcm, void **data)
+int snd_pcm_mmap(snd_pcm_t *pcm)
 {
        int err;
        assert(pcm);
        assert(pcm->valid_setup);
-       if (pcm->mmap_data) {
-               if (data)
-                       *data = pcm->mmap_data;
+       if (pcm->mmap_info)
                return 0;
-       }
 
-       if ((err = pcm->ops->mmap_data(pcm->op_arg)) < 0)
+       if ((err = pcm->ops->mmap(pcm->op_arg)) < 0)
                return err;
-       if (data) 
-               *data = pcm->mmap_data;
        err = snd_pcm_mmap_get_areas(pcm, NULL, NULL);
        if (err < 0)
                return err;
        return 0;
 }
 
-int snd_pcm_munmap_status(snd_pcm_t *pcm)
-{
-       int err;
-       assert(pcm);
-       assert(pcm->mmap_status);
-       if ((err = pcm->ops->munmap_status(pcm->op_arg)) < 0)
-               return err;
-       pcm->mmap_status = 0;
-       return 0;
-}
-
-int snd_pcm_munmap_control(snd_pcm_t *pcm)
-{
-       int err;
-       assert(pcm);
-       assert(pcm->mmap_control);
-       if ((err = pcm->ops->munmap_control(pcm->op_arg)) < 0)
-               return err;
-       pcm->mmap_control = 0;
-       return 0;
-}
-
-int snd_pcm_munmap_data(snd_pcm_t *pcm)
+int snd_pcm_munmap(snd_pcm_t *pcm)
 {
        int err;
        assert(pcm);
-       assert(pcm->mmap_data);
-       if ((err = pcm->ops->munmap_data(pcm->op_arg)) < 0)
+       assert(pcm->mmap_info);
+       if ((err = pcm->ops->munmap(pcm->op_arg)) < 0)
                return err;
        free(pcm->stopped_areas);
        free(pcm->running_areas);
        pcm->stopped_areas = 0;
        pcm->running_areas = 0;
-       pcm->mmap_data = 0;
        return 0;
 }
 
-int snd_pcm_mmap(snd_pcm_t *pcm, void **data)
-{
-       return snd_pcm_mmap_data(pcm, data);
-}
-
-int snd_pcm_munmap(snd_pcm_t *pcm)
-{
-       return snd_pcm_munmap_data(pcm);
-}
-
-
 ssize_t snd_pcm_write_mmap(snd_pcm_t *pcm, size_t size)
 {
        size_t xfer = 0;
index ba6dc888c4083ae41bdd4781f9c3e47ff6aa7878..ae78f39a947fd271e3a555add906721d525d9500 100644 (file)
@@ -276,11 +276,6 @@ static int snd_pcm_mulaw_params(snd_pcm_t *pcm, snd_pcm_params_t * params)
                params->fail_reason = SND_PCM_PARAMS_FAIL_INVAL;
                return -EINVAL;
        }
-       if (slave->mmap_data) {
-               err = snd_pcm_munmap_data(slave);
-               if (err < 0)
-                       return err;
-       }
        mulaw->cformat = params->format.sfmt;
        mulaw->cxfer_mode = params->xfer_mode;
        mulaw->cmmap_shape = params->mmap_shape;
@@ -291,10 +286,6 @@ static int snd_pcm_mulaw_params(snd_pcm_t *pcm, snd_pcm_params_t * params)
        params->format.sfmt = mulaw->cformat;
        params->xfer_mode = mulaw->cxfer_mode;
        params->mmap_shape = mulaw->cmmap_shape;
-       if (slave->valid_setup) {
-               int r = snd_pcm_mmap_data(slave, NULL);
-               assert(r >= 0);
-       }
        return err;
 }
 
@@ -418,7 +409,7 @@ static void snd_pcm_mulaw_dump(snd_pcm_t *pcm, FILE *fp)
        snd_pcm_dump(mulaw->plug.slave, fp);
 }
 
-struct snd_pcm_ops snd_pcm_mulaw_ops = {
+snd_pcm_ops_t snd_pcm_mulaw_ops = {
        close: snd_pcm_plugin_close,
        info: snd_pcm_plugin_info,
        params_info: snd_pcm_mulaw_params_info,
@@ -430,20 +421,15 @@ struct snd_pcm_ops snd_pcm_mulaw_ops = {
        dump: snd_pcm_mulaw_dump,
        nonblock: snd_pcm_plugin_nonblock,
        async: snd_pcm_plugin_async,
-       mmap_status: snd_pcm_plugin_mmap_status,
-       mmap_control: snd_pcm_plugin_mmap_control,
-       mmap_data: snd_pcm_plugin_mmap_data,
-       munmap_status: snd_pcm_plugin_munmap_status,
-       munmap_control: snd_pcm_plugin_munmap_control,
-       munmap_data: snd_pcm_plugin_munmap_data,
+       mmap: snd_pcm_plugin_mmap,
+       munmap: snd_pcm_plugin_munmap,
 };
 
-int snd_pcm_mulaw_open(snd_pcm_t **handlep, char *name, int sformat, snd_pcm_t *slave, int close_slave)
+int snd_pcm_mulaw_open(snd_pcm_t **pcmp, char *name, int sformat, snd_pcm_t *slave, int close_slave)
 {
-       snd_pcm_t *handle;
+       snd_pcm_t *pcm;
        snd_pcm_mulaw_t *mulaw;
-       int err;
-       assert(handlep && slave);
+       assert(pcmp && slave);
        if (snd_pcm_format_linear(sformat) != 1 &&
            sformat != SND_PCM_SFMT_MU_LAW)
                return -EINVAL;
@@ -457,27 +443,25 @@ int snd_pcm_mulaw_open(snd_pcm_t **handlep, char *name, int sformat, snd_pcm_t *
        mulaw->plug.slave = slave;
        mulaw->plug.close_slave = close_slave;
 
-       handle = calloc(1, sizeof(snd_pcm_t));
-       if (!handle) {
+       pcm = calloc(1, sizeof(snd_pcm_t));
+       if (!pcm) {
                free(mulaw);
                return -ENOMEM;
        }
        if (name)
-               handle->name = strdup(name);
-       handle->type = SND_PCM_TYPE_MULAW;
-       handle->stream = slave->stream;
-       handle->ops = &snd_pcm_mulaw_ops;
-       handle->op_arg = handle;
-       handle->fast_ops = &snd_pcm_plugin_fast_ops;
-       handle->fast_op_arg = handle;
-       handle->mode = slave->mode;
-       handle->private = mulaw;
-       err = snd_pcm_init(handle);
-       if (err < 0) {
-               snd_pcm_close(handle);
-               return err;
-       }
-       *handlep = handle;
+               pcm->name = strdup(name);
+       pcm->type = SND_PCM_TYPE_MULAW;
+       pcm->stream = slave->stream;
+       pcm->mode = slave->mode;
+       pcm->ops = &snd_pcm_mulaw_ops;
+       pcm->op_arg = pcm;
+       pcm->fast_ops = &snd_pcm_plugin_fast_ops;
+       pcm->fast_op_arg = pcm;
+       pcm->private = mulaw;
+       pcm->poll_fd = slave->poll_fd;
+       pcm->hw_ptr = &mulaw->plug.hw_ptr;
+       pcm->appl_ptr = &mulaw->plug.appl_ptr;
+       *pcmp = pcm;
 
        return 0;
 }
index c317c112db3ae047d939897ab0ae0b1f76aeeb23..cd41dd31c5675c58130b115abff71dc2ccebfb82 100644 (file)
@@ -152,6 +152,60 @@ static int snd_pcm_multi_params_info(snd_pcm_t *pcm, snd_pcm_params_info_t *info
        return 0;
 }
 
+static int snd_pcm_multi_mmap(snd_pcm_t *pcm)
+{
+       snd_pcm_multi_t *multi = pcm->private;
+       unsigned int i;
+       size_t count = 0;
+       for (i = 0; i < multi->slaves_count; ++i) {
+               snd_pcm_t *slave = multi->slaves[i].pcm;
+               snd_pcm_setup_t *setup;
+               int err = snd_pcm_mmap(slave);
+               if (err < 0)
+                       return err;
+               count += slave->mmap_info_count;
+               setup = &slave->setup;
+               if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
+                       snd_pcm_channel_area_t r[setup->format.channels];
+                       snd_pcm_channel_area_t s[setup->format.channels];
+                       err = snd_pcm_mmap_get_areas(slave, s, r);
+                       if (err < 0)
+                               return err;
+                       err = snd_pcm_areas_silence(s, 0, setup->format.channels, setup->buffer_size, setup->format.sfmt);
+                       if (err < 0)
+                               return err;
+                       err = snd_pcm_areas_silence(r, 0, setup->format.channels, setup->buffer_size, setup->format.sfmt);
+                       if (err < 0)
+                               return err;
+               }
+       }
+       pcm->mmap_info_count = count;
+       pcm->mmap_info = malloc(count * sizeof(*pcm->mmap_info));
+       count = 0;
+       for (i = 0; i < multi->slaves_count; ++i) {
+               snd_pcm_t *slave = multi->slaves[i].pcm;
+               memcpy(&pcm->mmap_info[count], slave->mmap_info, slave->mmap_info_count * sizeof(*pcm->mmap_info));
+               count += slave->mmap_info_count;
+       }
+       return 0;
+}
+
+static int snd_pcm_multi_munmap(snd_pcm_t *pcm)
+{
+       snd_pcm_multi_t *multi = pcm->private;
+       unsigned int i;
+       for (i = 0; i < multi->slaves_count; ++i) {
+               snd_pcm_t *slave = multi->slaves[i].pcm;
+               int err = snd_pcm_munmap(slave);
+               if (err < 0)
+                       return err;
+       }
+       pcm->mmap_info_count = 0;
+       free(pcm->mmap_info);
+       pcm->mmap_info = 0;
+       return 0;
+}
+               
 static int snd_pcm_multi_params(snd_pcm_t *pcm, snd_pcm_params_t *params)
 {
        snd_pcm_multi_t *multi = pcm->private;
@@ -166,11 +220,6 @@ static int snd_pcm_multi_params(snd_pcm_t *pcm, snd_pcm_params_t *params)
        p = *params;
        for (i = 0; i < multi->slaves_count; ++i) {
                snd_pcm_t *slave = multi->slaves[i].pcm;
-               if (slave->mmap_data) {
-                       err = snd_pcm_munmap_data(slave);
-                       if (err < 0)
-                               return err;
-               }
                p.format.channels = multi->slaves[i].channels_count;
                err = snd_pcm_params(slave, &p);
                if (err < 0) {
@@ -179,14 +228,6 @@ static int snd_pcm_multi_params(snd_pcm_t *pcm, snd_pcm_params_t *params)
                        break;
                }
        }
-       for (i = 0; i < multi->slaves_count; ++i) {
-               snd_pcm_t *slave = multi->slaves[i].pcm;
-               snd_pcm_mmap_data(slave, NULL);
-               if (pcm->stream == SND_PCM_STREAM_PLAYBACK &&
-                   err == 0)
-                       snd_pcm_areas_silence(snd_pcm_mmap_areas(slave), 0, slave->setup.format.channels, 
-                                             slave->setup.buffer_size, slave->setup.format.sfmt);
-       }
        if (err == 0)
                multi->xfer_mode = params->xfer_mode;
        return err;
@@ -346,73 +387,6 @@ static ssize_t snd_pcm_multi_rewind(snd_pcm_t *pcm, size_t frames)
        return frames;
 }
 
-static int snd_pcm_multi_mmap_status(snd_pcm_t *pcm)
-{
-       snd_pcm_multi_t *multi = pcm->private;
-       pcm->mmap_status = multi->slaves[0].pcm->mmap_status;
-       return 0;
-}
-
-static int snd_pcm_multi_mmap_control(snd_pcm_t *pcm)
-{
-       snd_pcm_multi_t *multi = pcm->private;
-       pcm->mmap_control = multi->slaves[0].pcm->mmap_control;
-       return 0;
-}
-
-static int snd_pcm_multi_mmap_data(snd_pcm_t *pcm)
-{
-       snd_pcm_multi_t *multi = pcm->private;
-       unsigned int i;
-       for (i = 0; i < multi->slaves_count; ++i) {
-               snd_pcm_t *slave = multi->slaves[i].pcm;
-               int err = snd_pcm_mmap_data(slave, 0);
-               snd_pcm_setup_t *setup;
-               if (err < 0)
-                       return err;
-               setup = &slave->setup;
-               if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
-                       snd_pcm_channel_area_t r[setup->format.channels];
-                       snd_pcm_channel_area_t s[setup->format.channels];
-                       err = snd_pcm_mmap_get_areas(slave, s, r);
-                       if (err < 0)
-                               return err;
-                       err = snd_pcm_areas_silence(s, 0, setup->format.channels, setup->buffer_size, setup->format.sfmt);
-                       if (err < 0)
-                               return err;
-                       err = snd_pcm_areas_silence(r, 0, setup->format.channels, setup->buffer_size, setup->format.sfmt);
-                       if (err < 0)
-                               return err;
-               }
-       }
-       pcm->mmap_data = multi->slaves[0].pcm->mmap_data;
-       return 0;
-}
-
-static int snd_pcm_multi_munmap_status(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
-{
-       return 0;
-}
-               
-static int snd_pcm_multi_munmap_control(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
-{
-       return 0;
-}
-               
-static int snd_pcm_multi_munmap_data(snd_pcm_t *pcm)
-{
-       snd_pcm_multi_t *multi = pcm->private;
-       unsigned int i;
-       int ret = 0;
-       for (i = 0; i < multi->slaves_count; ++i) {
-               snd_pcm_t *slave = multi->slaves[i].pcm;
-               int err = snd_pcm_munmap_data(slave);
-               if (err < 0)
-                       ret = err;
-       }
-       return ret;
-}
-               
 static ssize_t snd_pcm_multi_mmap_forward(snd_pcm_t *pcm, size_t size)
 {
        snd_pcm_multi_t *multi = pcm->private;
@@ -500,7 +474,7 @@ static void snd_pcm_multi_dump(snd_pcm_t *pcm, FILE *fp)
        }
 }
 
-struct snd_pcm_ops snd_pcm_multi_ops = {
+snd_pcm_ops_t snd_pcm_multi_ops = {
        close: snd_pcm_multi_close,
        info: snd_pcm_multi_info,
        params_info: snd_pcm_multi_params_info,
@@ -512,15 +486,11 @@ struct snd_pcm_ops snd_pcm_multi_ops = {
        dump: snd_pcm_multi_dump,
        nonblock: snd_pcm_multi_nonblock,
        async: snd_pcm_multi_async,
-       mmap_status: snd_pcm_multi_mmap_status,
-       mmap_control: snd_pcm_multi_mmap_control,
-       mmap_data: snd_pcm_multi_mmap_data,
-       munmap_status: snd_pcm_multi_munmap_status,
-       munmap_control: snd_pcm_multi_munmap_control,
-       munmap_data: snd_pcm_multi_munmap_data,
+       mmap: snd_pcm_multi_mmap,
+       munmap: snd_pcm_multi_munmap,
 };
 
-struct snd_pcm_fast_ops snd_pcm_multi_fast_ops = {
+snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = {
        status: snd_pcm_multi_status,
        state: snd_pcm_multi_state,
        delay: snd_pcm_multi_delay,
@@ -534,28 +504,26 @@ struct snd_pcm_fast_ops snd_pcm_multi_fast_ops = {
        readi: snd_pcm_mmap_readi,
        readn: snd_pcm_mmap_readn,
        rewind: snd_pcm_multi_rewind,
-       poll_descriptor: snd_pcm_multi_poll_descriptor,
        channels_mask: snd_pcm_multi_channels_mask,
        avail_update: snd_pcm_multi_avail_update,
        mmap_forward: snd_pcm_multi_mmap_forward,
 };
 
-int snd_pcm_multi_open(snd_pcm_t **handlep, char *name,
+int snd_pcm_multi_open(snd_pcm_t **pcmp, char *name,
                       size_t slaves_count,
-                      snd_pcm_t **slaves_handle, size_t *schannels_count,
+                      snd_pcm_t **slaves_pcm, size_t *schannels_count,
                       size_t channels_count,
                       int *sidxs, unsigned int *schannels,
                       int close_slaves)
 {
-       snd_pcm_t *handle;
+       snd_pcm_t *pcm;
        snd_pcm_multi_t *multi;
        unsigned int i;
-       int err;
        int stream;
        char slave_map[32][32] = { { 0 } };
 
-       assert(handlep);
-       assert(slaves_count > 0 && slaves_handle && schannels_count);
+       assert(pcmp);
+       assert(slaves_count > 0 && slaves_pcm && schannels_count);
        assert(channels_count > 0 && sidxs && schannels);
 
        multi = calloc(1, sizeof(snd_pcm_multi_t));
@@ -563,7 +531,7 @@ int snd_pcm_multi_open(snd_pcm_t **handlep, char *name,
                return -ENOMEM;
        }
 
-       stream = slaves_handle[0]->stream;
+       stream = slaves_pcm[0]->stream;
        
        multi->slaves_count = slaves_count;
        multi->slaves = calloc(slaves_count, sizeof(*multi->slaves));
@@ -571,12 +539,12 @@ int snd_pcm_multi_open(snd_pcm_t **handlep, char *name,
        multi->channels = calloc(channels_count, sizeof(*multi->channels));
        for (i = 0; i < slaves_count; ++i) {
                snd_pcm_multi_slave_t *slave = &multi->slaves[i];
-               assert(slaves_handle[i]->stream == stream);
-               slave->pcm = slaves_handle[i];
+               assert(slaves_pcm[i]->stream == stream);
+               slave->pcm = slaves_pcm[i];
                slave->channels_count = schannels_count[i];
                slave->close_slave = close_slaves;
                if (i != 0)
-                       snd_pcm_link(slaves_handle[i-1], slaves_handle[i]);
+                       snd_pcm_link(slaves_pcm[i-1], slaves_pcm[i]);
        }
        for (i = 0; i < channels_count; ++i) {
                snd_pcm_multi_channel_t *bind = &multi->channels[i];
@@ -591,27 +559,26 @@ int snd_pcm_multi_open(snd_pcm_t **handlep, char *name,
        }
        multi->channels_count = channels_count;
 
-       handle = calloc(1, sizeof(snd_pcm_t));
-       if (!handle) {
+       pcm = calloc(1, sizeof(snd_pcm_t));
+       if (!pcm) {
                free(multi);
                return -ENOMEM;
        }
        if (name)
-               handle->name = strdup(name);
-       handle->type = SND_PCM_TYPE_MULTI;
-       handle->stream = stream;
-       handle->mode = multi->slaves[0].pcm->mode;
-       handle->ops = &snd_pcm_multi_ops;
-       handle->op_arg = handle;
-       handle->fast_ops = &snd_pcm_multi_fast_ops;
-       handle->fast_op_arg = handle;
-       handle->private = multi;
-       err = snd_pcm_init(handle);
-       if (err < 0) {
-               snd_pcm_close(handle);
-               return err;
-       }
-       *handlep = handle;
+               pcm->name = strdup(name);
+       pcm->type = SND_PCM_TYPE_MULTI;
+       pcm->stream = stream;
+       pcm->mode = multi->slaves[0].pcm->mode;
+       pcm->mmap_auto = 1;
+       pcm->ops = &snd_pcm_multi_ops;
+       pcm->op_arg = pcm;
+       pcm->fast_ops = &snd_pcm_multi_fast_ops;
+       pcm->fast_op_arg = pcm;
+       pcm->private = multi;
+       pcm->poll_fd = multi->slaves[0].pcm->poll_fd;
+       pcm->hw_ptr = multi->slaves[0].pcm->hw_ptr;
+       pcm->appl_ptr = multi->slaves[0].pcm->appl_ptr;
+       *pcmp = pcm;
        return 0;
 }
 
index 36ea8930bb2b469fdc22f00ee920f6261cab38c2..8c2a5f6d2e67fca37e970f0c1ab339179fd82b27 100644 (file)
@@ -323,6 +323,7 @@ static int snd_pcm_plug_change_rate(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm_for
        err = snd_pcm_rate_open(new, NULL, slv->sfmt, slv->rate, plug->slave, plug->slave != plug->req_slave);
        if (err < 0)
                return err;
+       (*new)->mmap_auto = 1;
        slv->rate = clt->rate;
        if (snd_pcm_format_linear(clt->sfmt))
                slv->sfmt = clt->sfmt;
@@ -387,6 +388,7 @@ static int snd_pcm_plug_change_channels(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm
        err = snd_pcm_route_open(new, NULL, slv->sfmt, slv->channels, ttable, tt_ssize, tt_cused, tt_sused, plug->slave, plug->slave != plug->req_slave);
        if (err < 0)
                return err;
+       (*new)->mmap_auto = 1;
        slv->channels = clt->channels;
        if (snd_pcm_format_linear(clt->sfmt))
                slv->sfmt = clt->sfmt;
@@ -397,7 +399,7 @@ static int snd_pcm_plug_change_format(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm_f
 {
        snd_pcm_plug_t *plug = pcm->private;
        int err, cfmt;
-       int (*f)(snd_pcm_t **handle, char *name, int sformat, snd_pcm_t *slave, int close_slave);
+       int (*f)(snd_pcm_t **pcm, char *name, int sformat, snd_pcm_t *slave, int close_slave);
        if (snd_pcm_format_linear(slv->sfmt)) {
                /* Conversion is done in another plugin */
                if (clt->sfmt == slv->sfmt ||
@@ -451,6 +453,7 @@ static int snd_pcm_plug_change_format(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm_f
        err = f(new, NULL, slv->sfmt, plug->slave, plug->slave != plug->req_slave);
        if (err < 0)
                return err;
+       (*new)->mmap_auto = 1;
        slv->sfmt = cfmt;
        return 1;
 }
@@ -489,6 +492,7 @@ static int snd_pcm_plug_insert_plugins(snd_pcm_t *pcm,
                }
                k++;
        }
+       plug->slave->mmap_auto = 0;
        assert(0);
        return 0;
 }
@@ -563,15 +567,16 @@ static int snd_pcm_plug_params(snd_pcm_t *pcm, snd_pcm_params_t *params)
                return err;
 
        err = snd_pcm_params(plug->slave, params);
-       if (err < 0)
+       if (err < 0) {
                snd_pcm_plug_clear(pcm);
-       else {
-               assert(slave->setup.format.sfmt == slave_format->sfmt);
-               assert(slave->setup.format.channels == slave_format->channels);
-               assert(slave->setup.format.rate == slave_format->rate);
+               return err;
        }
-
-       return err;
+       assert(slave->setup.format.sfmt == slave_format->sfmt);
+       assert(slave->setup.format.channels == slave_format->channels);
+       assert(slave->setup.format.rate == slave_format->rate);
+       pcm->hw_ptr = slave->hw_ptr;
+       pcm->appl_ptr = slave->appl_ptr;
+       return 0;
 }
 
 static int snd_pcm_plug_setup(snd_pcm_t *pcm, snd_pcm_setup_t *setup)
@@ -598,53 +603,27 @@ static int snd_pcm_plug_channel_setup(snd_pcm_t *pcm, snd_pcm_channel_setup_t *s
        return snd_pcm_channel_setup(plug->slave, setup);
 }
 
-static int snd_pcm_plug_mmap_status(snd_pcm_t *pcm)
+static int snd_pcm_plug_mmap(snd_pcm_t *pcm)
 {
        snd_pcm_plug_t *plug = pcm->private;
-       int err = snd_pcm_mmap_status(plug->slave, NULL);
+       int err = snd_pcm_mmap(plug->slave);
        if (err < 0)
                return err;
-       pcm->mmap_status = plug->slave->mmap_status;
+       pcm->mmap_info_count = plug->slave->mmap_info_count;
+       pcm->mmap_info = plug->slave->mmap_info;
        return 0;
 }
 
-static int snd_pcm_plug_mmap_control(snd_pcm_t *pcm)
+static int snd_pcm_plug_munmap(snd_pcm_t *pcm)
 {
        snd_pcm_plug_t *plug = pcm->private;
-       int err = snd_pcm_mmap_control(plug->slave, NULL);
+       int err = snd_pcm_munmap(plug->slave);
        if (err < 0)
                return err;
-       pcm->mmap_control = plug->slave->mmap_control;
+       pcm->mmap_info_count = 0;
+       pcm->mmap_info = 0;
        return 0;
 }
-
-static int snd_pcm_plug_mmap_data(snd_pcm_t *pcm)
-{
-       snd_pcm_plug_t *plug = pcm->private;
-       int err = snd_pcm_mmap_data(plug->slave, NULL);
-       if (err < 0)
-               return err;
-       pcm->mmap_data = plug->slave->mmap_data;
-       return 0;
-}
-
-static int snd_pcm_plug_munmap_status(snd_pcm_t *pcm)
-{
-       snd_pcm_plug_t *plug = pcm->private;
-       return snd_pcm_munmap_status(plug->slave);
-}
-               
-static int snd_pcm_plug_munmap_control(snd_pcm_t *pcm)
-{
-       snd_pcm_plug_t *plug = pcm->private;
-       return snd_pcm_munmap_control(plug->slave);
-}
-               
-static int snd_pcm_plug_munmap_data(snd_pcm_t *pcm)
-{
-       snd_pcm_plug_t *plug = pcm->private;
-       return snd_pcm_munmap_data(plug->slave);
-}
                
 static void snd_pcm_plug_dump(snd_pcm_t *pcm, FILE *fp)
 {
@@ -653,7 +632,7 @@ static void snd_pcm_plug_dump(snd_pcm_t *pcm, FILE *fp)
        snd_pcm_dump(plug->slave, fp);
 }
 
-struct snd_pcm_ops snd_pcm_plug_ops = {
+snd_pcm_ops_t snd_pcm_plug_ops = {
        close: snd_pcm_plug_close,
        info: snd_pcm_plug_info,
        params_info: snd_pcm_plug_params_info,
@@ -665,25 +644,20 @@ struct snd_pcm_ops snd_pcm_plug_ops = {
        dump: snd_pcm_plug_dump,
        nonblock: snd_pcm_plug_nonblock,
        async: snd_pcm_plug_async,
-       mmap_status: snd_pcm_plug_mmap_status,
-       mmap_control: snd_pcm_plug_mmap_control,
-       mmap_data: snd_pcm_plug_mmap_data,
-       munmap_status: snd_pcm_plug_munmap_status,
-       munmap_control: snd_pcm_plug_munmap_control,
-       munmap_data: snd_pcm_plug_munmap_data,
+       mmap: snd_pcm_plug_mmap,
+       munmap: snd_pcm_plug_munmap,
 };
 
-int snd_pcm_plug_open(snd_pcm_t **handlep,
+int snd_pcm_plug_open(snd_pcm_t **pcmp,
                      char *name,
                      ttable_entry_t *ttable,
                      unsigned int tt_ssize,
                      unsigned int tt_cused, unsigned int tt_sused,
                      snd_pcm_t *slave, int close_slave)
 {
-       snd_pcm_t *handle;
+       snd_pcm_t *pcm;
        snd_pcm_plug_t *plug;
-       int err;
-       assert(handlep && slave);
+       assert(pcmp && slave);
        plug = calloc(1, sizeof(snd_pcm_plug_t));
        if (!plug)
                return -ENOMEM;
@@ -694,44 +668,42 @@ int snd_pcm_plug_open(snd_pcm_t **handlep,
        plug->tt_cused = tt_cused;
        plug->tt_sused = tt_sused;
        
-       handle = calloc(1, sizeof(snd_pcm_t));
-       if (!handle) {
+       pcm = calloc(1, sizeof(snd_pcm_t));
+       if (!pcm) {
                free(plug);
                return -ENOMEM;
        }
        if (name)
-               handle->name = strdup(name);
-       handle->type = SND_PCM_TYPE_PLUG;
-       handle->stream = slave->stream;
-       handle->ops = &snd_pcm_plug_ops;
-       handle->op_arg = handle;
-       handle->fast_ops = slave->fast_ops;
-       handle->fast_op_arg = slave->fast_op_arg;
-       handle->mode = slave->mode;
-       handle->private = plug;
-       err = snd_pcm_init(handle);
-       if (err < 0) {
-               snd_pcm_close(handle);
-               return err;
-       }
-       *handlep = handle;
+               pcm->name = strdup(name);
+       pcm->type = SND_PCM_TYPE_PLUG;
+       pcm->stream = slave->stream;
+       pcm->mode = slave->mode;
+       pcm->ops = &snd_pcm_plug_ops;
+       pcm->op_arg = pcm;
+       pcm->fast_ops = slave->fast_ops;
+       pcm->fast_op_arg = slave->fast_op_arg;
+       pcm->private = plug;
+       pcm->poll_fd = slave->poll_fd;
+       pcm->hw_ptr = slave->hw_ptr;
+       pcm->appl_ptr = slave->appl_ptr;
+       *pcmp = pcm;
 
        return 0;
 }
 
-int snd_pcm_plug_open_subdevice(snd_pcm_t **handlep, int card, int device, int subdevice, int stream, int mode)
+int snd_pcm_plug_open_subdevice(snd_pcm_t **pcmp, int card, int device, int subdevice, int stream, int mode)
 {
        snd_pcm_t *slave;
        int err;
        err = snd_pcm_hw_open_subdevice(&slave, card, device, subdevice, stream, mode);
        if (err < 0)
                return err;
-       return snd_pcm_plug_open(handlep, NULL, 0, 0, 0, 0, slave, 1);
+       return snd_pcm_plug_open(pcmp, NULL, 0, 0, 0, 0, slave, 1);
 }
 
-int snd_pcm_plug_open_device(snd_pcm_t **handlep, int card, int device, int stream, int mode)
+int snd_pcm_plug_open_device(snd_pcm_t **pcmp, int card, int device, int stream, int mode)
 {
-       return snd_pcm_plug_open_subdevice(handlep, card, device, -1, stream, mode);
+       return snd_pcm_plug_open_subdevice(pcmp, card, device, -1, stream, mode);
 }
 
 #define MAX_CHANNELS 32
index 7fb5a0b40cdcee5f97f7bfae50f82c7855034523..18c553a058dd1b23c3f241d515d35475176c7d3d 100644 (file)
@@ -70,12 +70,14 @@ int snd_pcm_plugin_channel_setup(snd_pcm_t *pcm, snd_pcm_channel_setup_t * setup
        err = snd_pcm_channel_setup(plugin->slave, setup);
        if (err < 0)
                return err;
+       if (!pcm->mmap_info)
+               return 0;
        if (pcm->setup.mmap_shape == SND_PCM_MMAP_INTERLEAVED) {
-               setup->running_area.addr = pcm->mmap_data;
+               setup->running_area.addr = pcm->mmap_info->addr;
                setup->running_area.first = setup->channel * pcm->bits_per_sample;
                setup->running_area.step = pcm->bits_per_frame;
        } else {
-               setup->running_area.addr = pcm->mmap_data + setup->channel * pcm->setup.buffer_size * pcm->bits_per_sample / 8;
+               setup->running_area.addr = pcm->mmap_info->addr + setup->channel * pcm->setup.buffer_size * pcm->bits_per_sample / 8;
                setup->running_area.first = 0;
                setup->running_area.step = pcm->bits_per_sample;
        }
@@ -118,8 +120,8 @@ int snd_pcm_plugin_prepare(snd_pcm_t *pcm)
        int err = snd_pcm_prepare(plugin->slave);
        if (err < 0)
                return err;
-       plugin->mmap_status.hw_ptr = 0;
-       plugin->mmap_control.appl_ptr = 0;
+       plugin->hw_ptr = 0;
+       plugin->appl_ptr = 0;
        if (plugin->init) {
                err = plugin->init(pcm);
                if (err < 0)
@@ -276,7 +278,7 @@ ssize_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
        if (slave_size <= 0)
                return slave_size;
        if (pcm->stream == SND_PCM_STREAM_PLAYBACK ||
-           !pcm->mmap_data)
+           !pcm->mmap_info)
                return plugin->client_frames ?
                        plugin->client_frames(pcm, slave_size) : slave_size;
        client_xfer = snd_pcm_mmap_capture_avail(pcm);
@@ -301,42 +303,39 @@ ssize_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
        return err;
 }
 
-int snd_pcm_plugin_mmap_status(snd_pcm_t *pcm)
+int snd_pcm_plugin_mmap(snd_pcm_t *pcm)
 {
        snd_pcm_plugin_t *plugin = pcm->private;
-       pcm->mmap_status = &plugin->mmap_status;
-       return 0;
-}
-
-int snd_pcm_plugin_mmap_control(snd_pcm_t *pcm)
-{
-       snd_pcm_plugin_t *plugin = pcm->private;
-       pcm->mmap_control = &plugin->mmap_control;
-       return 0;
-}
-
-int snd_pcm_plugin_mmap_data(snd_pcm_t *pcm)
-{
-       void *ptr = malloc(snd_pcm_frames_to_bytes(pcm, pcm->setup.buffer_size));
-       if (!ptr)
+       snd_pcm_t *slave = plugin->slave;
+       int err = snd_pcm_mmap(slave);
+       if (err < 0)
+               return err;
+       pcm->mmap_info = calloc(1, sizeof(*pcm->mmap_info));
+       if (!pcm->mmap_info)
                return -ENOMEM;
-       pcm->mmap_data = ptr;
-       return 0;
-}
-
-int snd_pcm_plugin_munmap_status(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
-{
-       return 0;
-}
-
-int snd_pcm_plugin_munmap_control(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
-{
+       pcm->mmap_info_count = 1;
+       pcm->mmap_info->type = SND_PCM_MMAP_USER;
+       pcm->mmap_info->size = pcm->setup.buffer_size;
+       pcm->mmap_info->addr = valloc(snd_pcm_frames_to_bytes(pcm, pcm->setup.buffer_size));
+       if (!pcm->mmap_info->addr) {
+               free(pcm->mmap_info);
+               pcm->mmap_info = 0;
+               return -ENOMEM;
+       }
        return 0;
 }
 
-int snd_pcm_plugin_munmap_data(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
+int snd_pcm_plugin_munmap(snd_pcm_t *pcm)
 {
-       free(pcm->mmap_data);
+       snd_pcm_plugin_t *plugin = pcm->private;
+       snd_pcm_t *slave = plugin->slave;
+       int err = snd_pcm_munmap(slave);
+       if (err < 0)
+               return err;
+       free(pcm->mmap_info->addr);
+       free(pcm->mmap_info);
+       pcm->mmap_info_count = 0;
+       pcm->mmap_info = 0;
        return 0;
 }
 
@@ -392,7 +391,7 @@ int getput_index(int format)
        return width * 4 + endian * 2 + sign;
 }
 
-struct snd_pcm_fast_ops snd_pcm_plugin_fast_ops = {
+snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
        status: snd_pcm_plugin_status,
        state: snd_pcm_plugin_state,
        delay: snd_pcm_plugin_delay,
@@ -406,7 +405,6 @@ struct snd_pcm_fast_ops snd_pcm_plugin_fast_ops = {
        writen: snd_pcm_plugin_writen,
        readi: snd_pcm_plugin_readi,
        readn: snd_pcm_plugin_readn,
-       poll_descriptor: snd_pcm_plugin_poll_descriptor,
        channels_mask: snd_pcm_plugin_channels_mask,
        avail_update: snd_pcm_plugin_avail_update,
        mmap_forward: snd_pcm_plugin_mmap_forward,
index e86b1d06d7175821c15bca1184319da6a6b6cb38..13ec00af61c05f7cd894f7a10036c26aad55bf1d 100644 (file)
@@ -26,8 +26,7 @@ typedef struct {
        snd_pcm_xfer_areas_func_t write;
        size_t (*client_frames)(snd_pcm_t *pcm, size_t frames);
        int (*init)(snd_pcm_t *pcm);
-       snd_pcm_mmap_control_t mmap_control;
-       snd_pcm_mmap_status_t mmap_status;
+       size_t appl_ptr, hw_ptr;
 } snd_pcm_plugin_t;    
 
 int snd_pcm_plugin_close(snd_pcm_t *pcm);
@@ -54,10 +53,10 @@ ssize_t snd_pcm_plugin_mmap_forward(snd_pcm_t *pcm, size_t size);
 ssize_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm);
 int snd_pcm_plugin_mmap_status(snd_pcm_t *pcm);
 int snd_pcm_plugin_mmap_control(snd_pcm_t *pcm);
-int snd_pcm_plugin_mmap_data(snd_pcm_t *pcm);
+int snd_pcm_plugin_mmap(snd_pcm_t *pcm);
 int snd_pcm_plugin_munmap_status(snd_pcm_t *pcm);
 int snd_pcm_plugin_munmap_control(snd_pcm_t *pcm);
-int snd_pcm_plugin_munmap_data(snd_pcm_t *pcm);
+int snd_pcm_plugin_munmap(snd_pcm_t *pcm);
 int snd_pcm_plugin_poll_descriptor(snd_pcm_t *pcm);
 int snd_pcm_plugin_channels_mask(snd_pcm_t *pcm, bitset_t *cmask);
 int getput_index(int format);
@@ -71,7 +70,7 @@ int conv_index(int src_format, int dst_format);
                                SND_PCM_FMT_S32_LE | SND_PCM_FMT_S32_BE | \
                                SND_PCM_FMT_U32_LE | SND_PCM_FMT_U32_BE)
 
-extern struct snd_pcm_fast_ops snd_pcm_plugin_fast_ops;
+extern snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops;
 
 #define muldiv64(a,b,d) (((int64_t)(a) * (b) + (b) / 2) / (d))
 
@@ -88,19 +87,19 @@ typedef int ttable_entry_t;
 #define FULL ROUTE_PLUGIN_RESOLUTION
 #endif
 
-int snd_pcm_linear_open(snd_pcm_t **handlep, char *name, int sformat, snd_pcm_t *slave, int close_slave);
-int snd_pcm_mulaw_open(snd_pcm_t **handlep, char *name, int sformat, snd_pcm_t *slave, int close_slave);
-int snd_pcm_alaw_open(snd_pcm_t **handlep, char *name, int sformat, snd_pcm_t *slave, int close_slave);
-int snd_pcm_adpcm_open(snd_pcm_t **handlep, char *name, int sformat, snd_pcm_t *slave, int close_slave);
+int snd_pcm_linear_open(snd_pcm_t **pcmp, char *name, int sformat, snd_pcm_t *slave, int close_slave);
+int snd_pcm_mulaw_open(snd_pcm_t **pcmp, char *name, int sformat, snd_pcm_t *slave, int close_slave);
+int snd_pcm_alaw_open(snd_pcm_t **pcmp, char *name, int sformat, snd_pcm_t *slave, int close_slave);
+int snd_pcm_adpcm_open(snd_pcm_t **pcmp, char *name, int sformat, snd_pcm_t *slave, int close_slave);
 int snd_pcm_route_load_ttable(snd_config_t *tt, ttable_entry_t *ttable,
                              unsigned int tt_csize, unsigned int tt_ssize,
                              unsigned int *tt_cused, unsigned int *tt_sused,
                              int schannels);
-int snd_pcm_route_open(snd_pcm_t **handlep, char *name,
+int snd_pcm_route_open(snd_pcm_t **pcmp, char *name,
                       int sformat, unsigned int schannels,
                       ttable_entry_t *ttable,
                       unsigned int tt_ssize,
                       unsigned int tt_cused, unsigned int tt_sused,
                       snd_pcm_t *slave, int close_slave);
-int snd_pcm_rate_open(snd_pcm_t **handlep, char *name, int sformat, int srate, snd_pcm_t *slave, int close_slave);
+int snd_pcm_rate_open(snd_pcm_t **pcmp, char *name, int sformat, int srate, snd_pcm_t *slave, int close_slave);
 
index 43e5ee87911b292046d29bb16fbd062bb50a16cd..a804df514292bc380ed5126d0a1b6e33ba7ef35b 100644 (file)
@@ -326,12 +326,6 @@ static int snd_pcm_rate_params(snd_pcm_t *pcm, snd_pcm_params_t * params)
                return err;
        }
 
-       if (slave->mmap_data) {
-               err = snd_pcm_munmap_data(slave);
-               if (err < 0)
-                       return err;
-       }
-
        if (rate->req_srate - slave_info.min_rate < slave_info.max_rate - rate->req_srate)
                srate = slave_info.min_rate;
        else
@@ -349,10 +343,6 @@ static int snd_pcm_rate_params(snd_pcm_t *pcm, snd_pcm_params_t * params)
        err = snd_pcm_params(slave, &slave_params);
        params->fail_mask = slave_params.fail_mask;
        params->fail_reason = slave_params.fail_reason;
-       if (slave->valid_setup) {
-               int r = snd_pcm_mmap_data(slave, NULL);
-               assert(r >= 0);
-       }
        return err;
 }
 
@@ -565,7 +555,7 @@ static void snd_pcm_rate_dump(snd_pcm_t *pcm, FILE *fp)
        snd_pcm_dump(rate->plug.slave, fp);
 }
 
-struct snd_pcm_ops snd_pcm_rate_ops = {
+snd_pcm_ops_t snd_pcm_rate_ops = {
        close: snd_pcm_rate_close,
        info: snd_pcm_plugin_info,
        params_info: snd_pcm_rate_params_info,
@@ -577,20 +567,15 @@ struct snd_pcm_ops snd_pcm_rate_ops = {
        dump: snd_pcm_rate_dump,
        nonblock: snd_pcm_plugin_nonblock,
        async: snd_pcm_plugin_async,
-       mmap_status: snd_pcm_plugin_mmap_status,
-       mmap_control: snd_pcm_plugin_mmap_control,
-       mmap_data: snd_pcm_plugin_mmap_data,
-       munmap_status: snd_pcm_plugin_munmap_status,
-       munmap_control: snd_pcm_plugin_munmap_control,
-       munmap_data: snd_pcm_plugin_munmap_data,
+       mmap: snd_pcm_plugin_mmap,
+       munmap: snd_pcm_plugin_munmap,
 };
 
-int snd_pcm_rate_open(snd_pcm_t **handlep, char *name, int sformat, int srate, snd_pcm_t *slave, int close_slave)
+int snd_pcm_rate_open(snd_pcm_t **pcmp, char *name, int sformat, int srate, snd_pcm_t *slave, int close_slave)
 {
-       snd_pcm_t *handle;
+       snd_pcm_t *pcm;
        snd_pcm_rate_t *rate;
-       int err;
-       assert(handlep && slave);
+       assert(pcmp && slave);
        if (sformat >= 0 && snd_pcm_format_linear(sformat) != 1)
                return -EINVAL;
        rate = calloc(1, sizeof(snd_pcm_rate_t));
@@ -606,27 +591,25 @@ int snd_pcm_rate_open(snd_pcm_t **handlep, char *name, int sformat, int srate, s
        rate->plug.slave = slave;
        rate->plug.close_slave = close_slave;
 
-       handle = calloc(1, sizeof(snd_pcm_t));
-       if (!handle) {
+       pcm = calloc(1, sizeof(snd_pcm_t));
+       if (!pcm) {
                free(rate);
                return -ENOMEM;
        }
        if (name)
-               handle->name = strdup(name);
-       handle->type = SND_PCM_TYPE_RATE;
-       handle->stream = slave->stream;
-       handle->ops = &snd_pcm_rate_ops;
-       handle->op_arg = handle;
-       handle->fast_ops = &snd_pcm_plugin_fast_ops;
-       handle->fast_op_arg = handle;
-       handle->mode = slave->mode;
-       handle->private = rate;
-       err = snd_pcm_init(handle);
-       if (err < 0) {
-               snd_pcm_close(handle);
-               return err;
-       }
-       *handlep = handle;
+               pcm->name = strdup(name);
+       pcm->type = SND_PCM_TYPE_RATE;
+       pcm->stream = slave->stream;
+       pcm->mode = slave->mode;
+       pcm->ops = &snd_pcm_rate_ops;
+       pcm->op_arg = pcm;
+       pcm->fast_ops = &snd_pcm_plugin_fast_ops;
+       pcm->fast_op_arg = pcm;
+       pcm->private = rate;
+       pcm->poll_fd = slave->poll_fd;
+       pcm->hw_ptr = &rate->plug.hw_ptr;
+       pcm->appl_ptr = &rate->plug.appl_ptr;
+       *pcmp = pcm;
 
        return 0;
 }
index 347d83e028ea280a25272a11648ad8c0a0105bf9..c51be601d2c41070b464d2cf1a198ee6a2c9088e 100644 (file)
@@ -484,11 +484,6 @@ static int snd_pcm_route_params(snd_pcm_t *pcm, snd_pcm_params_t * params)
                params->fail_reason = SND_PCM_PARAMS_FAIL_INVAL;
                return -EINVAL;
        }
-       if (slave->mmap_data) {
-               err = snd_pcm_munmap_data(slave);
-               if (err < 0)
-                       return err;
-       }
        route->cformat = params->format.sfmt;
        route->cchannels = params->format.channels;
        route->cxfer_mode = params->xfer_mode;
@@ -504,10 +499,6 @@ static int snd_pcm_route_params(snd_pcm_t *pcm, snd_pcm_params_t * params)
        params->format.channels = route->cchannels;
        params->xfer_mode = route->cxfer_mode;
        params->mmap_shape = route->cmmap_shape;
-       if (slave->valid_setup) {
-               int r = snd_pcm_mmap_data(slave, NULL);
-               assert(r >= 0);
-       }
        return err;
 }
 
@@ -599,12 +590,14 @@ static int snd_pcm_route_channel_setup(snd_pcm_t *pcm, snd_pcm_channel_setup_t *
        if (err < 0)
                return err;
 #endif
+       if (!pcm->mmap_info)
+               return 0;
        if (pcm->setup.mmap_shape == SND_PCM_MMAP_INTERLEAVED) {
-               setup->running_area.addr = pcm->mmap_data;
+               setup->running_area.addr = pcm->mmap_info->addr;
                setup->running_area.first = setup->channel * pcm->bits_per_sample;
                setup->running_area.step = pcm->bits_per_frame;
        } else {
-               setup->running_area.addr = pcm->mmap_data + setup->channel * pcm->setup.buffer_size * pcm->bits_per_sample / 8;
+               setup->running_area.addr = pcm->mmap_info->addr + setup->channel * pcm->setup.buffer_size * pcm->bits_per_sample / 8;
                setup->running_area.first = 0;
                setup->running_area.step = pcm->bits_per_sample;
        }
@@ -684,7 +677,7 @@ static void snd_pcm_route_dump(snd_pcm_t *pcm, FILE *fp)
        snd_pcm_dump(route->plug.slave, fp);
 }
 
-struct snd_pcm_ops snd_pcm_route_ops = {
+snd_pcm_ops_t snd_pcm_route_ops = {
        close: snd_pcm_route_close,
        info: snd_pcm_plugin_info,
        params_info: snd_pcm_route_params_info,
@@ -696,12 +689,8 @@ struct snd_pcm_ops snd_pcm_route_ops = {
        dump: snd_pcm_route_dump,
        nonblock: snd_pcm_plugin_nonblock,
        async: snd_pcm_plugin_async,
-       mmap_status: snd_pcm_plugin_mmap_status,
-       mmap_control: snd_pcm_plugin_mmap_control,
-       mmap_data: snd_pcm_plugin_mmap_data,
-       munmap_status: snd_pcm_plugin_munmap_status,
-       munmap_control: snd_pcm_plugin_munmap_control,
-       munmap_data: snd_pcm_plugin_munmap_data,
+       mmap: snd_pcm_plugin_mmap,
+       munmap: snd_pcm_plugin_munmap,
 };
 
 int route_load_ttable(route_params_t *params, int stream,
@@ -776,17 +765,17 @@ int route_load_ttable(route_params_t *params, int stream,
 }
 
 
-int snd_pcm_route_open(snd_pcm_t **handlep, char *name,
+int snd_pcm_route_open(snd_pcm_t **pcmp, char *name,
                       int sformat, unsigned int schannels,
                       ttable_entry_t *ttable,
                       unsigned int tt_ssize,
                       unsigned int tt_cused, unsigned int tt_sused,
                       snd_pcm_t *slave, int close_slave)
 {
-       snd_pcm_t *handle;
+       snd_pcm_t *pcm;
        snd_pcm_route_t *route;
        int err;
-       assert(handlep && slave && ttable);
+       assert(pcmp && slave && ttable);
        if (sformat >= 0 && snd_pcm_format_linear(sformat) != 1)
                return -EINVAL;
        route = calloc(1, sizeof(snd_pcm_route_t));
@@ -800,32 +789,30 @@ int snd_pcm_route_open(snd_pcm_t **handlep, char *name,
        route->plug.slave = slave;
        route->plug.close_slave = close_slave;
 
-       handle = calloc(1, sizeof(snd_pcm_t));
-       if (!handle) {
+       pcm = calloc(1, sizeof(snd_pcm_t));
+       if (!pcm) {
                free(route);
                return -ENOMEM;
        }
        if (name)
-               handle->name = strdup(name);
-       handle->type = SND_PCM_TYPE_ROUTE;
-       handle->stream = slave->stream;
-       handle->ops = &snd_pcm_route_ops;
-       handle->op_arg = handle;
-       handle->fast_ops = &snd_pcm_plugin_fast_ops;
-       handle->fast_op_arg = handle;
-       handle->mode = slave->mode;
-       handle->private = route;
-       err = snd_pcm_init(handle);
-       if (err < 0) {
-               snd_pcm_close(handle);
-               return err;
-       }
-       err = route_load_ttable(&route->params, handle->stream, tt_ssize, ttable, tt_cused, tt_sused);
+               pcm->name = strdup(name);
+       pcm->type = SND_PCM_TYPE_ROUTE;
+       pcm->stream = slave->stream;
+       pcm->mode = slave->mode;
+       pcm->ops = &snd_pcm_route_ops;
+       pcm->op_arg = pcm;
+       pcm->fast_ops = &snd_pcm_plugin_fast_ops;
+       pcm->fast_op_arg = pcm;
+       pcm->private = route;
+       pcm->poll_fd = slave->poll_fd;
+       pcm->hw_ptr = &route->plug.hw_ptr;
+       pcm->appl_ptr = &route->plug.appl_ptr;
+       err = route_load_ttable(&route->params, pcm->stream, tt_ssize, ttable, tt_cused, tt_sused);
        if (err < 0) {
-               snd_pcm_close(handle);
+               snd_pcm_close(pcm);
                return err;
        }
-       *handlep = handle;
+       *pcmp = pcm;
 
        return 0;
 }
index 0b3e50f95d9c8238c70424b69b663046fb6922b1..9876afa9261ae44213c10c0003d9ac39024a1e40 100644 (file)
@@ -42,6 +42,7 @@ typedef struct {
        size_t channels_count;
        size_t open_count;
        size_t setup_count;
+       size_t mmap_count;
        size_t prepared_count;
        size_t running_count;
        size_t safety_threshold;
@@ -61,8 +62,9 @@ typedef struct {
        pid_t async_pid;
        struct timeval trigger_time;
        size_t draining_silence;
-       snd_pcm_mmap_control_t mmap_control;
-       snd_pcm_mmap_status_t mmap_status;
+       int state;
+       size_t hw_ptr;
+       size_t appl_ptr;
        int ready;
        int client_socket;
        int slave_socket;
@@ -79,7 +81,7 @@ static void snd_pcm_share_interrupt(snd_pcm_share_slave_t *slave)
                snd_pcm_share_t *share = list_entry(i, snd_pcm_share_t, list);
                snd_pcm_t *pcm = share->pcm;
                int ready;
-               switch (share->mmap_status.state) {
+               switch (share->state) {
                case SND_PCM_STATE_DRAINING:
                        if (pcm->stream == SND_PCM_STREAM_CAPTURE)
                                ready = 1;
@@ -146,7 +148,7 @@ static void snd_pcm_share_stop(snd_pcm_t *pcm, int state)
 {
        snd_pcm_share_t *share = pcm->private;
        snd_pcm_share_slave_t *slave = share->slave;
-       share->mmap_status.state = state;
+       share->state = state;
        gettimeofday(&share->trigger_time, 0);
        slave->prepared_count--;
        slave->running_count--;
@@ -160,8 +162,8 @@ static void snd_pcm_share_stop(snd_pcm_t *pcm, int state)
                                   pcm->setup.format.channels, pcm->setup.buffer_size,
                                   pcm->setup.format.sfmt);
        }
-       share->mmap_status.hw_ptr = slave->pcm->mmap_status->hw_ptr;
-       pcm->mmap_status = &share->mmap_status;
+       share->hw_ptr = *slave->pcm->hw_ptr;
+       pcm->hw_ptr = &share->hw_ptr;
 }
 
 /* Warning: take the mutex before to call this */
@@ -182,11 +184,11 @@ static void snd_pcm_share_slave_forward(snd_pcm_share_slave_t *slave)
        buffer_size = slave->pcm->setup.buffer_size;
        min_frames = buffer_size;
        max_frames = 0;
-       slave_appl_ptr = slave->pcm->mmap_control->appl_ptr;
+       slave_appl_ptr = *slave->pcm->appl_ptr;
        for (i = slave->clients.next; i != &slave->clients; i = i->next) {
                snd_pcm_share_t *share = list_entry(i, snd_pcm_share_t, list);
                snd_pcm_t *pcm = share->pcm;
-               switch (share->mmap_status.state) {
+               switch (share->state) {
                case SND_PCM_STATE_RUNNING:
                        break;
                case SND_PCM_STATE_DRAINING:
@@ -220,7 +222,7 @@ static void snd_pcm_share_slave_forward(snd_pcm_share_slave_t *slave)
                default:
                        continue;
                }
-               frames = share->mmap_control.appl_ptr - slave_appl_ptr;
+               frames = share->appl_ptr - slave_appl_ptr;
                if (frames > (ssize_t)buffer_size)
                        frames -= pcm->setup.boundary;
                else if (frames < -(ssize_t)pcm->setup.buffer_size)
@@ -262,7 +264,7 @@ static int snd_pcm_share_close(snd_pcm_t *pcm)
        snd_pcm_share_t *share = pcm->private;
        snd_pcm_share_slave_t *slave = share->slave;
        int err = 0;
-       if (share->mmap_status.state == SND_PCM_STATE_RUNNING) {
+       if (share->state == SND_PCM_STATE_RUNNING) {
                if (pcm->mode & SND_PCM_NONBLOCK)
                        snd_pcm_drop(pcm);
                else
@@ -276,11 +278,14 @@ static int snd_pcm_share_close(snd_pcm_t *pcm)
                pthread_kill(slave->thread, SIGTERM);
                err = snd_pcm_close(slave->pcm);
                list_del(&slave->list);
+               pthread_mutex_unlock(&slave->mutex);
                pthread_mutex_destroy(&slave->mutex);
                free(slave);
+               list_del(&share->list);
+       } else {
+               list_del(&share->list);
+               pthread_mutex_unlock(&slave->mutex);
        }
-       list_del(&share->list);
-       pthread_mutex_unlock(&slave->mutex);
        close(share->client_socket);
        close(share->slave_socket);
        free(share->slave_channels);
@@ -358,6 +363,64 @@ static int snd_pcm_share_params_info(snd_pcm_t *pcm, snd_pcm_params_info_t *info
        return err;
 }
 
+static int snd_pcm_share_mmap(snd_pcm_t *pcm)
+{
+       snd_pcm_share_t *share = pcm->private;
+       snd_pcm_share_slave_t *slave = share->slave;
+       snd_pcm_mmap_info_t *i;
+       int err;
+       pthread_mutex_lock(&slave->mutex);
+       if (slave->mmap_count == 0) {
+               err = snd_pcm_mmap(slave->pcm);
+               if (err < 0) {
+                       pthread_mutex_unlock(&slave->mutex);
+                       return err;
+               }
+               if (slave->pcm->stream == SND_PCM_STREAM_PLAYBACK)
+                       snd_pcm_areas_silence(slave->pcm->running_areas, 0, slave->pcm->setup.format.channels, slave->pcm->setup.buffer_size, slave->pcm->setup.format.sfmt);
+               slave->mmap_count++;
+       }
+       pthread_mutex_unlock(&slave->mutex);
+       pcm->mmap_info_count = slave->pcm->mmap_info_count + 1;
+       pcm->mmap_info = malloc(pcm->mmap_info_count * sizeof(*pcm->mmap_info));
+       if (!pcm->mmap_info)
+               return -ENOMEM;
+       memcpy(pcm->mmap_info, slave->pcm->mmap_info, slave->pcm->mmap_info_count * sizeof(*pcm->mmap_info));
+       i = &pcm->mmap_info[slave->pcm->mmap_info_count];
+       i->type = SND_PCM_MMAP_USER;
+       i->size = snd_pcm_frames_to_bytes(pcm, pcm->setup.buffer_size);
+       share->stopped_data = malloc(i->size);
+       if (share->stopped_data == 0) {
+               free(pcm->mmap_info);
+               pcm->mmap_info = 0;
+               return -ENOMEM;
+       }
+       i->addr = share->stopped_data;
+       return 0;
+}
+
+static int snd_pcm_share_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
+{
+       snd_pcm_share_t *share = pcm->private;
+       snd_pcm_share_slave_t *slave = share->slave;
+       int err;
+       pthread_mutex_lock(&slave->mutex);
+       slave->mmap_count--;
+       if (slave->mmap_count == 0) {
+               err = snd_pcm_munmap(slave->pcm);
+               if (err < 0) {
+                       pthread_mutex_unlock(&slave->mutex);
+                       return err;
+               }
+       }
+       pthread_mutex_unlock(&slave->mutex);
+       free(pcm->mmap_info);
+       pcm->mmap_info_count = 0;
+       pcm->mmap_info = 0;
+       free(share->stopped_data);
+       return 0;
+}
+               
 static int snd_pcm_share_params(snd_pcm_t *pcm, snd_pcm_params_t *params)
 {
        snd_pcm_share_t *share = pcm->private;
@@ -367,7 +430,7 @@ static int snd_pcm_share_params(snd_pcm_t *pcm, snd_pcm_params_t *params)
        if (channels != share->channels_count) {
                params->fail_mask = SND_PCM_PARAMS_CHANNELS;
                params->fail_reason = SND_PCM_PARAMS_FAIL_INVAL;
-               ERR("channels requested (%d) differs from configuration (%d)", channels, share->channels_count);
+               ERR("channels requested (%d) differs from configuration (%ld)", channels, (long)share->channels_count);
                return -EINVAL;
        }
        share->xfer_mode = params->xfer_mode;
@@ -387,22 +450,14 @@ static int snd_pcm_share_params(snd_pcm_t *pcm, snd_pcm_params_t *params)
                }
        } else {
                snd_pcm_params_t sp = *params;
-               if (slave->pcm->mmap_data) {
-                       err = snd_pcm_munmap_data(slave->pcm);
-                       if (err < 0)
-                               goto _end;
-               }
                sp.xfer_mode = SND_PCM_XFER_UNSPECIFIED;
                sp.xrun_mode = SND_PCM_XRUN_NONE;
                sp.format.channels = slave->channels_count;
                err = snd_pcm_params(slave->pcm, &sp);
-               snd_pcm_mmap_data(slave->pcm, NULL);
                if (err < 0)
                        goto _end;
-               if (slave->pcm->stream == SND_PCM_STREAM_PLAYBACK)
-                       snd_pcm_areas_silence(slave->pcm->running_areas, 0, slave->pcm->setup.format.channels, slave->pcm->setup.buffer_size, slave->pcm->setup.format.sfmt);
        }
-       share->mmap_status.state = SND_PCM_STATE_SETUP;
+       share->state = SND_PCM_STATE_SETUP;
        slave->setup_count++;
  _end:
        pthread_mutex_unlock(&slave->mutex);
@@ -437,13 +492,13 @@ static int snd_pcm_share_status(snd_pcm_t *pcm, snd_pcm_status_t *status)
        pthread_mutex_lock(&slave->mutex);
        if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
                status->avail = snd_pcm_mmap_playback_avail(pcm);
-               if (share->mmap_status.state != SND_PCM_STATE_RUNNING &&
-                   share->mmap_status.state != SND_PCM_STATE_DRAINING)
+               if (share->state != SND_PCM_STATE_RUNNING &&
+                   share->state != SND_PCM_STATE_DRAINING)
                        goto _notrunning;
                d = pcm->setup.buffer_size - status->avail;
        } else {
                status->avail = snd_pcm_mmap_capture_avail(pcm);
-               if (share->mmap_status.state != SND_PCM_STATE_RUNNING)
+               if (share->state != SND_PCM_STATE_RUNNING)
                        goto _notrunning;
                d = status->avail;
        }
@@ -452,7 +507,7 @@ static int snd_pcm_share_status(snd_pcm_t *pcm, snd_pcm_status_t *status)
                goto _end;
  _notrunning:
        status->delay = sd + d;
-       status->state = share->mmap_status.state;
+       status->state = share->state;
        status->trigger_time = share->trigger_time;
  _end:
        pthread_mutex_unlock(&slave->mutex);
@@ -462,7 +517,7 @@ static int snd_pcm_share_status(snd_pcm_t *pcm, snd_pcm_status_t *status)
 static int snd_pcm_share_state(snd_pcm_t *pcm)
 {
        snd_pcm_share_t *share = pcm->private;
-       return share->mmap_status.state;
+       return share->state;
 }
 
 static int snd_pcm_share_delay(snd_pcm_t *pcm, ssize_t *delayp)
@@ -472,7 +527,7 @@ static int snd_pcm_share_delay(snd_pcm_t *pcm, ssize_t *delayp)
        int err = 0;
        ssize_t sd;
        pthread_mutex_lock(&slave->mutex);
-       switch (share->mmap_status.state) {
+       switch (share->state) {
        case SND_PCM_STATE_XRUN:
                err = -EPIPE;
                goto _end;
@@ -507,7 +562,7 @@ static ssize_t snd_pcm_share_avail_update(snd_pcm_t *pcm)
                for (i = slave->clients.next; i != &slave->clients; i = i->next) {
                        snd_pcm_share_t *share = list_entry(i, snd_pcm_share_t, list);
                        snd_pcm_t *pcm = share->pcm;
-                       if (share->mmap_status.state == SND_PCM_STATE_RUNNING &&
+                       if (share->state == SND_PCM_STATE_RUNNING &&
                            pcm->setup.xrun_mode != SND_PCM_XRUN_NONE)
                                snd_pcm_share_stop(pcm, SND_PCM_STATE_XRUN);
                }
@@ -521,16 +576,16 @@ static ssize_t snd_pcm_share_avail_update(snd_pcm_t *pcm)
        return ret;
 }
 
-static ssize_t snd_pcm_share_mmap_forward(snd_pcm_t *pcm, size_t size)
+/* Call it with mutex held */
+static ssize_t _snd_pcm_share_mmap_forward(snd_pcm_t *pcm, size_t size)
 {
        snd_pcm_share_t *share = pcm->private;
        snd_pcm_share_slave_t *slave = share->slave;
        ssize_t ret = 0;
        ssize_t frames;
-       pthread_mutex_lock(&slave->mutex);
        if (pcm->stream == SND_PCM_STREAM_PLAYBACK &&
-           share->mmap_status.state == SND_PCM_STATE_RUNNING) {
-               frames = slave->pcm->mmap_control->appl_ptr - share->mmap_control.appl_ptr;
+           share->state == SND_PCM_STATE_RUNNING) {
+               frames = *slave->pcm->appl_ptr - share->appl_ptr;
                if (frames > (ssize_t)pcm->setup.buffer_size)
                        frames -= pcm->setup.boundary;
                else if (frames < -(ssize_t)pcm->setup.buffer_size)
@@ -538,19 +593,27 @@ static ssize_t snd_pcm_share_mmap_forward(snd_pcm_t *pcm, size_t size)
                if (frames > 0) {
                        /* Latecomer PCM */
                        ret = snd_pcm_rewind(slave->pcm, frames);
-                       if (ret < 0) {
-                               pthread_mutex_unlock(&slave->mutex);
+                       if (ret < 0)
                                return ret;
-                       }
                        size += ret;
                }
        }
        snd_pcm_mmap_appl_forward(pcm, size);
        snd_pcm_share_slave_forward(share->slave);
-       pthread_mutex_unlock(&slave->mutex);
        return size;
 }
 
+static ssize_t snd_pcm_share_mmap_forward(snd_pcm_t *pcm, size_t size)
+{
+       snd_pcm_share_t *share = pcm->private;
+       snd_pcm_share_slave_t *slave = share->slave;
+       ssize_t ret;
+       pthread_mutex_lock(&slave->mutex);
+       ret = _snd_pcm_share_mmap_forward(pcm, size);
+       pthread_mutex_unlock(&slave->mutex);
+       return ret;
+}
+
 static int snd_pcm_share_prepare(snd_pcm_t *pcm)
 {
        snd_pcm_share_t *share = pcm->private;
@@ -563,9 +626,9 @@ static int snd_pcm_share_prepare(snd_pcm_t *pcm)
                        goto _end;
        }
        slave->prepared_count++;
-       share->mmap_status.hw_ptr = 0;
-       share->mmap_control.appl_ptr = 0;
-       share->mmap_status.state = SND_PCM_STATE_PREPARED;
+       share->hw_ptr = 0;
+       share->appl_ptr = 0;
+       share->state = SND_PCM_STATE_PREPARED;
  _end:
        pthread_mutex_unlock(&slave->mutex);
        return err;
@@ -576,10 +639,10 @@ static int snd_pcm_share_start(snd_pcm_t *pcm)
        snd_pcm_share_t *share = pcm->private;
        snd_pcm_share_slave_t *slave = share->slave;
        int err = 0;
-       if (share->mmap_status.state != SND_PCM_STATE_PREPARED)
+       if (share->state != SND_PCM_STATE_PREPARED)
                return -EBADFD;
        pthread_mutex_lock(&slave->mutex);
-       share->mmap_status.state = SND_PCM_STATE_RUNNING;
+       share->state = SND_PCM_STATE_RUNNING;
        if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
                size_t hw_avail = snd_pcm_mmap_playback_hw_avail(pcm);
                if (hw_avail == 0) {
@@ -595,15 +658,15 @@ static int snd_pcm_share_start(snd_pcm_t *pcm)
                        if (err < 0)
                                goto _end;
                }
-               assert(share->mmap_status.hw_ptr == 0);
-               /* Use the same mmap_status of slave */
-               pcm->mmap_status = slave->pcm->mmap_status;
-               share->mmap_control.appl_ptr = slave->pcm->mmap_control->appl_ptr;
+               assert(share->hw_ptr == 0);
+               /* Share the same hw_ptr of slave */
+               pcm->hw_ptr = slave->pcm->hw_ptr;
+               share->appl_ptr = *slave->pcm->appl_ptr;
                snd_pcm_areas_copy(pcm->stopped_areas, 0,
                                   pcm->running_areas, snd_pcm_mmap_offset(pcm),
                                   pcm->setup.format.channels, hw_avail,
                                   pcm->setup.format.sfmt);
-               snd_pcm_mmap_forward(pcm, pcm->setup.buffer_size);
+               _snd_pcm_share_mmap_forward(pcm, pcm->setup.buffer_size);
        }
        if (slave->running_count == 0) {
                err = snd_pcm_start(slave->pcm);
@@ -623,7 +686,7 @@ static int snd_pcm_share_drop(snd_pcm_t *pcm)
        snd_pcm_share_slave_t *slave = share->slave;
        int err = 0;
        pthread_mutex_lock(&slave->mutex);
-       switch (share->mmap_status.state) {
+       switch (share->state) {
        case SND_PCM_STATE_OPEN:
                err = -EBADFD;
                goto _end;
@@ -631,7 +694,7 @@ static int snd_pcm_share_drop(snd_pcm_t *pcm)
                goto _end;
        case SND_PCM_STATE_DRAINING:
                if (pcm->stream == SND_PCM_STREAM_CAPTURE) {
-                       share->mmap_status.state = SND_PCM_STATE_SETUP;
+                       share->state = SND_PCM_STATE_SETUP;
                        break;
                }
                /* Fall through */
@@ -640,7 +703,7 @@ static int snd_pcm_share_drop(snd_pcm_t *pcm)
                break;
        case SND_PCM_STATE_PREPARED:
        case SND_PCM_STATE_XRUN:
-               share->mmap_status.state = SND_PCM_STATE_SETUP;
+               share->state = SND_PCM_STATE_SETUP;
                break;
        }
        
@@ -659,7 +722,7 @@ static int snd_pcm_share_drop(snd_pcm_t *pcm)
                                      pcm->setup.buffer_size, pcm->setup.format.sfmt);
                snd_pcm_mmap_forward(pcm, pcm->setup.buffer_size);
        }
-       share->mmap_control.appl_ptr = share->mmap_status.hw_ptr = 0;
+       share->appl_ptr = share->hw_ptr = 0;
  _end:
        pthread_mutex_unlock(&slave->mutex);
        return err;
@@ -671,29 +734,29 @@ static int snd_pcm_share_drain(snd_pcm_t *pcm)
        snd_pcm_share_slave_t *slave = share->slave;
        int err = 0;
        pthread_mutex_lock(&slave->mutex);
-       switch (share->mmap_status.state) {
+       switch (share->state) {
        case SND_PCM_STATE_OPEN:
                err = -EBADFD;
                goto _end;
        case SND_PCM_STATE_PREPARED:
-               share->mmap_status.state = SND_PCM_STATE_SETUP;
+               share->state = SND_PCM_STATE_SETUP;
                break;
        case SND_PCM_STATE_SETUP:
        case SND_PCM_STATE_DRAINING:
                goto _end;
        case SND_PCM_STATE_XRUN:
                if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
-                       share->mmap_status.state = SND_PCM_STATE_SETUP;
+                       share->state = SND_PCM_STATE_SETUP;
                        break;
                }
                /* Fall through */
        case SND_PCM_STATE_RUNNING:
                if (snd_pcm_mmap_avail(pcm) <= 0) {
-                       share->mmap_status.state = SND_PCM_STATE_SETUP;
+                       share->state = SND_PCM_STATE_SETUP;
                        break;
                }
                share->draining_silence = 0;
-               share->mmap_status.state = SND_PCM_STATE_DRAINING;
+               share->state = SND_PCM_STATE_DRAINING;
                break;
        }
  _end:
@@ -742,7 +805,26 @@ static int snd_pcm_share_channel_setup(snd_pcm_t *pcm, snd_pcm_channel_setup_t *
        setup->channel = c;
        err = snd_pcm_channel_setup(slave->pcm, setup);
        setup->channel = channel;
-       return err;
+       if (err < 0)
+               return err;
+       if (!pcm->mmap_info)
+               return 0;
+       switch (pcm->setup.mmap_shape) {
+       case SND_PCM_MMAP_INTERLEAVED:
+       case SND_PCM_MMAP_COMPLEX:
+               setup->stopped_area.addr = share->stopped_data;
+               setup->stopped_area.first = channel * pcm->bits_per_sample;
+               setup->stopped_area.step = pcm->bits_per_frame;
+               break;
+       case SND_PCM_MMAP_NONINTERLEAVED:
+               setup->stopped_area.addr = share->stopped_data + c * pcm->setup.buffer_size * pcm->bits_per_sample / 8;
+               setup->stopped_area.first = 0;
+               setup->stopped_area.step = pcm->bits_per_sample;
+               break;
+       default:
+               assert(0);
+       }
+       return 0;
 }
 
 static ssize_t snd_pcm_share_rewind(snd_pcm_t *pcm, size_t frames)
@@ -751,7 +833,7 @@ static ssize_t snd_pcm_share_rewind(snd_pcm_t *pcm, size_t frames)
        snd_pcm_share_slave_t *slave = share->slave;
        int ret = -EBADFD;
        ssize_t n;
-       switch (share->mmap_status.state) {
+       switch (share->state) {
        case SND_PCM_STATE_RUNNING:
                break;
        case SND_PCM_STATE_PREPARED:
@@ -774,7 +856,7 @@ static ssize_t snd_pcm_share_rewind(snd_pcm_t *pcm, size_t frames)
                        n = frames;
                frames -= n;
        }
-       if (share->mmap_status.state == SND_PCM_STATE_RUNNING &&
+       if (share->state == SND_PCM_STATE_RUNNING &&
            frames > 0) {
                pthread_mutex_lock(&slave->mutex);
                ret = snd_pcm_rewind(slave->pcm, frames);
@@ -793,43 +875,6 @@ static ssize_t snd_pcm_share_rewind(snd_pcm_t *pcm, size_t frames)
        return ret;
 }
 
-static int snd_pcm_share_mmap_status(snd_pcm_t *pcm)
-{
-       snd_pcm_share_t *share = pcm->private;
-       pcm->mmap_status = &share->mmap_status;
-       return 0;
-}
-
-static int snd_pcm_share_mmap_control(snd_pcm_t *pcm)
-{
-       snd_pcm_share_t *share = pcm->private;
-       pcm->mmap_control = &share->mmap_control;
-       return 0;
-}
-
-static int snd_pcm_share_mmap_data(snd_pcm_t *pcm)
-{
-       snd_pcm_share_t *share = pcm->private;
-       snd_pcm_share_slave_t *slave = share->slave;
-       pcm->mmap_data = slave->pcm->mmap_data;
-       return 0;
-}
-
-static int snd_pcm_share_munmap_status(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
-{
-       return 0;
-}
-               
-static int snd_pcm_share_munmap_control(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
-{
-       return 0;
-}
-               
-static int snd_pcm_share_munmap_data(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
-{
-       return 0;
-}
-               
 static int snd_pcm_share_channels_mask(snd_pcm_t *pcm, bitset_t *cmask)
 {
        snd_pcm_share_t *share = pcm->private;
@@ -869,7 +914,7 @@ static void snd_pcm_share_dump(snd_pcm_t *pcm, FILE *fp)
        snd_pcm_dump(slave->pcm, fp);
 }
 
-struct snd_pcm_ops snd_pcm_share_ops = {
+snd_pcm_ops_t snd_pcm_share_ops = {
        close: snd_pcm_share_close,
        info: snd_pcm_share_info,
        params_info: snd_pcm_share_params_info,
@@ -881,15 +926,11 @@ struct snd_pcm_ops snd_pcm_share_ops = {
        dump: snd_pcm_share_dump,
        nonblock: snd_pcm_share_nonblock,
        async: snd_pcm_share_async,
-       mmap_status: snd_pcm_share_mmap_status,
-       mmap_control: snd_pcm_share_mmap_control,
-       mmap_data: snd_pcm_share_mmap_data,
-       munmap_status: snd_pcm_share_munmap_status,
-       munmap_control: snd_pcm_share_munmap_control,
-       munmap_data: snd_pcm_share_munmap_data,
+       mmap: snd_pcm_share_mmap,
+       munmap: snd_pcm_share_munmap,
 };
 
-struct snd_pcm_fast_ops snd_pcm_share_fast_ops = {
+snd_pcm_fast_ops_t snd_pcm_share_fast_ops = {
        status: snd_pcm_share_status,
        state: snd_pcm_share_state,
        delay: snd_pcm_share_delay,
@@ -903,18 +944,17 @@ struct snd_pcm_fast_ops snd_pcm_share_fast_ops = {
        readi: snd_pcm_mmap_readi,
        readn: snd_pcm_mmap_readn,
        rewind: snd_pcm_share_rewind,
-       poll_descriptor: snd_pcm_share_poll_descriptor,
        channels_mask: snd_pcm_share_channels_mask,
        avail_update: snd_pcm_share_avail_update,
        mmap_forward: snd_pcm_share_mmap_forward,
 };
 
-int snd_pcm_share_open(snd_pcm_t **handlep, char *name, char *sname,
+int snd_pcm_share_open(snd_pcm_t **pcmp, char *name, char *sname,
                       size_t schannels_count,
                       size_t channels_count, int *channels_map,
                       int stream, int mode)
 {
-       snd_pcm_t *handle;
+       snd_pcm_t *pcm;
        snd_pcm_share_t *share;
        int err;
        struct list_head *i;
@@ -923,7 +963,7 @@ int snd_pcm_share_open(snd_pcm_t **handlep, char *name, char *sname,
        snd_pcm_share_slave_t *slave = NULL;
        int sd[2];
 
-       assert(handlep);
+       assert(pcmp);
        assert(channels_count > 0 && sname && channels_map);
 
        for (k = 0; k < channels_count; ++k) {
@@ -951,8 +991,8 @@ int snd_pcm_share_open(snd_pcm_t **handlep, char *name, char *sname,
        }
        memcpy(share->slave_channels, channels_map, channels_count * sizeof(*share->slave_channels));
 
-       handle = calloc(1, sizeof(snd_pcm_t));
-       if (!handle) {
+       pcm = calloc(1, sizeof(snd_pcm_t));
+       if (!pcm) {
                free(share->slave_channels);
                free(share);
                return -ENOMEM;
@@ -976,7 +1016,7 @@ int snd_pcm_share_open(snd_pcm_t **handlep, char *name, char *sname,
        }
        if (err < 0) {
                err = -errno;
-               free(handle);
+               free(pcm);
                free(share->slave_channels);
                free(share);
                return err;
@@ -997,7 +1037,7 @@ int snd_pcm_share_open(snd_pcm_t **handlep, char *name, char *sname,
                        pthread_mutex_unlock(&slaves_mutex);
                        close(sd[0]);
                        close(sd[1]);
-                       free(handle);
+                       free(pcm);
                        free(share->slave_channels);
                        free(share);
                        return err;
@@ -1008,7 +1048,7 @@ int snd_pcm_share_open(snd_pcm_t **handlep, char *name, char *sname,
                        snd_pcm_close(spcm);
                        close(sd[0]);
                        close(sd[1]);
-                       free(handle);
+                       free(pcm);
                        free(share->slave_channels);
                        free(share);
                        return err;
@@ -1031,28 +1071,27 @@ int snd_pcm_share_open(snd_pcm_t **handlep, char *name, char *sname,
        pthread_mutex_unlock(&slave->mutex);
 
        share->slave = slave;
-       share->pcm = handle;
+       share->pcm = pcm;
        share->client_socket = sd[0];
        share->slave_socket = sd[1];
        share->async_sig = SIGIO;
        share->async_pid = getpid();
        
        if (name)
-               handle->name = strdup(name);
-       handle->type = SND_PCM_TYPE_SHARE;
-       handle->stream = stream;
-       handle->mode = mode;
-       handle->ops = &snd_pcm_share_ops;
-       handle->op_arg = handle;
-       handle->fast_ops = &snd_pcm_share_fast_ops;
-       handle->fast_op_arg = handle;
-       handle->private = share;
-       err = snd_pcm_init(handle);
-       if (err < 0) {
-               snd_pcm_close(handle);
-               return err;
-       }
-       *handlep = handle;
+               pcm->name = strdup(name);
+       pcm->type = SND_PCM_TYPE_SHARE;
+       pcm->stream = stream;
+       pcm->mode = mode;
+       pcm->mmap_auto = 1;
+       pcm->ops = &snd_pcm_share_ops;
+       pcm->op_arg = pcm;
+       pcm->fast_ops = &snd_pcm_share_fast_ops;
+       pcm->fast_op_arg = pcm;
+       pcm->private = share;
+       pcm->poll_fd = share->client_socket;
+       pcm->hw_ptr = &share->hw_ptr;
+       pcm->appl_ptr = &share->appl_ptr;
+       *pcmp = pcm;
        return 0;
 }
 
@@ -1104,11 +1143,11 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, char *name, snd_config_t *conf,
                return -EINVAL;
        }
        if (!sname) {
-               ERR("Missing sname");
+               ERR("sname is not defined");
                return -EINVAL;
        }
        if (!binding) {
-               ERR("Missing binding");
+               ERR("binding is not defined");
                return -EINVAL;
        }
        snd_config_foreach(i, binding) {