OSDN Git Service

New async notification API. Removed obsolete surround. Cleaning
authorAbramo Bagnara <abramo@alsa-project.org>
Wed, 20 Jun 2001 20:52:12 +0000 (20:52 +0000)
committerAbramo Bagnara <abramo@alsa-project.org>
Wed, 20 Jun 2001 20:52:12 +0000 (20:52 +0000)
35 files changed:
aserver/aserver.c
include/control.h
include/global.h
include/local.h
include/pcm.h
src/Makefile.am
src/async.c [new file with mode: 0644]
src/conf.c
src/control/control.c
src/control/control_hw.c
src/control/control_local.h
src/control/control_shm.c
src/control/setup.c
src/mixer/mixer_local.h
src/pcm/Makefile.am
src/pcm/pcm.c
src/pcm/pcm_adpcm.c
src/pcm/pcm_alaw.c
src/pcm/pcm_copy.c
src/pcm/pcm_file.c
src/pcm/pcm_hooks.c
src/pcm/pcm_hw.c
src/pcm/pcm_linear.c
src/pcm/pcm_local.h
src/pcm/pcm_meter.c
src/pcm/pcm_mulaw.c
src/pcm/pcm_multi.c
src/pcm/pcm_null.c
src/pcm/pcm_plug.c
src/pcm/pcm_rate.c
src/pcm/pcm_route.c
src/pcm/pcm_share.c
src/pcm/pcm_shm.c
src/pcm/pcm_surr.c [deleted file]
src/pcm/surround.conf [deleted file]

index 68fdf5d..9ba0eea 100644 (file)
@@ -31,9 +31,9 @@
 #include <netinet/in.h>
 #include <netdb.h>
 #include <limits.h>
+#include <signal.h>
 
 #include "aserver.h"
-#include "list.h"
 
 char *command;
 
@@ -199,6 +199,9 @@ struct client {
        int stream;
        int mode;
        transport_ops_t *ops;
+       snd_async_handler_t *async_handler;
+       int async_sig;
+       pid_t async_pid;
        union {
                struct {
                        snd_pcm_t *handle;
@@ -207,7 +210,7 @@ struct client {
                struct {
                        snd_ctl_t *handle;
                        int fd;
-               } control;
+               } ctl;
 #if 0
                struct {
                        snd_rawmidi_t *handle;
@@ -358,6 +361,13 @@ static int shm_ack_fd(client_t *client, int fd)
        return 0;
 }
 
+static void async_handler(snd_async_handler_t *handler)
+{
+       client_t *client = snd_async_handler_get_callback_private(handler);
+       /* FIXME: use sigqueue */
+       kill(client->async_pid, client->async_sig);
+}
+
 static int pcm_shm_cmd(client_t *client)
 {
        volatile snd_pcm_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
@@ -374,6 +384,19 @@ static int pcm_shm_cmd(client_t *client)
        switch (cmd) {
        case SND_PCM_IOCTL_ASYNC:
                ctrl->result = snd_pcm_async(pcm, ctrl->u.async.sig, ctrl->u.async.pid);
+               if (ctrl->result < 0)
+                       break;
+               if (ctrl->u.async.sig >= 0) {
+                       assert(client->async_sig < 0);
+                       ctrl->result = snd_async_add_pcm_handler(&client->async_handler, pcm, async_handler, client);
+                       if (ctrl->result < 0)
+                               break;
+               } else {
+                       assert(client->async_sig >= 0);
+                       snd_async_del_handler(client->async_handler);
+               }
+               client->async_sig = ctrl->u.async.sig;
+               client->async_pid = ctrl->u.async.pid;
                break;
        case SNDRV_PCM_IOCTL_INFO:
                ctrl->result = snd_pcm_info(pcm, (snd_pcm_info_t *) &ctrl->u.info);
@@ -506,8 +529,8 @@ static int ctl_shm_open(client_t *client, int *cookie)
        err = snd_ctl_open(&ctl, client->name, SND_CTL_NONBLOCK);
        if (err < 0)
                return err;
-       client->device.control.handle = ctl;
-       client->device.control.fd = _snd_ctl_poll_descriptor(ctl);
+       client->device.ctl.handle = ctl;
+       client->device.ctl.fd = _snd_ctl_poll_descriptor(ctl);
 
        shmid = shmget(IPC_PRIVATE, CTL_SHM_SIZE, 0666);
        if (shmid < 0) {
@@ -524,7 +547,7 @@ static int ctl_shm_open(client_t *client, int *cookie)
                goto _err;
        }
        *cookie = shmid;
-       add_waiter(client->device.control.fd, POLLIN, ctl_handler, client);
+       add_waiter(client->device.ctl.fd, POLLIN, ctl_handler, client);
        client->polling = 1;
        return 0;
 
@@ -539,10 +562,10 @@ static int ctl_shm_close(client_t *client)
        int err;
        snd_ctl_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
        if (client->polling) {
-               del_waiter(client->device.control.fd);
+               del_waiter(client->device.ctl.fd);
                client->polling = 0;
        }
-       err = snd_ctl_close(client->device.control.handle);
+       err = snd_ctl_close(client->device.ctl.handle);
        ctrl->result = err;
        if (err < 0) 
                ERROR("snd_ctl_close");
@@ -571,10 +594,24 @@ static int ctl_shm_cmd(client_t *client)
                return -EBADFD;
        cmd = ctrl->cmd;
        ctrl->cmd = 0;
-       ctl = client->device.control.handle;
+       ctl = client->device.ctl.handle;
        switch (cmd) {
        case SND_CTL_IOCTL_ASYNC:
                ctrl->result = snd_ctl_async(ctl, ctrl->u.async.sig, ctrl->u.async.pid);
+               if (ctrl->result < 0)
+                       break;
+               if (ctrl->u.async.sig >= 0) {
+                       assert(client->async_sig < 0);
+                       ctrl->result = snd_async_add_ctl_handler(&client->async_handler, ctl, async_handler, client);
+                       if (ctrl->result < 0)
+                               break;
+               } else {
+                       assert(client->async_sig >= 0);
+                       snd_async_del_handler(client->async_handler);
+               }
+               client->async_sig = ctrl->u.async.sig;
+               client->async_pid = ctrl->u.async.pid;
+               break;
                break;
        case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
                ctrl->result = snd_ctl_subscribe_events(ctl, ctrl->u.subscribe_events);
index 8967f13..94bc13c 100644 (file)
@@ -274,7 +274,9 @@ int snd_sctl_remove(snd_sctl_t *handle);
 int snd_ctl_open(snd_ctl_t **ctl, const char *name, int mode);
 int snd_ctl_close(snd_ctl_t *ctl);
 int snd_ctl_nonblock(snd_ctl_t *ctl, int nonblock);
-int snd_ctl_async(snd_ctl_t *ctl, int sig, pid_t pid);
+int snd_async_add_ctl_handler(snd_async_handler_t **handler, snd_ctl_t *ctl, 
+                             snd_async_callback_t callback, void *private_data);
+snd_ctl_t *snd_async_handler_get_ctl(snd_async_handler_t *handler);
 int snd_ctl_poll_descriptors_count(snd_ctl_t *ctl);
 int snd_ctl_poll_descriptors(snd_ctl_t *ctl, struct pollfd *pfds, unsigned int space);
 int snd_ctl_subscribe_events(snd_ctl_t *ctl, int subscribe);
@@ -515,7 +517,6 @@ typedef int (*snd_hctl_elem_callback_t)(snd_hctl_elem_t *elem,
 int snd_hctl_open(snd_hctl_t **hctl, const char *name, int mode);
 int snd_hctl_close(snd_hctl_t *hctl);
 int snd_hctl_nonblock(snd_hctl_t *hctl, int nonblock);
-int snd_hctl_async(snd_hctl_t *hctl, int sig, pid_t pid);
 int snd_hctl_poll_descriptors_count(snd_hctl_t *hctl);
 int snd_hctl_poll_descriptors(snd_hctl_t *hctl, struct pollfd *pfds, unsigned int space);
 unsigned int snd_hctl_get_count(snd_hctl_t *hctl);
index 6742a7b..9db9aff 100644 (file)
 
 /** \} */
 
+/** Async notification client handler */
+typedef struct _snd_async_handler snd_async_handler_t;
+
+/** Async notification callback */
+typedef void (*snd_async_callback_t)(snd_async_handler_t *handler);
+
+int snd_async_add_handler(snd_async_handler_t **handler, int fd, 
+                         snd_async_callback_t callback, void *private_data);
+int snd_async_del_handler(snd_async_handler_t *handler);
+int snd_async_handler_get_fd(snd_async_handler_t *handler);
+void *snd_async_handler_get_callback_private(snd_async_handler_t *handler);
index 03d30a7..e15018a 100644 (file)
 #define _snd_hwdep_info sndrv_hwdep_info
 
 #include "asoundlib.h"
+#include "list.h"
+
+struct _snd_async_handler {
+       enum {
+               SND_ASYNC_HANDLER_GENERIC,
+               SND_ASYNC_HANDLER_PCM,
+               SND_ASYNC_HANDLER_CTL,
+       } type;
+       int fd;
+       union {
+               snd_pcm_t *pcm;
+               snd_ctl_t *ctl;
+       } u;
+       snd_async_callback_t callback;
+       void *private_data;
+       struct list_head glist;
+       struct list_head hlist;
+};
 
 typedef enum _snd_set_mode {
        SND_CHANGE,
index 6994b1a..6d670fa 100644 (file)
@@ -305,7 +305,9 @@ int snd_pcm_close(snd_pcm_t *pcm);
 int snd_pcm_poll_descriptors_count(snd_pcm_t *pcm);
 int snd_pcm_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space);
 int snd_pcm_nonblock(snd_pcm_t *pcm, int nonblock);
-int snd_pcm_async(snd_pcm_t *pcm, int sig, pid_t pid);
+int snd_async_add_pcm_handler(snd_async_handler_t **handler, snd_pcm_t *pcm, 
+                             snd_async_callback_t callback, void *private_data);
+snd_pcm_t *snd_async_handler_get_pcm(snd_async_handler_t *handler);
 int snd_pcm_info(snd_pcm_t *pcm, snd_pcm_info_t *info);
 int snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
 int snd_pcm_hw_free(snd_pcm_t *pcm);
index f52db05..a2f6614 100644 (file)
@@ -2,7 +2,7 @@ SUBDIRS=control mixer pcm rawmidi timer hwdep seq instr compat cards
 COMPATNUM=@LIBTOOL_VERSION_INFO@
 
 lib_LTLIBRARIES = libasound.la
-libasound_la_SOURCES = conf.c confmisc.c input.c output.c error.c 
+libasound_la_SOURCES = conf.c confmisc.c input.c output.c async.c error.c 
 libasound_la_LIBADD = control/libcontrol.la mixer/libmixer.la pcm/libpcm.la \
                       rawmidi/librawmidi.la timer/libtimer.la \
                      hwdep/libhwdep.la seq/libseq.la instr/libinstr.la \
diff --git a/src/async.c b/src/async.c
new file mode 100644 (file)
index 0000000..180866b
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ *  Async notification helpers
+ *  Copyright (c) 2001 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 "pcm/pcm_local.h"
+#include "control/control_local.h"
+#include <signal.h>
+
+static struct list_head snd_async_handlers;
+
+static void snd_async_handler(int signo ATTRIBUTE_UNUSED, siginfo_t *siginfo, void *context ATTRIBUTE_UNUSED)
+{
+       int fd;
+       struct list_head *i;
+       assert(siginfo->si_code = SI_SIGIO);
+       fd = siginfo->si_fd;
+       list_for_each(i, &snd_async_handlers) {
+               snd_async_handler_t *h = list_entry(i, snd_async_handler_t, glist);
+               if (h->fd == fd) {
+                       h->callback(h);
+                       // break;
+               }
+       }
+}
+
+int snd_async_add_handler(snd_async_handler_t **handler, int fd, 
+                         snd_async_callback_t callback, void *private_data)
+{
+       snd_async_handler_t *h;
+       int was_empty;
+       h = malloc(sizeof(*h));
+       if (!h)
+               return -ENOMEM;
+       h->fd = fd;
+       h->callback = callback;
+       h->private_data = private_data;
+       was_empty = list_empty(&snd_async_handlers);
+       list_add_tail(&h->glist, &snd_async_handlers);
+       *handler = h;
+       if (was_empty) {
+               int err;
+               struct sigaction act;
+               act.sa_flags = SA_RESTART | SA_SIGINFO;
+               act.sa_sigaction = snd_async_handler;
+               sigemptyset(&act.sa_mask);
+               err = sigaction(SIGIO, &act, NULL);
+               if (err < 0) {
+                       SYSERR("sigaction");
+                       return -errno;
+               }
+       }
+       return 0;
+}
+
+int snd_async_del_handler(snd_async_handler_t *handler)
+{
+       int err = 0;
+       list_del(&handler->glist);
+       if (list_empty(&snd_async_handlers)) {
+               struct sigaction act;
+               act.sa_flags = 0;
+               act.sa_handler = SIG_DFL;
+               err = sigaction(SIGIO, &act, NULL);
+               if (err < 0) {
+                       SYSERR("sigaction");
+                       return -errno;
+               }
+       }
+       if (handler->type == SND_ASYNC_HANDLER_GENERIC)
+               goto _end;
+       list_del(&handler->hlist);
+       if (!list_empty(&handler->hlist))
+               goto _end;
+       switch (handler->type) {
+       case SND_ASYNC_HANDLER_PCM:
+               err = snd_pcm_async(handler->u.pcm, -1, 1);
+               break;
+       case SND_ASYNC_HANDLER_CTL:
+               err = snd_ctl_async(handler->u.ctl, -1, 1);
+               break;
+       default:
+               assert(0);
+       }
+ _end:
+       free(handler);
+       return err;
+}
+
+int snd_async_handler_get_fd(snd_async_handler_t *handler)
+{
+       return handler->fd;
+}
+
+void *snd_async_handler_get_callback_private(snd_async_handler_t *handler)
+{
+       return handler->private_data;
+}
+
index f68135e..459bd4a 100644 (file)
@@ -25,7 +25,6 @@
 #include <sys/stat.h>
 #include <dlfcn.h>
 #include "local.h"
-#include "list.h"
 
 #ifndef DOC_HIDDEN
 
index 6c5eb7c..8a2f8ec 100644 (file)
@@ -74,12 +74,16 @@ snd_ctl_type_t snd_ctl_type(snd_ctl_t *ctl)
  */
 int snd_ctl_close(snd_ctl_t *ctl)
 {
-       int res;
-       res = ctl->ops->close(ctl);
+       int err;
+       while (!list_empty(&ctl->async_handlers)) {
+               snd_async_handler_t *h = list_entry(&ctl->async_handlers.next, snd_async_handler_t, hlist);
+               snd_async_del_handler(h);
+       }
+       err = ctl->ops->close(ctl);
        if (ctl->name)
                free(ctl->name);
        free(ctl);
-       return res;
+       return err;
 }
 
 /**
@@ -99,6 +103,22 @@ int snd_ctl_nonblock(snd_ctl_t *ctl, int nonblock)
        return 0;
 }
 
+#ifndef DOC_HIDDEN
+int snd_ctl_new(snd_ctl_t **ctlp, snd_ctl_type_t type, const char *name)
+{
+       snd_ctl_t *ctl;
+       ctl = calloc(1, sizeof(*ctl));
+       if (!ctl)
+               return -ENOMEM;
+       ctl->type = type;
+       if (name)
+               ctl->name = strdup(name);
+       INIT_LIST_HEAD(&ctl->async_handlers);
+       *ctlp = ctl;
+       return 0;
+}
+       
+
 /**
  * \brief set async mode
  * \param ctl CTL handle
@@ -110,21 +130,10 @@ int snd_ctl_nonblock(snd_ctl_t *ctl, int nonblock)
  */
 int snd_ctl_async(snd_ctl_t *ctl, int sig, pid_t pid)
 {
-       int err;
        assert(ctl);
-       err = ctl->ops->async(ctl, sig, pid);
-       if (err < 0)
-               return err;
-       if (sig)
-               ctl->async_sig = sig;
-       else
-               ctl->async_sig = SIGIO;
-       if (pid)
-               ctl->async_pid = pid;
-       else
-               ctl->async_pid = getpid();
-       return 0;
+       return ctl->ops->async(ctl, sig, pid);
 }
+#endif
 
 /**
  * \brief get count of poll descriptors for CTL handle
@@ -148,7 +157,7 @@ int snd_ctl_poll_descriptors(snd_ctl_t *ctl, struct pollfd *pfds, unsigned int s
 {
        assert(ctl);
        if (space > 0) {
-               pfds->fd = ctl->ops->poll_descriptor(ctl);
+               pfds->fd = ctl->poll_fd;
                pfds->events = POLLIN;
                return 1;
        }
@@ -380,6 +389,50 @@ int snd_ctl_wait(snd_ctl_t *ctl, int timeout)
        return 0;
 }
 
+/**
+ * \brief Add an async handler for a CTL
+ * \param handler Returned handler handle
+ * \param ctl CTL handle
+ * \param callback Callback function
+ * \param private_data Callback private data
+ * \return 0 otherwise a negative error code on failure
+ */
+int snd_async_add_ctl_handler(snd_async_handler_t **handler, snd_ctl_t *ctl, 
+                             snd_async_callback_t callback, void *private_data)
+{
+       int err;
+       int was_empty;
+       snd_async_handler_t *h;
+       err = snd_async_add_handler(&h, _snd_ctl_async_descriptor(ctl),
+                                   callback, private_data);
+       if (err < 0)
+               return err;
+       h->type = SND_ASYNC_HANDLER_CTL;
+       h->u.ctl = ctl;
+       was_empty = list_empty(&ctl->async_handlers);
+       list_add_tail(&h->hlist, &ctl->async_handlers);
+       if (was_empty) {
+               err = snd_ctl_async(ctl, getpid(), SIGIO);
+               if (err < 0) {
+                       snd_async_del_handler(h);
+                       return err;
+               }
+       }
+       *handler = h;
+       return 0;
+}
+
+/**
+ * \brief Return CTL handle related to an async handler
+ * \param handler Async handler handle
+ * \return CTL handle
+ */
+snd_ctl_t *snd_async_handler_get_ctl(snd_async_handler_t *handler)
+{
+       assert(handler->type = SND_ASYNC_HANDLER_CTL);
+       return handler->u.ctl;
+}
+
 int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name,
                      snd_config_t *ctl_root, snd_config_t *ctl_conf, int mode)
 {
@@ -701,7 +754,7 @@ unsigned int snd_ctl_event_elem_get_index(const snd_ctl_event_t *obj)
 int _snd_ctl_poll_descriptor(snd_ctl_t *ctl)
 {
        assert(ctl);
-       return ctl->ops->poll_descriptor(ctl);
+       return ctl->poll_fd;
 }
 #endif
 
index b287e35..694517f 100644 (file)
@@ -105,12 +105,6 @@ static int snd_ctl_hw_async(snd_ctl_t *ctl, int sig, pid_t pid)
        return 0;
 }
 
-static int snd_ctl_hw_poll_descriptor(snd_ctl_t *handle)
-{
-       snd_ctl_hw_t *hw = handle->private_data;
-       return hw->fd;
-}
-
 static int snd_ctl_hw_subscribe_events(snd_ctl_t *handle, int subscribe)
 {
        snd_ctl_hw_t *hw = handle->private_data;
@@ -257,7 +251,6 @@ snd_ctl_ops_t snd_ctl_hw_ops = {
        close: snd_ctl_hw_close,
        nonblock: snd_ctl_hw_nonblock,
        async: snd_ctl_hw_async,
-       poll_descriptor: snd_ctl_hw_poll_descriptor,
        subscribe_events: snd_ctl_hw_subscribe_events,
        card_info: snd_ctl_hw_card_info,
        element_list: snd_ctl_hw_elem_list,
@@ -284,6 +277,7 @@ int snd_ctl_hw_open(snd_ctl_t **handle, const char *name, int card, int mode)
        int fmode;
        snd_ctl_t *ctl;
        snd_ctl_hw_t *hw;
+       int err;
 
        *handle = NULL; 
 
@@ -308,24 +302,22 @@ int snd_ctl_hw_open(snd_ctl_t **handle, const char *name, int card, int mode)
                close(fd);
                return -SND_ERROR_INCOMPATIBLE_VERSION;
        }
-       ctl = calloc(1, sizeof(snd_ctl_t));
-       if (ctl == NULL) {
-               close(fd);
-               return -ENOMEM;
-       }
        hw = calloc(1, sizeof(snd_ctl_hw_t));
        if (hw == NULL) {
                close(fd);
-               free(ctl);
                return -ENOMEM;
        }
        hw->card = card;
        hw->fd = fd;
-       if (name)
-               ctl->name = strdup(name);
-       ctl->type = SND_CTL_TYPE_HW;
+
+       err = snd_ctl_new(&ctl, SND_CTL_TYPE_HW, name);
+       if (err < 0) {
+               close(fd);
+               free(hw);
+       }
        ctl->ops = &snd_ctl_hw_ops;
        ctl->private_data = hw;
+       ctl->poll_fd = fd;
        *handle = ctl;
        return 0;
 }
index 01b8013..b3522cf 100644 (file)
  */
 
 #include "local.h"
-#include "list.h"
 
 typedef struct _snd_ctl_ops {
        int (*close)(snd_ctl_t *handle);
        int (*nonblock)(snd_ctl_t *handle, int nonblock);
        int (*async)(snd_ctl_t *handle, int sig, pid_t pid);
-       int (*poll_descriptor)(snd_ctl_t *handle);
        int (*subscribe_events)(snd_ctl_t *handle, int subscribe);
        int (*card_info)(snd_ctl_t *handle, snd_ctl_card_info_t *info);
        int (*element_list)(snd_ctl_t *handle, snd_ctl_elem_list_t *list);
@@ -53,8 +51,8 @@ struct _snd_ctl {
        snd_ctl_ops_t *ops;
        void *private_data;
        int nonblock;
-       int async_sig;
-       pid_t async_pid;
+       int poll_fd;
+       struct list_head async_handlers;
 };
 
 struct _snd_hctl_elem {
@@ -80,6 +78,9 @@ struct _snd_hctl {
 };
 
 
+int snd_ctl_new(snd_ctl_t **ctlp, snd_ctl_type_t type, const char *name);
 int _snd_ctl_poll_descriptor(snd_ctl_t *ctl);
+#define _snd_ctl_async_descriptor _snd_ctl_poll_descriptor
 int snd_ctl_hw_open(snd_ctl_t **handle, const char *name, int card, int mode);
 int snd_ctl_shm_open(snd_ctl_t **handlep, const char *name, const char *sockname, const char *sname, int mode);
+int snd_ctl_async(snd_ctl_t *ctl, int sig, pid_t pid);
index 34262da..f04834f 100644 (file)
@@ -124,7 +124,7 @@ static int snd_ctl_shm_subscribe_events(snd_ctl_t *ctl, int subscribe)
 {
        snd_ctl_shm_t *shm = ctl->private_data;
        volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
-       ctrl->cmd = SND_CTL_IOCTL_POLL_DESCRIPTOR;
+       ctrl->cmd = SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS;
        ctrl->u.subscribe_events = subscribe;
        return snd_ctl_shm_action(ctl);
 }
@@ -368,7 +368,6 @@ snd_ctl_ops_t snd_ctl_shm_ops = {
        close: snd_ctl_shm_close,
        nonblock: snd_ctl_shm_nonblock,
        async: snd_ctl_shm_async,
-       poll_descriptor: snd_ctl_shm_poll_descriptor,
        subscribe_events: snd_ctl_shm_subscribe_events,
        card_info: snd_ctl_shm_card_info,
        element_list: snd_ctl_shm_elem_list,
@@ -492,14 +491,8 @@ int snd_ctl_shm_open(snd_ctl_t **handlep, const char *name, const char *sockname
                goto _err;
        }
                
-       ctl = calloc(1, sizeof(snd_ctl_t));
-       if (!ctl) {
-               result = -ENOMEM;
-               goto _err;
-       }
        shm = calloc(1, sizeof(snd_ctl_shm_t));
        if (!shm) {
-               free(ctl);
                result = -ENOMEM;
                goto _err;
        }
@@ -507,11 +500,19 @@ int snd_ctl_shm_open(snd_ctl_t **handlep, const char *name, const char *sockname
        shm->socket = sock;
        shm->ctrl = ctrl;
 
-       if (name)
-               ctl->name = strdup(name);
-       ctl->type = SND_CTL_TYPE_SHM;
+       err = snd_ctl_new(&ctl, SND_CTL_TYPE_SHM, name);
+       if (err < 0) {
+               result = err;
+               goto _err;
+       }
        ctl->ops = &snd_ctl_shm_ops;
        ctl->private_data = shm;
+       err = snd_ctl_shm_poll_descriptor(ctl);
+       if (err < 0) {
+               snd_ctl_close(ctl);
+               return err;
+       }
+       ctl->poll_fd = err;
        *handlep = ctl;
        return 0;
 
index fac0828..a2154ae 100644 (file)
@@ -34,7 +34,6 @@
 #include <unistd.h>
 #include <string.h>
 #include <ctype.h>
-#include "list.h"
 #include "local.h"
 
 typedef struct {
index 266b11f..813f396 100644 (file)
@@ -20,7 +20,6 @@
  *
  */
 
-#include "list.h"
 #include "local.h"
 
 typedef struct _bag1 {
index 4944d5d..90391d8 100644 (file)
@@ -11,8 +11,6 @@ libpcm_la_SOURCES = atomic.c mask.c interval.c \
 noinst_HEADERS = atomic.h pcm_local.h pcm_plugin.h mask.h mask_inline.h \
                 interval.h interval_inline.h plugin_ops.h
 
-EXTRA_DIST = surround.conf
-
 alsadir = $(datadir)/alsa
 alsa_DATA = surround.conf
 
index 93a7101..d5a8836 100644 (file)
@@ -44,7 +44,6 @@
 #include <limits.h>
 #include <dlfcn.h>
 #include "pcm_local.h"
-#include "list.h"
 
 /**
  * \brief get identifier of PCM handle
@@ -108,6 +107,10 @@ int snd_pcm_close(snd_pcm_t *pcm)
                if (err < 0)
                        return err;
        }
+       while (!list_empty(&pcm->async_handlers)) {
+               snd_async_handler_t *h = list_entry(&pcm->async_handlers.next, snd_async_handler_t, hlist);
+               snd_async_del_handler(h);
+       }
        err = pcm->ops->close(pcm->op_arg);
        if (err < 0)
                return err;
@@ -136,6 +139,7 @@ int snd_pcm_nonblock(snd_pcm_t *pcm, int nonblock)
        return 0;
 }
 
+#ifndef DOC_HIDDEN
 /**
  * \brief set async mode
  * \param pcm PCM handle
@@ -147,21 +151,14 @@ int snd_pcm_nonblock(snd_pcm_t *pcm, int nonblock)
  */
 int snd_pcm_async(snd_pcm_t *pcm, int sig, pid_t pid)
 {
-       int err;
        assert(pcm);
-       err = pcm->ops->async(pcm->op_arg, sig, pid);
-       if (err < 0)
-               return err;
-       if (sig)
-               pcm->async_sig = sig;
-       else
-               pcm->async_sig = SIGIO;
-       if (pid)
-               pcm->async_pid = pid;
-       else
-               pcm->async_pid = getpid();
-       return 0;
+       if (sig == 0)
+               sig = SIGIO;
+       if (pid == 0)
+               pid = getpid();
+       return pcm->ops->async(pcm->op_arg, sig, pid);
 }
+#endif
 
 /**
  * \brief Obtain general (static) information for PCM handle
@@ -911,6 +908,50 @@ ssize_t snd_pcm_samples_to_bytes(snd_pcm_t *pcm, int samples)
        return samples * pcm->sample_bits / 8;
 }
 
+/**
+ * \brief Add an async handler for a PCM
+ * \param handler Returned handler handle
+ * \param pcm PCM handle
+ * \param callback Callback function
+ * \param private_data Callback private data
+ * \return 0 otherwise a negative error code on failure
+ */
+int snd_async_add_pcm_handler(snd_async_handler_t **handler, snd_pcm_t *pcm, 
+                             snd_async_callback_t callback, void *private_data)
+{
+       int err;
+       int was_empty;
+       snd_async_handler_t *h;
+       err = snd_async_add_handler(&h, _snd_pcm_async_descriptor(pcm),
+                                   callback, private_data);
+       if (err < 0)
+               return err;
+       h->type = SND_ASYNC_HANDLER_PCM;
+       h->u.pcm = pcm;
+       was_empty = list_empty(&pcm->async_handlers);
+       list_add_tail(&h->hlist, &pcm->async_handlers);
+       if (was_empty) {
+               err = snd_pcm_async(pcm, getpid(), SIGIO);
+               if (err < 0) {
+                       snd_async_del_handler(h);
+                       return err;
+               }
+       }
+       *handler = h;
+       return 0;
+}
+
+/**
+ * \brief Return PCM handle related to an async handler
+ * \param handler Async handler handle
+ * \return PCM handle
+ */
+snd_pcm_t *snd_async_handler_get_pcm(snd_async_handler_t *handler)
+{
+       assert(handler->type = SND_ASYNC_HANDLER_PCM);
+       return handler->u.pcm;
+}
+
 static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name,
                             snd_config_t *pcm_root, snd_config_t *pcm_conf,
                             snd_pcm_stream_t stream, int mode)
@@ -1045,6 +1086,26 @@ int snd_pcm_open(snd_pcm_t **pcmp, const char *name,
 }
 
 #ifndef DOC_HIDDEN
+
+int snd_pcm_new(snd_pcm_t **pcmp, snd_pcm_type_t type, const char *name,
+               snd_pcm_stream_t stream, int mode)
+{
+       snd_pcm_t *pcm;
+       pcm = calloc(1, sizeof(*pcm));
+       if (!pcm)
+               return -ENOMEM;
+       pcm->type = type;
+       if (name)
+               pcm->name = strdup(name);
+       pcm->stream = stream;
+       pcm->mode = mode;
+       pcm->op_arg = pcm;
+       pcm->fast_op_arg = pcm;
+       INIT_LIST_HEAD(&pcm->async_handlers);
+       *pcmp = pcm;
+       return 0;
+}
+
 int snd_pcm_open_slave(snd_pcm_t **pcmp, snd_config_t *root,
                       snd_config_t *conf, snd_pcm_stream_t stream,
                       int mode)
index 304fcb9..f9baec0 100644 (file)
@@ -509,6 +509,7 @@ int snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfor
 {
        snd_pcm_t *pcm;
        snd_pcm_adpcm_t *adpcm;
+       int err;
        assert(pcmp && slave);
        if (snd_pcm_format_linear(sformat) != 1 &&
            sformat != SND_PCM_FORMAT_IMA_ADPCM)
@@ -524,20 +525,13 @@ int snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfor
        adpcm->plug.slave = slave;
        adpcm->plug.close_slave = close_slave;
 
-       pcm = calloc(1, sizeof(snd_pcm_t));
-       if (!pcm) {
+       err = snd_pcm_new(&pcm, SND_PCM_TYPE_ADPCM, name, slave->stream, slave->mode);
+       if (err < 0) {
                free(adpcm);
-               return -ENOMEM;
+               return err;
        }
-       if (name)
-               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_data = adpcm;
        pcm->poll_fd = slave->poll_fd;
        pcm->hw_ptr = &adpcm->plug.hw_ptr;
index 6ac4381..04a886d 100644 (file)
@@ -383,6 +383,7 @@ int snd_pcm_alaw_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sform
 {
        snd_pcm_t *pcm;
        snd_pcm_alaw_t *alaw;
+       int err;
        assert(pcmp && slave);
        if (snd_pcm_format_linear(sformat) != 1 &&
            sformat != SND_PCM_FORMAT_A_LAW)
@@ -397,20 +398,13 @@ int snd_pcm_alaw_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sform
        alaw->plug.slave = slave;
        alaw->plug.close_slave = close_slave;
 
-       pcm = calloc(1, sizeof(snd_pcm_t));
-       if (!pcm) {
+       err = snd_pcm_new(&pcm, SND_PCM_TYPE_ALAW, name, slave->stream, slave->mode);
+       if (err < 0) {
                free(alaw);
-               return -ENOMEM;
+               return err;
        }
-       if (name)
-               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_data = alaw;
        pcm->poll_fd = slave->poll_fd;
        pcm->hw_ptr = &alaw->plug.hw_ptr;
index 35972df..8c6b486 100644 (file)
@@ -157,6 +157,7 @@ int snd_pcm_copy_open(snd_pcm_t **pcmp, const char *name, snd_pcm_t *slave, int
 {
        snd_pcm_t *pcm;
        snd_pcm_copy_t *copy;
+       int err;
        assert(pcmp && slave);
        copy = calloc(1, sizeof(snd_pcm_copy_t));
        if (!copy) {
@@ -167,20 +168,13 @@ int snd_pcm_copy_open(snd_pcm_t **pcmp, const char *name, snd_pcm_t *slave, int
        copy->plug.slave = slave;
        copy->plug.close_slave = close_slave;
 
-       pcm = calloc(1, sizeof(snd_pcm_t));
-       if (!pcm) {
+       err = snd_pcm_new(&pcm, SND_PCM_TYPE_COPY, name, slave->stream, slave->mode);
+       if (err < 0) {
                free(copy);
-               return -ENOMEM;
+               return err;
        }
-       if (name)
-               pcm->name = strdup(name);
-       pcm->type = SND_PCM_TYPE_COPY;
-       pcm->stream = slave->stream;
-       pcm->mode = slave->mode;
        pcm->ops = &snd_pcm_copy_ops;
-       pcm->op_arg = pcm;
        pcm->fast_ops = &snd_pcm_plugin_fast_ops;
-       pcm->fast_op_arg = pcm;
        pcm->private_data = copy;
        pcm->poll_fd = slave->poll_fd;
        pcm->hw_ptr = &copy->plug.hw_ptr;
index c0f9d33..6697112 100644 (file)
@@ -401,6 +401,7 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name, const char *fname, int
        snd_pcm_t *pcm;
        snd_pcm_file_t *file;
        snd_pcm_file_format_t format;
+       int err;
        assert(pcmp);
        if (fmt == NULL ||
            strcmp(fmt, "raw") == 0)
@@ -430,22 +431,15 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name, const char *fname, int
        file->slave = slave;
        file->close_slave = close_slave;
 
-       pcm = calloc(1, sizeof(snd_pcm_t));
-       if (!pcm) {
+       err = snd_pcm_new(&pcm, SND_PCM_TYPE_FILE, name, slave->stream, slave->mode);
+       if (err < 0) {
                if (fname)
                        free(file->fname);
                free(file);
-               return -ENOMEM;
+               return err;
        }
-       if (name)
-               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_data = file;
        pcm->poll_fd = slave->poll_fd;
        pcm->hw_ptr = slave->hw_ptr;
index 58a9429..5d27a69 100644 (file)
@@ -293,6 +293,7 @@ int snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name, snd_pcm_t *slave, int
        snd_pcm_t *pcm;
        snd_pcm_hooks_t *h;
        unsigned int k;
+       int err;
        assert(pcmp && slave);
        h = calloc(1, sizeof(snd_pcm_hooks_t));
        if (!h)
@@ -302,20 +303,13 @@ int snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name, snd_pcm_t *slave, int
        for (k = 0; k <= SND_PCM_HOOK_TYPE_LAST; ++k) {
                INIT_LIST_HEAD(&h->hooks[k]);
        }
-       pcm = calloc(1, sizeof(snd_pcm_t));
-       if (!pcm) {
+       err = snd_pcm_new(&pcm, SND_PCM_TYPE_HOOKS, name, slave->stream, slave->mode);
+       if (err < 0) {
                free(h);
-               return -ENOMEM;
+               return err;
        }
-       if (name)
-               pcm->name = strdup(name);
-       pcm->type = SND_PCM_TYPE_HOOKS;
-       pcm->stream = slave->stream;
-       pcm->mode = slave->mode;
        pcm->ops = &snd_pcm_hooks_ops;
-       pcm->op_arg = pcm;
        pcm->fast_ops = &snd_pcm_hooks_fast_ops;
-       pcm->fast_op_arg = pcm;
        pcm->private_data = h;
        pcm->poll_fd = slave->poll_fd;
        pcm->hw_ptr = slave->hw_ptr;
index c67fc23..07066ec 100644 (file)
@@ -88,14 +88,10 @@ static int snd_pcm_hw_async(snd_pcm_t *pcm, int sig, pid_t pid)
        }
        if (sig < 0)
                return 0;
-       if (sig == 0)
-               sig = SIGIO;
        if (fcntl(fd, F_SETSIG, sig) < 0) {
                SYSERR("F_SETSIG failed");
                return -errno;
        }
-       if (pid == 0)
-               pid = getpid();
        if (fcntl(fd, F_SETOWN, pid) < 0) {
                SYSERR("F_SETOWN failed");
                return -errno;
@@ -531,12 +527,12 @@ snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
        mmap_commit: snd_pcm_hw_mmap_commit,
 };
 
-static int snd_pcm_hw_open_subdevice(snd_pcm_t **pcmp, int card, int device, int subdevice, snd_pcm_stream_t stream, int mode)
+int snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name, int card, int device, int subdevice, snd_pcm_stream_t stream, int mode)
 {
        char filename[32];
        const char *filefmt;
        int ver;
-       int ret = 0, fd = -1;
+       int err, ret = 0, fd = -1;
        int attempt = 0;
        snd_pcm_info_t info;
        int fmode;
@@ -610,19 +606,14 @@ static int snd_pcm_hw_open_subdevice(snd_pcm_t **pcmp, int card, int device, int
        hw->subdevice = subdevice;
        hw->fd = fd;
 
-       pcm = calloc(1, sizeof(snd_pcm_t));
-       if (!pcm) {
-               ret = -ENOMEM;
+       err = snd_pcm_new(&pcm, SND_PCM_TYPE_HW, name, stream, mode);
+       if (err < 0) {
+               ret = err;
                goto _err;
        }
        snd_ctl_close(ctl);
-       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_data = hw;
        pcm->poll_fd = fd;
        *pcmp = pcm;
@@ -649,16 +640,6 @@ static int snd_pcm_hw_open_subdevice(snd_pcm_t **pcmp, int card, int device, int
        return ret;
 }
 
-int snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name, int card, int device, int subdevice, snd_pcm_stream_t stream, int mode)
-{
-       int err = snd_pcm_hw_open_subdevice(pcmp, card, device, subdevice, stream, mode);
-       if (err < 0)
-               return err;
-       if (name)
-               (*pcmp)->name = strdup(name);
-       return 0;
-}
-
 int _snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name,
                     snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t *conf,
                     snd_pcm_stream_t stream, int mode)
index f5187fc..f1b9c92 100644 (file)
@@ -289,6 +289,7 @@ int snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfo
 {
        snd_pcm_t *pcm;
        snd_pcm_linear_t *linear;
+       int err;
        assert(pcmp && slave);
        if (snd_pcm_format_linear(sformat) != 1)
                return -EINVAL;
@@ -302,20 +303,13 @@ int snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfo
        linear->plug.slave = slave;
        linear->plug.close_slave = close_slave;
 
-       pcm = calloc(1, sizeof(snd_pcm_t));
-       if (!pcm) {
+       err = snd_pcm_new(&pcm, SND_PCM_TYPE_LINEAR, name, slave->stream, slave->mode);
+       if (err < 0) {
                free(linear);
-               return -ENOMEM;
+               return err;
        }
-       if (name)
-               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_data = linear;
        pcm->poll_fd = slave->poll_fd;
        pcm->hw_ptr = &linear->plug.hw_ptr;
index ee40f6b..7956ffd 100644 (file)
@@ -31,7 +31,6 @@
 #define _snd_pcm_subformat_mask _snd_mask
 
 #include "local.h"
-#include "list.h"
 
 #define SND_INTERVAL_INLINE
 #include "interval.h"
@@ -66,15 +65,6 @@ typedef enum sndrv_pcm_hw_param snd_pcm_hw_param_t;
 #define SND_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_LAST_INTERVAL
 #define SND_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_FIRST_INTERVAL
 
-/** Surround type */
-typedef enum _snd_pcm_surround_type {
-       /** 4.0 speakers */
-       SND_PCM_SURROUND_40 = 0,
-       /** 5.1 speakers */
-       SND_PCM_SURROUND_51 = 1,
-       SND_PCM_SURROUND_LAST = SND_PCM_SURROUND_51
-} snd_pcm_surround_type_t;
-
 typedef struct _snd_pcm_channel_info {
        unsigned int channel;
        void *addr;                     /* base address of channel samples */
@@ -153,8 +143,6 @@ struct _snd_pcm {
        snd_pcm_uframes_t silence_size; /* Silence filling size */
        snd_pcm_uframes_t xfer_align;   /* xfer size need to be a multiple */
        snd_pcm_uframes_t boundary;     /* pointers wrap point */
-       int async_sig;
-       pid_t async_pid;
        unsigned int info;              /* Info for returned setup */
        unsigned int msbits;            /* used most significant bits */
        unsigned int rate_num;          /* rate numerator */
@@ -175,6 +163,7 @@ struct _snd_pcm {
        snd_pcm_t *op_arg;
        snd_pcm_t *fast_op_arg;
        void *private_data;
+       struct list_head async_handlers;
 };
 
 #define ROUTE_PLUGIN_FLOAT 1
@@ -192,7 +181,10 @@ typedef int snd_pcm_route_ttable_entry_t;
 
 /* FIXME */
 #define _snd_pcm_link_descriptor _snd_pcm_poll_descriptor
+#define _snd_pcm_async_descriptor _snd_pcm_poll_descriptor
 
+int snd_pcm_new(snd_pcm_t **pcmp, snd_pcm_type_t type, const char *name,
+               snd_pcm_stream_t stream, int mode);
 int snd_pcm_hw_open(snd_pcm_t **pcm, const char *name, int card, int device, int subdevice, snd_pcm_stream_t stream, int mode);
 int snd_pcm_plug_open(snd_pcm_t **pcmp,
                      const char *name,
@@ -204,12 +196,11 @@ int snd_pcm_plug_open_hw(snd_pcm_t **pcm, const char *name, int card, int device
 int snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name, const char *sockname, const char *sname, snd_pcm_stream_t stream, int mode);
 int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name, const char *fname, int fd, const char *fmt, snd_pcm_t *slave, int close_slave);
 int snd_pcm_null_open(snd_pcm_t **pcmp, const char *name, snd_pcm_stream_t stream, int mode);
-int snd_pcm_surround_open(snd_pcm_t **pcmp, const char *name, int card, int device, snd_pcm_surround_type_t type, snd_pcm_stream_t stream, int mode);
-
 
 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_async(snd_pcm_t *pcm, int sig, pid_t pid);
 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);
index f0e5f9b..e5d7e35 100644 (file)
@@ -30,7 +30,6 @@
 #include <time.h>
 #include <pthread.h>
 #include <dlfcn.h>
-#include "list.h"
 #include "pcm_local.h"
 #include "pcm_plugin.h"
 
@@ -614,6 +613,7 @@ int snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name, unsigned int frequenc
 {
        snd_pcm_t *pcm;
        snd_pcm_meter_t *meter;
+       int err;
        assert(pcmp);
        meter = calloc(1, sizeof(snd_pcm_meter_t));
        if (!meter)
@@ -624,21 +624,14 @@ int snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name, unsigned int frequenc
        meter->delay.tv_nsec = 1000000000 / frequency;
        INIT_LIST_HEAD(&meter->scopes);
 
-       pcm = calloc(1, sizeof(snd_pcm_t));
-       if (!pcm) {
+       err = snd_pcm_new(&pcm, SND_PCM_TYPE_METER, name, slave->stream, slave->mode);
+       if (err < 0) {
                free(meter);
-               return -ENOMEM;
+               return err;
        }
-       if (name)
-               pcm->name = strdup(name);
-       pcm->type = SND_PCM_TYPE_METER;
-       pcm->stream = slave->stream;
-       pcm->mode = slave->mode;
        pcm->mmap_rw = 1;
        pcm->ops = &snd_pcm_meter_ops;
-       pcm->op_arg = pcm;
        pcm->fast_ops = &snd_pcm_meter_fast_ops;
-       pcm->fast_op_arg = pcm;
        pcm->private_data = meter;
        pcm->poll_fd = slave->poll_fd;
        pcm->hw_ptr = slave->hw_ptr;
index 2b4884c..1965594 100644 (file)
@@ -398,6 +398,7 @@ int snd_pcm_mulaw_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfor
 {
        snd_pcm_t *pcm;
        snd_pcm_mulaw_t *mulaw;
+       int err;
        assert(pcmp && slave);
        if (snd_pcm_format_linear(sformat) != 1 &&
            sformat != SND_PCM_FORMAT_MU_LAW)
@@ -412,20 +413,13 @@ int snd_pcm_mulaw_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfor
        mulaw->plug.slave = slave;
        mulaw->plug.close_slave = close_slave;
 
-       pcm = calloc(1, sizeof(snd_pcm_t));
-       if (!pcm) {
+       err = snd_pcm_new(&pcm, SND_PCM_TYPE_MULAW, name, slave->stream, slave->mode);
+       if (err < 0) {
                free(mulaw);
-               return -ENOMEM;
+               return err;
        }
-       if (name)
-               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_data = mulaw;
        pcm->poll_fd = slave->poll_fd;
        pcm->hw_ptr = &mulaw->plug.hw_ptr;
index b7fa626..29da1e4 100644 (file)
@@ -587,6 +587,7 @@ int snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
        unsigned int i;
        snd_pcm_stream_t stream;
        char slave_map[32][32] = { { 0 } };
+       int err;
 
        assert(pcmp);
        assert(slaves_count > 0 && slaves_pcm && schannels_count);
@@ -625,21 +626,15 @@ int snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
        }
        multi->channels_count = channels_count;
 
-       pcm = calloc(1, sizeof(snd_pcm_t));
-       if (!pcm) {
+       err = snd_pcm_new(&pcm, SND_PCM_TYPE_MULTI, name, stream,
+                         multi->slaves[0].pcm->mode);
+       if (err < 0) {
                free(multi);
-               return -ENOMEM;
+               return err;
        }
-       if (name)
-               pcm->name = strdup(name);
-       pcm->type = SND_PCM_TYPE_MULTI;
-       pcm->stream = stream;
-       pcm->mode = multi->slaves[0].pcm->mode;
        pcm->mmap_rw = 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_data = multi;
        pcm->poll_fd = multi->slaves[master_slave].pcm->poll_fd;
        pcm->hw_ptr = multi->slaves[master_slave].pcm->hw_ptr;
index 402ff9a..f1425a8 100644 (file)
@@ -318,6 +318,7 @@ int snd_pcm_null_open(snd_pcm_t **pcmp, const char *name, snd_pcm_stream_t strea
        snd_pcm_t *pcm;
        snd_pcm_null_t *null;
        int fd;
+       int err;
        assert(pcmp);
        if (stream == SND_PCM_STREAM_PLAYBACK) {
                fd = open("/dev/null", O_WRONLY);
@@ -340,21 +341,14 @@ int snd_pcm_null_open(snd_pcm_t **pcmp, const char *name, snd_pcm_stream_t strea
        null->poll_fd = fd;
        null->state = SND_PCM_STATE_OPEN;
        
-       pcm = calloc(1, sizeof(snd_pcm_t));
-       if (!pcm) {
+       err = snd_pcm_new(&pcm, SND_PCM_TYPE_NULL, name, stream, mode);
+       if (err < 0) {
                close(fd);
                free(null);
-               return -ENOMEM;
+               return err;
        }
-       if (name)
-               pcm->name = strdup(name);
-       pcm->type = SND_PCM_TYPE_NULL;
-       pcm->stream = stream;
-       pcm->mode = mode;
        pcm->ops = &snd_pcm_null_ops;
-       pcm->op_arg = pcm;
        pcm->fast_ops = &snd_pcm_null_fast_ops;
-       pcm->fast_op_arg = pcm;
        pcm->private_data = null;
        pcm->poll_fd = fd;
        pcm->hw_ptr = &null->hw_ptr;
index 9426f04..6d32297 100644 (file)
@@ -664,6 +664,7 @@ int snd_pcm_plug_open(snd_pcm_t **pcmp,
 {
        snd_pcm_t *pcm;
        snd_pcm_plug_t *plug;
+       int err;
        assert(pcmp && slave);
        plug = calloc(1, sizeof(snd_pcm_plug_t));
        if (!plug)
@@ -675,18 +676,12 @@ int snd_pcm_plug_open(snd_pcm_t **pcmp,
        plug->tt_cused = tt_cused;
        plug->tt_sused = tt_sused;
        
-       pcm = calloc(1, sizeof(snd_pcm_t));
-       if (!pcm) {
+       err = snd_pcm_new(&pcm, SND_PCM_TYPE_PLUG, name, slave->stream, slave->mode);
+       if (err < 0) {
                free(plug);
-               return -ENOMEM;
+               return err;
        }
-       if (name)
-               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_data = plug;
index 27a34ab..d720379 100644 (file)
@@ -493,6 +493,7 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sform
 {
        snd_pcm_t *pcm;
        snd_pcm_rate_t *rate;
+       int err;
        assert(pcmp && slave);
        if (sformat != SND_PCM_FORMAT_UNKNOWN &&
            snd_pcm_format_linear(sformat) != 1)
@@ -511,20 +512,13 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sform
        rate->plug.slave = slave;
        rate->plug.close_slave = close_slave;
 
-       pcm = calloc(1, sizeof(snd_pcm_t));
-       if (!pcm) {
+       err = snd_pcm_new(&pcm, SND_PCM_TYPE_RATE, name, slave->stream, slave->mode);
+       if (err < 0) {
                free(rate);
-               return -ENOMEM;
+               return err;
        }
-       if (name)
-               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_data = rate;
        pcm->poll_fd = slave->poll_fd;
        pcm->hw_ptr = &rate->plug.hw_ptr;
index abe1aab..1d400c3 100644 (file)
@@ -747,20 +747,13 @@ int snd_pcm_route_open(snd_pcm_t **pcmp, const char *name,
        route->plug.slave = slave;
        route->plug.close_slave = close_slave;
 
-       pcm = calloc(1, sizeof(snd_pcm_t));
-       if (!pcm) {
+       err = snd_pcm_new(&pcm, SND_PCM_TYPE_ROUTE, name, slave->stream, slave->mode);
+       if (err < 0) {
                free(route);
-               return -ENOMEM;
+               return err;
        }
-       if (name)
-               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_data = route;
        pcm->poll_fd = slave->poll_fd;
        pcm->hw_ptr = &route->plug.hw_ptr;
index 9d84576..e64e55a 100644 (file)
@@ -31,7 +31,6 @@
 #include <sys/shm.h>
 #include <pthread.h>
 #include "pcm_local.h"
-#include "list.h"
 
 
 static LIST_HEAD(snd_pcm_share_slaves);
@@ -1233,11 +1232,11 @@ int snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, const char *sname,
        }
        memcpy(share->slave_channels, channels_map, channels * sizeof(*share->slave_channels));
 
-       pcm = calloc(1, sizeof(snd_pcm_t));
-       if (!pcm) {
+       err = snd_pcm_new(&pcm, SND_PCM_TYPE_SHARE, name, stream, mode);
+       if (err < 0) {
                free(share->slave_channels);
                free(share);
-               return -ENOMEM;
+               return err;
        }
        err = socketpair(AF_LOCAL, SOCK_STREAM, 0, sd);
        if (err < 0) {
@@ -1343,16 +1342,9 @@ int snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, const char *sname,
        share->client_socket = sd[0];
        share->slave_socket = sd[1];
        
-       if (name)
-               pcm->name = strdup(name);
-       pcm->type = SND_PCM_TYPE_SHARE;
-       pcm->stream = stream;
-       pcm->mode = mode;
        pcm->mmap_rw = 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_data = share;
        pcm->poll_fd = share->client_socket;
        pcm->hw_ptr = &share->hw_ptr;
@@ -1415,8 +1407,8 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, const char *name,
                return -EINVAL;
        }
        err = snd_pcm_slave_conf(root, slave, &sconf, 5,
-                                SND_PCM_HW_PARAM_CHANNELS, 0, &schannels,
                                 SND_PCM_HW_PARAM_FORMAT, 0, &sformat,
+                                SND_PCM_HW_PARAM_CHANNELS, 0, &schannels,
                                 SND_PCM_HW_PARAM_RATE, 0, &srate,
                                 SND_PCM_HW_PARAM_PERIOD_TIME, 0, &speriod_time,
                                 SND_PCM_HW_PARAM_BUFFER_TIME, 0, &sbuffer_time);
@@ -1425,8 +1417,8 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, const char *name,
 
        /* FIXME: nothing strictly forces to have named definition */
        err = snd_config_get_string(sconf, &sname);
+       snd_config_delete(sconf);
        if (err < 0) {
-               snd_config_delete(sconf);
                SNDERR("slave.pcm is not a string");
                return err;
        }
@@ -1441,7 +1433,6 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, const char *name,
                const char *id = snd_config_get_id(n);
                err = safe_strtol(id, &cchannel);
                if (err < 0 || cchannel < 0) {
-                       snd_config_delete(sconf);
                        SNDERR("Invalid client channel in binding: %s", id);
                        return -EINVAL;
                }
@@ -1449,7 +1440,6 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, const char *name,
                        channels = cchannel + 1;
        }
        if (channels == 0) {
-               snd_config_delete(sconf);
                SNDERR("No bindings defined");
                return -EINVAL;
        }
@@ -1463,7 +1453,6 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, const char *name,
                cchannel = atoi(id);
                err = snd_config_get_integer(n, &schannel);
                if (err < 0) {
-                       snd_config_delete(sconf);
                        goto _free;
                }
                assert(schannel >= 0);
@@ -1478,7 +1467,6 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, const char *name,
                                 (unsigned int) schannels,
                                 speriod_time, sbuffer_time,
                                 channels, channels_map, stream, mode);
-       snd_config_delete(sconf);
 _free:
        free(channels_map);
        return err;
index c59a81e..062a539 100644 (file)
@@ -126,8 +126,6 @@ static int snd_pcm_shm_async(snd_pcm_t *pcm, int sig, pid_t pid)
        volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        ctrl->cmd = SND_PCM_IOCTL_ASYNC;
        ctrl->u.async.sig = sig;
-       if (pid == 0)
-               pid = getpid();
        ctrl->u.async.pid = pid;
        return snd_pcm_shm_action(pcm);
 }
@@ -638,21 +636,14 @@ int snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name, const char *sockname, c
        shm->socket = sock;
        shm->ctrl = ctrl;
 
-       pcm = calloc(1, sizeof(snd_pcm_t));
-       if (!pcm) {
-               result = -ENOMEM;
+       err = snd_pcm_new(&pcm, SND_PCM_TYPE_SHM, name, stream, mode);
+       if (err < 0) {
+               result = err;
                goto _err;
        }
-       if (name)
-               pcm->name = strdup(name);
-       pcm->type = SND_PCM_TYPE_SHM;
-       pcm->stream = stream;
-       pcm->mode = mode;
        pcm->mmap_rw = 1;
        pcm->ops = &snd_pcm_shm_ops;
-       pcm->op_arg = pcm;
        pcm->fast_ops = &snd_pcm_shm_fast_ops;
-       pcm->fast_op_arg = pcm;
        pcm->private_data = shm;
        err = snd_pcm_shm_poll_descriptor(pcm);
        if (err < 0) {
diff --git a/src/pcm/pcm_surr.c b/src/pcm/pcm_surr.c
deleted file mode 100644 (file)
index b8b5bc2..0000000
+++ /dev/null
@@ -1,1090 +0,0 @@
-/*
- *  PCM - Surround plugin
- *  Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
- *
- *  This plugin offers 4.0 and 5.1 surround devices with these routing:
- *
- *   1st channel - front left speaker
- *   2nd channel - front rear speaker
- *   3rd channel - rear left speaker
- *   4th channel - rear right speaker
- *   5th channel - center speaker
- *   6th channel - LFE channel (woofer)
- *
- *
- *   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 <byteswap.h>
-#include <limits.h>
-#include <ctype.h>
-#include <sys/shm.h>
-#include "../control/control_local.h"
-#include "pcm_local.h"
-#include "pcm_plugin.h"
-
-#define ALSA_SURROUND_FILE DATADIR "/alsa/surround.conf"
-
-#define SURR_CAP_CAPTURE       (1<<0)
-#define SURR_CAP_4CH           (1<<1)
-#define SURR_CAP_6CH           (1<<2)
-
-typedef struct _snd_pcm_surround snd_pcm_surround_t;
-
-struct _snd_pcm_surround {
-       int card;               /* card number */
-       int device;             /* device number */
-       unsigned int channels;  /* count of channels (4 or 6) */
-       int pcms;               /* count of PCM channels */
-       int use_fd;             /* use this FD for the direct access */
-       int use_fd_four;
-       int use_fd_six;
-       snd_pcm_t *pcm[3];      /* up to three PCM stereo streams */
-       int use_route: 1;       /* route is used */
-       int route[6];           /* channel route */
-       int linked[3];          /* streams are linked */
-       snd_ctl_t *ctl;         /* CTL handle */
-       unsigned int caps;      /* capabilities */
-       snd_sctl_t *store;      /* control store container */
-};
-
-static int snd_pcm_surround_free(snd_pcm_surround_t *surr);
-
-static int snd_pcm_surround_close(snd_pcm_t *pcm)
-{
-       snd_pcm_surround_t *surr = pcm->private_data;
-       return snd_pcm_surround_free(surr);
-}
-
-static int snd_pcm_surround_nonblock(snd_pcm_t *pcm, int nonblock)
-{
-       int i, err = 0, err1;
-       snd_pcm_surround_t *surr = pcm->private_data;
-       for (i = 0; i < surr->pcms; i++) {
-               err1 = snd_pcm_nonblock(surr->pcm[i], nonblock);
-               if (err1 && !err)
-                       err = err1;
-       }
-       return err;
-}
-
-static int snd_pcm_surround_async(snd_pcm_t *pcm, int sig, pid_t pid)
-{
-       snd_pcm_surround_t *surr = pcm->private_data;
-       return snd_pcm_async(surr->pcm[0], sig, pid);
-}
-
-static int snd_pcm_surround_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
-{
-       snd_pcm_surround_t *surr = pcm->private_data;
-       memset(info, 0, sizeof(*info));
-       info->stream = snd_enum_to_int(pcm->stream);
-       info->card = surr->card;
-       strncpy(info->id, "Surround", sizeof(info->id));
-       strncpy(info->name, "Surround", sizeof(info->name));
-       strncpy(info->subname, "Surround", sizeof(info->subname));
-       info->subdevices_count = 1;
-       return 0;
-}
-
-static int snd_pcm_surround_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info)
-{
-       snd_pcm_surround_t *surr = pcm->private_data;
-       int err, old_channel, use_pcm;
-
-       old_channel = info->channel;
-       if (old_channel < 0 || old_channel > 5)
-               return -EINVAL;
-       info->channel = surr->route[old_channel];
-       use_pcm = 0;
-       if (surr->pcms > 1) {
-               use_pcm = info->channel / 2;
-               info->channel %= 2;
-       }
-       if (surr->pcm[use_pcm] == NULL) {
-               info->channel = old_channel;
-               return -EINVAL;
-       }
-       err = snd_pcm_channel_info(surr->pcm[use_pcm], info);
-       info->channel = old_channel;
-       return err;
-}
-
-static int snd_pcm_surround_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
-{
-       snd_pcm_surround_t *surr = pcm->private_data;
-       return snd_pcm_status(surr->pcm[0], status);
-}
-
-static snd_pcm_state_t snd_pcm_surround_state(snd_pcm_t *pcm)
-{
-       snd_pcm_surround_t *surr = pcm->private_data;
-       return snd_pcm_state(surr->pcm[0]);
-}
-
-static int snd_pcm_surround_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
-{
-       snd_pcm_surround_t *surr = pcm->private_data;
-       return snd_pcm_delay(surr->pcm[0], delayp);
-}
-
-static int snd_pcm_surround_prepare(snd_pcm_t *pcm)
-{
-       snd_pcm_surround_t *surr = pcm->private_data;
-       return snd_pcm_prepare(surr->pcm[0]);
-}
-
-static int snd_pcm_surround_reset(snd_pcm_t *pcm)
-{
-       snd_pcm_surround_t *surr = pcm->private_data;
-       return snd_pcm_reset(surr->pcm[0]);
-}
-
-static int snd_pcm_surround_start(snd_pcm_t *pcm)
-{
-       snd_pcm_surround_t *surr = pcm->private_data;
-       return snd_pcm_start(surr->pcm[0]);
-}
-
-static int snd_pcm_surround_drop(snd_pcm_t *pcm)
-{
-       snd_pcm_surround_t *surr = pcm->private_data;
-       return snd_pcm_drop(surr->pcm[0]);
-}
-
-static int snd_pcm_surround_drain(snd_pcm_t *pcm)
-{
-       snd_pcm_surround_t *surr = pcm->private_data;
-       return snd_pcm_drain(surr->pcm[0]);
-}
-
-static int snd_pcm_surround_pause(snd_pcm_t *pcm, int enable)
-{
-       snd_pcm_surround_t *surr = pcm->private_data;
-       return snd_pcm_pause(surr->pcm[0], enable);
-}
-
-static snd_pcm_sframes_t snd_pcm_surround_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
-{
-       snd_pcm_surround_t *surr = pcm->private_data;
-       return snd_pcm_rewind(surr->pcm[0], frames);
-}
-
-static snd_pcm_sframes_t snd_pcm_surround_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
-{
-       snd_pcm_surround_t *surr = pcm->private_data;
-       if (surr->pcms == 1 && !surr->use_route)
-               return snd_pcm_writei(surr->pcm[0], buffer, size);
-       if (pcm->running_areas == NULL) {
-               int err;
-               if ((err = snd_pcm_mmap(pcm)) < 0)
-                       return err;
-       }
-       return snd_pcm_mmap_writei(pcm, buffer, size);
-}
-
-static snd_pcm_sframes_t snd_pcm_surround_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
-{
-       int i;
-       snd_pcm_sframes_t res = -1, res1;
-       snd_pcm_surround_t *surr = pcm->private_data;
-       if (surr->use_route) {
-               if (pcm->running_areas == NULL) {
-                       int err;
-                       if ((err = snd_pcm_mmap(pcm)) < 0)
-                               return err;
-               }
-               return snd_pcm_mmap_writen(pcm, bufs, size);
-       }
-       for (i = 0; i < surr->pcms; i++, bufs += 2) {
-               res1 = snd_pcm_writen(pcm, bufs, size);
-               if (res1 < 0)
-                       return res1;
-               if (res < 0)
-                       res = res1;
-               else if (res != res1)
-                       return -EPIPE;
-       }
-       return res;
-}
-
-static snd_pcm_sframes_t snd_pcm_surround_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
-{
-       snd_pcm_surround_t *surr = pcm->private_data;
-       if (surr->pcms == 1 && !surr->use_route)
-               return snd_pcm_readi(surr->pcm[0], buffer, size);
-       if (pcm->running_areas == NULL) {
-               int err;
-               if ((err = snd_pcm_mmap(pcm)) < 0)
-                       return err;
-       }
-       return snd_pcm_mmap_readi(pcm, buffer, size);
-}
-
-static snd_pcm_sframes_t snd_pcm_surround_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
-{
-       int i;
-       snd_pcm_sframes_t res = -1, res1;
-       snd_pcm_surround_t *surr = pcm->private_data;
-       if (surr->use_route) {
-               if (pcm->running_areas == NULL) {
-                       int err;
-                       if ((err = snd_pcm_mmap(pcm)) < 0)
-                               return err;
-               }
-               return snd_pcm_mmap_readn(pcm, bufs, size);
-       }
-       for (i = 0; i < surr->pcms; i++) {
-               res1 = snd_pcm_writen(pcm, bufs, size);
-               if (res1 < 0)
-                       return res1;
-               if (res < 0) {
-                       res = size = res1;
-               } else if (res != res1)
-                       return -EPIPE;
-       }
-       return res;
-}
-
-static snd_pcm_sframes_t snd_pcm_surround_mmap_commit(snd_pcm_t *pcm, snd_pcm_uframes_t offset, snd_pcm_uframes_t size)
-{
-       int i;
-       snd_pcm_sframes_t res = -1, res1;
-       snd_pcm_surround_t *surr = pcm->private_data;
-       for (i = 0; i < surr->pcms; i++) {
-               res1 = snd_pcm_mmap_commit(surr->pcm[i], offset, size);
-               if (res1 < 0)
-                       return res1;
-               if (res < 0) {
-                       res = size = res1;
-               } else if (res != res1)
-                       return -EPIPE;
-       }
-       return res;
-}
-
-static snd_pcm_sframes_t snd_pcm_surround_avail_update(snd_pcm_t *pcm)
-{
-       snd_pcm_surround_t *surr = pcm->private_data;
-       return snd_pcm_avail_update(surr->pcm[0]);
-}
-
-static int snd_pcm_surround_interval_channels(snd_pcm_surround_t *surr,
-                                             snd_pcm_hw_params_t *params,
-                                             int refine)
-{
-       snd_interval_t *interval;
-       interval = &params->intervals[SND_PCM_HW_PARAM_CHANNELS-SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
-       if (interval->empty)
-               return -EINVAL;
-       if (interval->openmin) {
-               if (!refine) {
-                       interval->empty = 1;
-                       return -EINVAL;
-               }
-               interval->min = surr->channels;
-               interval->openmin = 0;
-       }
-       if (interval->openmax) {
-               if (!refine) {
-                       interval->empty = 1;
-                       return -EINVAL;
-               }
-               interval->max = surr->channels;
-               interval->openmax = 0;
-       }
-       if (refine && interval->min <= surr->channels && interval->max >= surr->channels)
-               interval->min = interval->max = surr->channels;
-       if (interval->min != interval->max || interval->min != surr->channels) {
-               interval->empty = 1;
-               return -EINVAL;
-       }
-       if (surr->pcms != 1)
-               interval->min = interval->max = 2;
-       return 0;
-}
-
-static void snd_pcm_surround_interval_channels_fixup(snd_pcm_surround_t *surr,
-                                                    snd_pcm_hw_params_t *params)
-{
-       snd_interval_t *interval;
-       interval = &params->intervals[SND_PCM_HW_PARAM_CHANNELS-SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
-       interval->min = interval->max = surr->channels;
-}
-
-static int snd_pcm_surround_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
-{
-       snd_pcm_surround_t *surr = pcm->private_data;
-       snd_pcm_access_mask_t *access_mask;
-       snd_pcm_access_mask_t *access_mask1;
-       int i, err;
-
-       err = snd_pcm_surround_interval_channels(surr, params, 1);
-       if (err < 0)
-               return err;
-       if (surr->pcms == 1 && !surr->use_route)
-               return snd_pcm_hw_refine(surr->pcm[0], params);
-       access_mask = (snd_pcm_access_mask_t *)snd_pcm_hw_param_get_mask(params, SND_PCM_HW_PARAM_ACCESS);
-       snd_pcm_access_mask_alloca(&access_mask1);
-       snd_pcm_access_mask_copy(access_mask1, access_mask);
-       snd_pcm_access_mask_reset(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED);
-       if (snd_pcm_access_mask_test(access_mask1, SND_PCM_ACCESS_RW_INTERLEAVED))
-               snd_pcm_access_mask_set(access_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
-       for (i = 0; i < surr->pcms; i++) {
-               err = snd_pcm_hw_refine(surr->pcm[i], params);
-               if (err < 0)
-                       goto __error;
-       }
-       err = 0;
-      __error:
-       snd_pcm_access_mask_none(access_mask);
-       if (snd_pcm_access_mask_test(access_mask1, SND_PCM_ACCESS_RW_INTERLEAVED))
-               snd_pcm_access_mask_set(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED);
-       if (snd_pcm_access_mask_test(access_mask1, SND_PCM_ACCESS_RW_NONINTERLEAVED))
-               snd_pcm_access_mask_set(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED);
-       if (snd_pcm_access_mask_test(access_mask1, SND_PCM_ACCESS_MMAP_COMPLEX))
-               snd_pcm_access_mask_set(access_mask, SND_PCM_ACCESS_MMAP_COMPLEX);
-       snd_pcm_surround_interval_channels_fixup(surr, params);
-       return err;
-}
-
-static int snd_pcm_surround_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
-{
-       snd_pcm_surround_t *surr = pcm->private_data;
-       snd_pcm_access_mask_t *access_mask;
-       snd_pcm_access_mask_t *access_mask1;
-       int i, err;
-       
-       err = snd_pcm_surround_interval_channels(surr, params, 0);
-       if (err < 0)
-               return err;
-       if (surr->pcms == 1 && !surr->use_route)
-               return snd_pcm_hw_params(surr->pcm[0], params);
-       access_mask = (snd_pcm_access_mask_t *)snd_pcm_hw_param_get_mask(params, SND_PCM_HW_PARAM_ACCESS);
-       snd_pcm_access_mask_alloca(&access_mask1);
-       snd_pcm_access_mask_copy(access_mask1, access_mask);
-       snd_pcm_access_mask_reset(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED);
-       if (snd_pcm_access_mask_test(access_mask1, SND_PCM_ACCESS_RW_INTERLEAVED))
-               snd_pcm_access_mask_set(access_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
-       for (i = 0; i < surr->pcms; i++) {
-               err = snd_pcm_hw_params(surr->pcm[i], params);
-               if (err < 0) {
-                       snd_pcm_access_mask_copy(access_mask, access_mask1);
-                       snd_pcm_surround_interval_channels_fixup(surr, params);
-                       return err;
-               }
-       }
-       snd_pcm_access_mask_copy(access_mask, access_mask1);
-       snd_pcm_surround_interval_channels_fixup(surr, params);
-       surr->linked[0] = 0;
-       for (i = 1; i < surr->pcms; i++) {
-               err = snd_pcm_link(surr->pcm[0], surr->pcm[i]);
-               if ((surr->linked[i] = (err >= 0)) == 0)
-                       return err;
-       }
-       return 0;
-}
-
-static int snd_pcm_surround_hw_free(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
-{
-       int i, err, res = 0;
-       snd_pcm_surround_t *surr = pcm->private_data;
-       for (i = 0; i < surr->pcms; i++) {
-               err = snd_pcm_hw_free(surr->pcm[i]);
-               if (err < 0)
-                       res = err;
-               if (!surr->linked[i])
-                       continue;
-               surr->linked[i] = 0;
-               err = snd_pcm_unlink(surr->pcm[i]);
-               if (err < 0)
-                       res = err;
-       }
-       return res;
-}
-
-static int snd_pcm_surround_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
-{
-       int i, err;
-       snd_pcm_surround_t *surr = pcm->private_data;
-       for (i = 0; i < surr->pcms; i++) {
-               err = snd_pcm_sw_params(surr->pcm[i], params);
-               if (err < 0)
-                       return err;
-       }
-       return 0;
-}
-
-static int snd_pcm_surround_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
-{
-       // snd_pcm_surround_t *surr = pcm->private_data;
-       return 0;
-}
-
-static int snd_pcm_surround_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
-{
-       // snd_pcm_surround_t *surr = pcm->private_data;
-       return 0;
-}
-
-static void snd_pcm_surround_dump(snd_pcm_t *pcm, snd_output_t *out)
-{
-       snd_output_printf(out, "Surround PCM\n");
-       if (pcm->setup) {
-               snd_output_printf(out, "Its setup is:\n");
-               snd_pcm_dump_setup(pcm, out);
-       }
-}
-
-snd_pcm_ops_t snd_pcm_surround_ops = {
-       close: snd_pcm_surround_close,
-       info: snd_pcm_surround_info,
-       hw_refine: snd_pcm_surround_hw_refine,
-       hw_params: snd_pcm_surround_hw_params,
-       hw_free: snd_pcm_surround_hw_free,
-       sw_params: snd_pcm_surround_sw_params,
-       channel_info: snd_pcm_surround_channel_info,
-       dump: snd_pcm_surround_dump,
-       nonblock: snd_pcm_surround_nonblock,
-       async: snd_pcm_surround_async,
-       mmap: snd_pcm_surround_mmap,
-       munmap: snd_pcm_surround_munmap,
-};
-
-snd_pcm_fast_ops_t snd_pcm_surround_fast_ops = {
-       status: snd_pcm_surround_status,
-       state: snd_pcm_surround_state,
-       delay: snd_pcm_surround_delay,
-       prepare: snd_pcm_surround_prepare,
-       reset: snd_pcm_surround_reset,
-       start: snd_pcm_surround_start,
-       drop: snd_pcm_surround_drop,
-       drain: snd_pcm_surround_drain,
-       pause: snd_pcm_surround_pause,
-       rewind: snd_pcm_surround_rewind,
-       writei: snd_pcm_surround_writei,
-       writen: snd_pcm_surround_writen,
-       readi: snd_pcm_surround_readi,
-       readn: snd_pcm_surround_readn,
-       avail_update: snd_pcm_surround_avail_update,
-       mmap_commit: snd_pcm_surround_mmap_commit,
-};
-
-static int snd_pcm_surround_free(snd_pcm_surround_t *surr)
-{
-       int i;
-
-       assert(surr);
-       for (i = 2; i >= 0; i--) {
-               if (surr->pcm[i] == NULL)
-                       continue;
-               snd_pcm_close(surr->pcm[i]);
-               surr->pcm[i] = NULL;
-       }
-       if (surr->store)
-               snd_sctl_free(surr->ctl, surr->store);
-       if (surr->ctl)
-               snd_ctl_close(surr->ctl);
-       free(surr);
-       return 0;
-}
-
-static int snd_pcm_surround_one_stream(snd_pcm_surround_t *surr,
-                                      snd_pcm_surround_type_t type ATTRIBUTE_UNUSED,
-                                      int card,
-                                      int dev, int subdev,
-                                      snd_pcm_stream_t stream, int mode)
-{
-       int err;
-
-       if ((err = snd_pcm_hw_open(&surr->pcm[0], "Surround", card, dev,
-                                  subdev, stream, mode)) < 0)
-               return err;
-       surr->pcms++;
-       return 0;
-}
-
-static int snd_pcm_surround_three_streams(snd_pcm_surround_t *surr,
-                                         snd_pcm_surround_type_t type,
-                                         int card,
-                                         int dev0, int subdev0,
-                                         int dev1, int subdev1,
-                                         int dev2, int subdev2,
-                                         snd_pcm_stream_t stream, int mode)
-{
-       int err;
-
-       if ((err = snd_pcm_hw_open(&surr->pcm[0], "Surround L/R", card, dev0,
-                                  subdev0, stream, mode)) < 0)
-               return err;
-       surr->pcms++;
-       if ((err = snd_pcm_hw_open(&surr->pcm[1], "Surround Rear L/R", card, dev1,
-                                  subdev1, stream, mode)) < 0)
-               return err;
-       surr->pcms++;
-       if (type == SND_PCM_SURROUND_51) {
-               if ((err = snd_pcm_hw_open(&surr->pcm[2], "Surround Center/LFE", card, dev2,
-                                          subdev2, stream, mode)) < 0)
-                       return err;
-               surr->pcms++;
-       }
-       return 0;
-}
-
-static int build_config(snd_config_t **r_conf)
-{
-       int err;
-       snd_input_t *in;
-       snd_config_t *conf, *file;
-       const char *filename = ALSA_SURROUND_FILE;
-
-       assert(r_conf);
-       *r_conf = NULL;
-       if ((err = snd_config_update()) < 0)
-               return err;
-       if ((err = snd_config_search(snd_config, "surround_file", &file)) >= 0) {
-               if ((err = snd_config_get_string(file, &filename)) < 0) {
-                       SNDERR("cards_file definition must be string");
-                       filename = ALSA_SURROUND_FILE;
-               }
-       }
-       if ((err = snd_input_stdio_open(&in, filename, "r")) < 0) {
-               SNDERR("unable to open configuration file '%s'", filename);
-               return err;
-       }
-       if ((err = snd_config_top(&conf)) < 0) {
-               SNDERR("config_top");
-               snd_input_close(in);
-               return err;
-       }
-       if ((err = snd_config_load(conf, in)) < 0) {
-               SNDERR("config load error");
-               snd_config_delete(conf);
-               snd_input_close(in);
-               return err;
-       }
-       snd_input_close(in);
-       *r_conf = conf;
-       return 0;
-}
-
-int load_surround_config(snd_ctl_t *ctl, snd_pcm_surround_t *surr,
-                        snd_pcm_surround_type_t stype,
-                        snd_card_type_t ctype,
-                        snd_pcm_stream_t stream,
-                        int mode)
-{
-       int err, res = -EINVAL;
-       snd_config_t *conf = NULL, *surrconf;
-       snd_config_iterator_t i, next;
-
-       if ((err = build_config(&conf)) < 0)
-               return err;
-       if ((err = snd_config_search(conf, "surround_plugin", &surrconf)) < 0) {
-               SNDERR("unable to find card definitions");
-               snd_config_delete(conf);
-               return err;
-       }
-       if (snd_config_get_type(surrconf) != SND_CONFIG_TYPE_COMPOUND) {
-               SNDERR("compound type expected");
-               snd_config_delete(conf);
-               return err;
-       }
-       snd_config_for_each(i, next, surrconf) {
-               snd_config_t *n = snd_config_iterator_entry(i), *n1;
-               const char *id = snd_config_get_id(n);
-               snd_card_type_t mytype = (snd_card_type_t)-1;
-               int opened = 0;
-               if (isdigit(*id)) {
-                       mytype = (snd_card_type_t)atoi(id);
-               } else {
-                       if (snd_card_type_string_to_enum(id, &mytype) < 0) {
-                               SNDERR("snd_card_type_string_to_enum %s", id);
-                               continue;
-                       }
-               }
-               if (mytype != ctype)
-                       continue;
-               if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
-                       SNDERR("compound type expected");
-                       goto __error;
-               }
-               if (snd_config_search(n, "device", &n1) >= 0) {
-                       unsigned long i;
-                       if ((err = snd_config_get_integer(n1, &i)) < 0) {
-                               SNDERR("Invalid type for field device");
-                               goto __error;
-                       }
-                       if (surr->device != (int)i)
-                               continue;
-               }
-               if (snd_config_search(n, "channels_four", &n1) >= 0) {
-                       const char *str;
-                       if ((err = snd_config_get_string(n1, &str)) < 0) {
-                               SNDERR("Invalid value for %s", id);
-                               goto __error;
-                       } else if (!strcasecmp(str, "true")) {
-                               surr->caps |= SURR_CAP_4CH;
-                       } else if (isdigit(*str) && atoi(str) != 0)
-                               surr->caps |= SURR_CAP_4CH;
-               }
-               if (snd_config_search(n, "channels_six", &n1) >= 0) {
-                       const char *str;
-                       if ((err = snd_config_get_string(n1, &str)) < 0) {
-                               SNDERR("Invalid value for %s", id);
-                               goto __error;
-                       } else if (!strcasecmp(str, "true")) {
-                               surr->caps |= SURR_CAP_6CH;
-                       } else if (isdigit(*str) && atoi(str) != 0)
-                               surr->caps |= SURR_CAP_6CH;
-               }
-               if (snd_config_search(n, "use_fd_four", &n1) >= 0) {
-                       unsigned long i;
-                       if ((err = snd_config_get_integer(n1, &i)) < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               goto __error;
-                       } else if (i <= 1)
-                               surr->use_fd_four = i;
-                       else {
-                               SNDERR("Invalid range for use_fd (0-2): %li", i);
-                               goto __error;
-                       }
-               }
-               if (snd_config_search(n, "use_fd_six", &n1) >= 0) {
-                       unsigned long i;
-                       if ((err = snd_config_get_integer(n1, &i)) < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               goto __error;
-                       } else if (i <= 2)
-                               surr->use_fd_six = i;
-                       else {
-                               SNDERR("Invalid range for use_fd (0-2): %li", i);
-                               goto __error;
-                       }
-               }
-               if (snd_config_search(n, "route_four", &n1) >= 0) {
-                       snd_config_iterator_t i, next;
-                       snd_config_t *n2;
-                       if (stype == SND_PCM_SURROUND_40) {
-                               if (snd_config_get_type(n1) != SND_CONFIG_TYPE_COMPOUND) {
-                                       SNDERR("compound type expected");
-                                       goto __error;
-                               }
-                               if (snd_config_search(n1, "channel", &n2) >= 0) {
-                                       snd_config_for_each(i, next, n2) {
-                                               snd_config_t *n = snd_config_iterator_entry(i);
-                                               int idx = atoi(snd_config_get_id(n));
-                                               unsigned long i;
-                                               int err = snd_config_get_integer(n, &i);
-                                               if (err < 0) {
-                                                       SNDERR("Invalid field channel.%s", snd_config_get_id(n));
-                                                       goto __error;
-                                               }
-                                               if (idx < 0 || idx >= 4) {
-                                                       SNDERR("Index is out of range (0-3): %i", idx);
-                                                       goto __error;
-                                               }
-                                               if (idx != (int)i)
-                                                       surr->use_route = 1;
-                                               surr->route[idx] = i;
-                                       }
-                               }
-                       }
-               }
-               if (snd_config_search(n, "route_six", &n1) >= 0) {
-                       snd_config_iterator_t i, next;
-                       snd_config_t *n2;
-                       if (stype == SND_PCM_SURROUND_51) {
-                               if (snd_config_get_type(n1) != SND_CONFIG_TYPE_COMPOUND) {
-                                       SNDERR("compound type expected");
-                                       goto __error;
-                               }
-                               if (snd_config_search(n1, "channel", &n2) >= 0) {
-                                       snd_config_for_each(i, next, n2) {
-                                               snd_config_t *n = snd_config_iterator_entry(i);
-                                               int idx = atoi(snd_config_get_id(n));
-                                               unsigned long i;
-                                               int err = snd_config_get_integer(n, &i);
-                                               if (err < 0) {
-                                                       SNDERR("Invalid field channel.%s", snd_config_get_id(n));
-                                                       goto __error;
-                                               }
-                                               if (idx < 0 || idx >= 6) {
-                                                       SNDERR("Index is out of range (0-5): %i", idx);
-                                                       goto __error;
-                                               }
-                                               if (idx != (int)i)
-                                                       surr->use_route = 1;
-                                               surr->route[idx] = i;
-                                       }
-                               }
-                       }
-               }
-               if (snd_config_search(n, "open_single", &n1) >= 0) {
-                       snd_config_iterator_t i, next;
-                       int device = 0, subdevice = -1;
-                       surr->use_fd = 0;
-                       if (snd_config_get_type(n1) != SND_CONFIG_TYPE_COMPOUND) {
-                               SNDERR("compound type expected");
-                               goto __error;
-                       }
-                       snd_config_for_each(i, next, n1) {
-                               snd_config_t *n = snd_config_iterator_entry(i);
-                               const char *id = snd_config_get_id(n);
-                               unsigned long i;
-                               if (!strcmp(id, "device")) {
-                                       if ((err = snd_config_get_integer(n, &i)) < 0) {
-                                               SNDERR("Invalid type for %s", id);
-                                               goto __error;
-                                       }
-                                       device = i;
-                               } else if (!strcmp(id, "subdevice")) {
-                                       if ((err = snd_config_get_integer(n, &i)) < 0) {
-                                               SNDERR("Invalid type for %s", id);
-                                               goto __error;
-                                       }
-                                       subdevice = i;
-                               } else {
-                                       SNDERR("Invalid field %s", id);
-                                       goto __error;
-                               }
-                       }
-                       if (stream == SND_PCM_STREAM_CAPTURE && !(surr->caps & SURR_CAP_CAPTURE)) {
-                               err = -ENODEV;
-                               goto __error;
-                       }
-                       switch (stype) {
-                       case SND_PCM_SURROUND_40:
-                               if (!(surr->caps & SURR_CAP_4CH)) {
-                                       err = -ENODEV;
-                                       goto __error;
-                               }
-                               break;
-                       case SND_PCM_SURROUND_51:
-                               if (!(surr->caps & SURR_CAP_6CH)) {
-                                       err = -ENODEV;
-                                       goto __error;
-                               }
-                               break;
-                       }
-                       if ((err = snd_pcm_surround_one_stream(surr, stype, surr->card, device, subdevice, stream, mode)) < 0) {
-                               SNDERR("surround single stream open error %i,%i,%i: %s", surr->card, device, subdevice, snd_strerror(err));
-                               goto __error;
-                       }
-                       opened = 1;
-               } else if (snd_config_search(n, "open_multi", &n1) >= 0) {
-                       snd_config_iterator_t i, next;
-                       int device[3] = { 0, 0, 0 }, subdevice[3] = { -1, -1, -1 };
-                       if (snd_config_get_type(n1) != SND_CONFIG_TYPE_COMPOUND) {
-                               SNDERR("compound type expected");
-                               goto __error;
-                       }
-                       snd_config_for_each(i, next, n1) {
-                               snd_config_t *n = snd_config_iterator_entry(i);
-                               const char *id = snd_config_get_id(n);
-                               snd_config_iterator_t i, next;
-                               if (!strcmp(id, "device") || !strcmp(id, "subdevice")) {
-                                       if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
-                                               SNDERR("compound type expected");
-                                               goto __error;
-                                       }
-                                       snd_config_for_each(i, next, n) {
-                                               snd_config_t *n = snd_config_iterator_entry(i);
-                                               const char *id = snd_config_get_id(n);
-                                               int idx = atoi(snd_config_get_id(n));
-                                               unsigned long i;
-                                               if (idx < 0 || idx > 2) {
-                                                       SNDERR("Invalid index %s", snd_config_get_id(n));
-                                                       goto __error;
-                                               }
-                                               if ((err = snd_config_get_integer(n, &i)) < 0) {
-                                                       SNDERR("Invalid type for %s", id);
-                                                       goto __error;
-                                               }
-                                               if (!strcmp(id, "device"))
-                                                       device[idx] = i;
-                                               else
-                                                       subdevice[idx] = i;
-                                       }
-                               } else {
-                                       SNDERR("Invalid field %s", id);
-                                       goto __error;
-                               }
-                       }
-                       if (stream == SND_PCM_STREAM_CAPTURE && !(surr->caps & SURR_CAP_CAPTURE)) {
-                               err = -ENODEV;
-                               goto __error;
-                       }
-                       switch (stype) {
-                       case SND_PCM_SURROUND_40:
-                               surr->use_fd = surr->use_fd_four;
-                               if (!(surr->caps & SURR_CAP_4CH)) {
-                                       err = -ENODEV;
-                                       goto __error;
-                               }
-                               break;
-                       case SND_PCM_SURROUND_51:
-                               surr->use_fd = surr->use_fd_six;
-                               if (!(surr->caps & SURR_CAP_6CH)) {
-                                       err = -ENODEV;
-                                       goto __error;
-                               }
-                               break;
-                       }
-                       if ((err = snd_pcm_surround_three_streams(surr, stype, surr->card, device[0], subdevice[0], device[1], subdevice[1], device[2], subdevice[2], stream, mode)) < 0) {
-                               SNDERR("surround single stream open error %i,%i,%i,%i,%i,%i,%i: %s", surr->card, device[0], subdevice[0], device[1], subdevice[1], device[2], subdevice[2], snd_strerror(err));
-                               goto __error;
-                       }
-                       if (surr->pcm[surr->use_fd] == NULL)
-                               surr->use_fd = 0;
-                       opened = 1;
-               }
-               if (opened == 0) {
-                       err = -ENODEV;
-                       goto __error;
-               }
-               if (stype == SND_PCM_SURROUND_40 && snd_config_search(n, "open_control_four", &n1) >= 0) {
-                       snd_sctl_replace_t replace[3];
-                       char values[2][10] = { "123", "123" };
-                       snd_pcm_info_t *info;
-                       int ridx = 0;
-                       
-                       snd_pcm_info_alloca(&info);
-                       if ((err = snd_pcm_info(surr->pcm[0], info)) < 0) {
-                               SNDERR("snd_pcm_info failed", snd_strerror(err));
-                               goto __error;
-                       }
-                       sprintf(values[0], "%i", snd_pcm_info_get_subdevice(info));
-                       replace[ridx].key = "index";
-                       replace[ridx].old_value = "subdevice0";
-                       replace[ridx].new_value = values[0];
-                       ridx++;
-                       
-                       if (surr->pcm[1]) {
-                               if ((err = snd_pcm_info(surr->pcm[1], info)) < 0) {
-                                       SNDERR("snd_pcm_info failed", snd_strerror(err));
-                                       goto __error;
-                               }
-                               sprintf(values[1], "%i", snd_pcm_info_get_subdevice(info));
-                               replace[ridx].key = "index";
-                               replace[ridx].old_value = "subdevice1";
-                               replace[ridx].new_value = values[1];
-                               ridx++;
-                       }
-                       replace[ridx].key = NULL;
-                       replace[ridx].old_value = NULL;
-                       replace[ridx].new_value = NULL;
-                       if ((err = snd_sctl_build(ctl, &surr->store, n1, replace)) < 0) {
-                               SNDERR("snd_sctl_build : %s\n", snd_strerror(err));
-                               goto __error;
-                       }
-               }
-               if ((stype == SND_PCM_SURROUND_51 && snd_config_search(n, "open_control_six", &n1) >= 0) ||
-                   snd_config_search(n, "open_control", &n1) >= 0) {
-                       snd_sctl_replace_t replace[4];
-                       char values[3][10] = { "123", "123", "123" };
-                       snd_pcm_info_t *info;
-                       int ridx = 0;
-                       
-                       snd_pcm_info_alloca(&info);
-                       if ((err = snd_pcm_info(surr->pcm[0], info)) < 0) {
-                               SNDERR("snd_pcm_info failed", snd_strerror(err));
-                               goto __error;
-                       }
-                       sprintf(values[0], "%i", snd_pcm_info_get_subdevice(info));
-                       replace[ridx].key = "index";
-                       replace[ridx].old_value = "subdevice0";
-                       replace[ridx].new_value = values[0];
-                       ridx++;
-                       
-                       if (surr->pcm[1]) {
-                               if ((err = snd_pcm_info(surr->pcm[1], info)) < 0) {
-                                       SNDERR("snd_pcm_info failed", snd_strerror(err));
-                                       goto __error;
-                               }
-                               sprintf(values[1], "%i", snd_pcm_info_get_subdevice(info));
-                               replace[ridx].key = "index";
-                               replace[ridx].old_value = "subdevice1";
-                               replace[ridx].new_value = values[1];
-                               ridx++;
-                       }
-                       if (surr->pcm[2]) {
-                               if ((err = snd_pcm_info(surr->pcm[2], info)) < 0) {
-                                       SNDERR("snd_pcm_info failed", snd_strerror(err));
-                                       goto __error;
-                               }
-                               sprintf(values[2], "%i", snd_pcm_info_get_subdevice(info));
-                               replace[ridx].key = "index";
-                               replace[ridx].old_value = "subdevice2";
-                               replace[ridx].new_value = values[2];
-                               ridx++;
-                       }
-                       replace[ridx].key = NULL;
-                       replace[ridx].old_value = NULL;
-                       replace[ridx].new_value = NULL;
-                       if ((err = snd_sctl_build(ctl, &surr->store, n1, replace)) < 0) {
-                               SNDERR("snd_sctl_build : %s\n", snd_strerror(err));
-                               goto __error;
-                       }
-               }
-               return 0;
-       }
-       res = -ENOENT;
-       SNDERR("configuration for card %i not found", (int)ctype);
-      __error:
-       snd_config_delete(conf);
-       return res;
-}
-
-int snd_pcm_surround_open(snd_pcm_t **pcmp, const char *name, int card, int dev,
-                         snd_pcm_surround_type_t type,
-                         snd_pcm_stream_t stream, int mode)
-{
-       snd_pcm_t *pcm = NULL;
-       snd_pcm_surround_t *surr;
-       snd_ctl_t *ctl = NULL;
-       snd_ctl_card_info_t *info;
-       snd_card_type_t ctype;
-       int err, idx;
-
-       assert(pcmp);
-       surr = calloc(1, sizeof(snd_pcm_surround_t));
-       if (!surr)
-               return -ENOMEM;
-       switch (type) {
-       case SND_PCM_SURROUND_40:
-               surr->channels = 4;
-               break;
-       case SND_PCM_SURROUND_51:
-               surr->channels = 6;
-               break;
-       default:
-               snd_pcm_surround_free(surr);
-               return -EINVAL;
-       }
-       if ((err = snd_ctl_hw_open(&ctl, "Surround", card, 0)) < 0) {
-               snd_pcm_surround_free(surr);
-               return err;
-       }
-       surr->ctl = ctl;
-       surr->card = card;
-       surr->device = dev;
-       surr->caps = SURR_CAP_4CH;
-       for (idx = 0; idx < 6; idx++)
-               surr->route[idx] = idx;
-       snd_ctl_card_info_alloca(&info);
-       if ((err = snd_ctl_card_info(ctl, info)) < 0)
-               goto __error;
-       ctype = snd_ctl_card_info_get_type(info);
-       if ((err = load_surround_config(ctl, surr, type, ctype, stream, mode)) < 0)
-               goto __error;
-       if (surr->store == NULL) {
-               snd_ctl_close(ctl);
-               surr->ctl = NULL;
-       }
-       ctl = NULL;
-       pcm = calloc(1, sizeof(snd_pcm_t));
-       if (!pcm) {
-               err = -ENOMEM;
-               goto __error;
-       }
-       if (name)
-               pcm->name = strdup(name);
-       pcm->type = SND_PCM_TYPE_SURROUND;
-       pcm->stream = stream;
-       pcm->mode = mode;
-       pcm->ops = &snd_pcm_surround_ops;
-       pcm->op_arg = pcm;
-       pcm->fast_ops = &snd_pcm_surround_fast_ops;
-       pcm->fast_op_arg = pcm;
-       pcm->private_data = surr;
-       pcm->poll_fd = surr->pcm[surr->use_fd]->poll_fd;
-       pcm->hw_ptr = surr->pcm[surr->use_fd]->hw_ptr;
-       pcm->appl_ptr = surr->pcm[surr->use_fd]->appl_ptr;
-       
-       *pcmp = pcm;
-
-       return 0;
-
-      __error:
-       snd_pcm_surround_free(surr);
-       return err;
-}
-
-int _snd_pcm_surround_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
-                          snd_pcm_stream_t stream, int mode)
-{
-       snd_config_iterator_t i, next;
-       long card = -1, device = 0;
-       const char *str;
-       int err;
-       snd_pcm_surround_type_t type = SND_PCM_SURROUND_40;
-       snd_config_for_each(i, next, conf) {
-               snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
-               if (snd_pcm_conf_generic_id(id))
-                       continue;
-               if (strcmp(id, "card") == 0) {
-                       err = snd_config_get_integer(n, &card);
-                       if (err < 0) {
-                               err = snd_config_get_string(n, &str);
-                               if (err < 0) {
-                                       SNDERR("Invalid type for %s", id);
-                                       return -EINVAL;
-                               }
-                               card = snd_card_get_index(str);
-                               if (card < 0) {
-                                       SNDERR("Invalid value for %s", id);
-                                       return card;
-                               }
-                       }
-                       continue;
-               }
-               if (strcmp(id, "device") == 0) {
-                       err = snd_config_get_integer(n, &device);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return err;
-                       }
-                       continue;
-               }
-#if 0
-               if (strcmp(id, "subdevice") == 0) {
-                       err = snd_config_get_integer(n, &subdevice);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return err;
-                       }
-                       continue;
-               }
-#endif
-               if (strcmp(id, "stype") == 0) {
-                       err = snd_config_get_string(n, &str);
-                       if (strcmp(str, "40") == 0 || strcmp(str, "4.0") == 0)
-                               type = SND_PCM_SURROUND_40;
-                       else if (strcmp(str, "51") == 0 || strcmp(str, "5.1") == 0)
-                               type = SND_PCM_SURROUND_51;
-                       continue;
-               }
-               SNDERR("Unknown field %s", id);
-               return -EINVAL;
-       }
-       if (card < 0) {
-               SNDERR("card is not defined");
-               return -EINVAL;
-       }
-       return snd_pcm_surround_open(pcmp, name, card, device, type, stream, mode);
-}
diff --git a/src/pcm/surround.conf b/src/pcm/surround.conf
deleted file mode 100644 (file)
index 5a41539..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-#
-#  Configuration for the surround plugin
-#
-
-surround_plugin.SI_7018 {      # test only
-       channels_six = true;
-       open_multi {
-               device.0 = 0;
-               subdevice.0 = -1;
-               device.1 = 0;
-               subdevice.1 = -1;
-               device.2 = 0;
-               subdevice.2 = -1;
-       }
-       open_control.0 {
-               iface = MIXER;
-               name = 'CD Playback Switch';
-               index = 0;
-               lock = true;
-               preserve = true;
-               value.0 = 1;
-               value.1 = 1;
-       }
-       open_control.1 {
-               iface = MIXER;
-               name = 'CD Playback Volume';
-               index = 0;
-               lock = true;
-               preserve = true;
-               value.0 = 16;
-               value.1 = 19;
-       }
-}
-
-surround_plugin.FM801 {
-       channels_six = true;
-       open_single {
-               device = 0;
-               subdevice = 0;
-       }
-}
-
-surround_plugin.ENS1370 {
-       use_fd_four = 1;
-       open_multi {
-               device.0 = 1;
-               subdevice.0 = 0;
-               device.1 = 0;
-               subdevice.1 = 0;
-       }
-       # Reroute PCM0 (rear) to Line-In Jack.
-       open_control.0 {
-               iface = CARD;
-               name = 'PCM 0 Output also on Line-In Jack';
-               index = 0;
-               lock = true;
-               preserve = true;
-               value.0 = true;
-       }
-       # Turn off the PCM volume, the second PCM (front speakers) uses
-       # the second PCM control.
-       open_control.1 {
-               iface = MIXER;
-               name = 'PCM Switch';
-               index = 0;
-               lock = true;
-               preserve = true;
-               value.0 = false;
-               value.1 = false;
-       }
-}
-
-surround_plugin.YMFPCI {
-       open_multi {
-               device.0 = 0;
-               subdevice.0 = 0;
-               device.1 = 2;
-               subdevice.1 = 0;
-       }
-}
-
-surround_plugin.TRID4DWAVENX {
-       open_multi {
-               device.0 = 0;
-               subdevice.0 = -1;
-               device.1 = 0;
-               subdevice.1 = -1;
-       }
-       # Enable rear path
-       open_control.0 {
-               iface = MIXER;
-               name = 'Rear Path';
-               index = subdevice1;
-               lock = true;
-               value.0 = true;
-       }
-       # Mute front volume
-       open_control.1 {
-               iface = MIXER;
-               name = 'PCM Front Playback Volume';
-               index = subdevice1;
-               lock = true;
-               value.0 = 0;
-               value.1 = 0;
-       }
-       # Set reverb (rear) volume
-       open_control.2 {
-               iface = MIXER;
-               name = 'PCM Reverb Playback Volume';
-               index = subdevice1;
-               lock = true;
-               value.0 = 127;
-               value.1 = 127;
-       }
-}
-
-surround_plugin.INTEL8X0 {
-       channels_six = true;
-       route_four {
-               channel.0 = 0;          # FR = FR
-               channel.1 = 1;          # FL = FL
-               channel.2 = 2;          # SR = SR
-               channel.3 = 3;          # SL = SL
-       }
-       route_six {
-               channel.0 = 0;          # FR = FR
-               channel.1 = 1;          # FL = FL
-               channel.2 = 4;          # SR = Center
-               channel.3 = 5;          # SL = LFE
-               channel.4 = 2;          # Center = SR
-               channel.5 = 3;          # LFE = SL
-       }
-       open_single {
-               device = 0;
-               subdevice = 0;
-       }
-}
-
-surround_plugin.EMU10K1 {
-       channels_six = true;
-       use_fd_four = 1;
-       use_fd_six = 2;
-       open_multi {
-               device.0 = 0;
-               subdevice.0 = -1;
-               device.1 = 0;
-               subdevice.1 = -1;
-               device.2 = 0;
-               subdevice.2 = -1;
-       }
-       open_control_four.0 {
-               iface = MIXER;
-               name = 'Wave Surround Playback Volume';
-               index = 0;
-               lock = true;
-               preserve = true;
-               value.0 = 0;
-               value.1 = 0;
-       }
-       # change send volume from front to rear
-       open_control_four.1 {
-               iface = MIXER;
-               name = 'EMU10K1 PCM Send Volume';
-               index = subdevice1;
-               lock = true;
-               value.4 = 0;
-               value.5 = 0;
-               value.6 = 255;
-               value.7 = 0;
-               value.8 = 0;
-               value.9 = 0;
-               value.10 = 0;
-               value.11 = 255;
-       }
-       open_control_six.0 {
-               iface = MIXER;
-               name = 'Wave Surround Playback Volume';
-               index = 0;
-               lock = true;
-               preserve = true;
-               value.0 = 0;
-               value.1 = 0;
-       }
-       # change send volume from front to rear
-       open_control_six.1 {
-               iface = MIXER;
-               name = 'EMU10K1 PCM Send Volume';
-               index = subdevice1;
-               lock = true;
-               value.4 = 0;
-               value.5 = 0;
-               value.6 = 255;
-               value.7 = 0;
-               value.8 = 0;
-               value.9 = 0;
-               value.10 = 0;
-               value.11 = 255;
-       }
-       # send routing must be changed to 6 (center) and 7 (LFE)
-       open_control_six.2 {
-               iface = MIXER;
-               name = 'EMU10K1 PCM Send Routing';
-               index = subdevice2;
-               lock = true;
-               value.4 = 6;
-               value.5 = 7;
-               value.6 = 0;
-               value.7 = 1;
-               value.8 = 6;
-               value.9 = 7;
-               value.10 = 0;
-               value.11 = 1;
-       }
-}