From 157f47aeddea28c64df2d4fa3be587813d42f4e2 Mon Sep 17 00:00:00 2001 From: Abramo Bagnara Date: Wed, 20 Jun 2001 20:52:12 +0000 Subject: [PATCH] New async notification API. Removed obsolete surround. Cleaning --- aserver/aserver.c | 53 ++- include/control.h | 5 +- include/global.h | 11 + include/local.h | 18 + include/pcm.h | 4 +- src/Makefile.am | 2 +- src/async.c | 114 +++++ src/conf.c | 1 - src/control/control.c | 89 +++- src/control/control_hw.c | 24 +- src/control/control_local.h | 9 +- src/control/control_shm.c | 23 +- src/control/setup.c | 1 - src/mixer/mixer_local.h | 1 - src/pcm/Makefile.am | 2 - src/pcm/pcm.c | 89 +++- src/pcm/pcm_adpcm.c | 14 +- src/pcm/pcm_alaw.c | 14 +- src/pcm/pcm_copy.c | 14 +- src/pcm/pcm_file.c | 14 +- src/pcm/pcm_hooks.c | 14 +- src/pcm/pcm_hw.c | 29 +- src/pcm/pcm_linear.c | 14 +- src/pcm/pcm_local.h | 19 +- src/pcm/pcm_meter.c | 15 +- src/pcm/pcm_mulaw.c | 14 +- src/pcm/pcm_multi.c | 15 +- src/pcm/pcm_null.c | 14 +- src/pcm/pcm_plug.c | 13 +- src/pcm/pcm_rate.c | 14 +- src/pcm/pcm_route.c | 13 +- src/pcm/pcm_share.c | 22 +- src/pcm/pcm_shm.c | 15 +- src/pcm/pcm_surr.c | 1090 ------------------------------------------- src/pcm/surround.conf | 214 --------- 35 files changed, 436 insertions(+), 1581 deletions(-) create mode 100644 src/async.c delete mode 100644 src/pcm/pcm_surr.c delete mode 100644 src/pcm/surround.conf diff --git a/aserver/aserver.c b/aserver/aserver.c index 68fdf5d1..9ba0eea8 100644 --- a/aserver/aserver.c +++ b/aserver/aserver.c @@ -31,9 +31,9 @@ #include #include #include +#include #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); diff --git a/include/control.h b/include/control.h index 8967f13b..94bc13cb 100644 --- a/include/control.h +++ b/include/control.h @@ -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); diff --git a/include/global.h b/include/global.h index 6742a7b7..9db9aff0 100644 --- a/include/global.h +++ b/include/global.h @@ -18,3 +18,14 @@ /** \} */ +/** 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); diff --git a/include/local.h b/include/local.h index 03d30a76..e15018ae 100644 --- a/include/local.h +++ b/include/local.h @@ -49,6 +49,24 @@ #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, diff --git a/include/pcm.h b/include/pcm.h index 6994b1a9..6d670fa7 100644 --- a/include/pcm.h +++ b/include/pcm.h @@ -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); diff --git a/src/Makefile.am b/src/Makefile.am index f52db05c..a2f66141 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 index 00000000..180866b5 --- /dev/null +++ b/src/async.c @@ -0,0 +1,114 @@ +/* + * Async notification helpers + * Copyright (c) 2001 by Abramo Bagnara + * + * 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 + +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; +} + diff --git a/src/conf.c b/src/conf.c index f68135e8..459bd4a8 100644 --- a/src/conf.c +++ b/src/conf.c @@ -25,7 +25,6 @@ #include #include #include "local.h" -#include "list.h" #ifndef DOC_HIDDEN diff --git a/src/control/control.c b/src/control/control.c index 6c5eb7ce..8a2f8ec2 100644 --- a/src/control/control.c +++ b/src/control/control.c @@ -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 diff --git a/src/control/control_hw.c b/src/control/control_hw.c index b287e35f..694517f3 100644 --- a/src/control/control_hw.c +++ b/src/control/control_hw.c @@ -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; } diff --git a/src/control/control_local.h b/src/control/control_local.h index 01b8013a..b3522cff 100644 --- a/src/control/control_local.h +++ b/src/control/control_local.h @@ -20,13 +20,11 @@ */ #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); diff --git a/src/control/control_shm.c b/src/control/control_shm.c index 34262da4..f04834f6 100644 --- a/src/control/control_shm.c +++ b/src/control/control_shm.c @@ -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; diff --git a/src/control/setup.c b/src/control/setup.c index fac0828e..a2154aeb 100644 --- a/src/control/setup.c +++ b/src/control/setup.c @@ -34,7 +34,6 @@ #include #include #include -#include "list.h" #include "local.h" typedef struct { diff --git a/src/mixer/mixer_local.h b/src/mixer/mixer_local.h index 266b11fc..813f3963 100644 --- a/src/mixer/mixer_local.h +++ b/src/mixer/mixer_local.h @@ -20,7 +20,6 @@ * */ -#include "list.h" #include "local.h" typedef struct _bag1 { diff --git a/src/pcm/Makefile.am b/src/pcm/Makefile.am index 4944d5d4..90391d8d 100644 --- a/src/pcm/Makefile.am +++ b/src/pcm/Makefile.am @@ -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 diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index 93a71018..d5a88365 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -44,7 +44,6 @@ #include #include #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) diff --git a/src/pcm/pcm_adpcm.c b/src/pcm/pcm_adpcm.c index 304fcb97..f9baec0c 100644 --- a/src/pcm/pcm_adpcm.c +++ b/src/pcm/pcm_adpcm.c @@ -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; diff --git a/src/pcm/pcm_alaw.c b/src/pcm/pcm_alaw.c index 6ac4381f..04a886d2 100644 --- a/src/pcm/pcm_alaw.c +++ b/src/pcm/pcm_alaw.c @@ -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; diff --git a/src/pcm/pcm_copy.c b/src/pcm/pcm_copy.c index 35972dff..8c6b4863 100644 --- a/src/pcm/pcm_copy.c +++ b/src/pcm/pcm_copy.c @@ -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 = ©->plug.hw_ptr; diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c index c0f9d33e..66971124 100644 --- a/src/pcm/pcm_file.c +++ b/src/pcm/pcm_file.c @@ -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; diff --git a/src/pcm/pcm_hooks.c b/src/pcm/pcm_hooks.c index 58a94293..5d27a69e 100644 --- a/src/pcm/pcm_hooks.c +++ b/src/pcm/pcm_hooks.c @@ -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; diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c index c67fc236..07066ec8 100644 --- a/src/pcm/pcm_hw.c +++ b/src/pcm/pcm_hw.c @@ -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) diff --git a/src/pcm/pcm_linear.c b/src/pcm/pcm_linear.c index f5187fcd..f1b9c92f 100644 --- a/src/pcm/pcm_linear.c +++ b/src/pcm/pcm_linear.c @@ -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; diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index ee40f6b0..7956ffde 100644 --- a/src/pcm/pcm_local.h +++ b/src/pcm/pcm_local.h @@ -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); diff --git a/src/pcm/pcm_meter.c b/src/pcm/pcm_meter.c index f0e5f9b9..e5d7e35d 100644 --- a/src/pcm/pcm_meter.c +++ b/src/pcm/pcm_meter.c @@ -30,7 +30,6 @@ #include #include #include -#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; diff --git a/src/pcm/pcm_mulaw.c b/src/pcm/pcm_mulaw.c index 2b4884c5..19655948 100644 --- a/src/pcm/pcm_mulaw.c +++ b/src/pcm/pcm_mulaw.c @@ -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; diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c index b7fa6261..29da1e42 100644 --- a/src/pcm/pcm_multi.c +++ b/src/pcm/pcm_multi.c @@ -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; diff --git a/src/pcm/pcm_null.c b/src/pcm/pcm_null.c index 402ff9a7..f1425a85 100644 --- a/src/pcm/pcm_null.c +++ b/src/pcm/pcm_null.c @@ -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; diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c index 9426f04c..6d322977 100644 --- a/src/pcm/pcm_plug.c +++ b/src/pcm/pcm_plug.c @@ -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; diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c index 27a34abc..d720379e 100644 --- a/src/pcm/pcm_rate.c +++ b/src/pcm/pcm_rate.c @@ -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; diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c index abe1aabd..1d400c33 100644 --- a/src/pcm/pcm_route.c +++ b/src/pcm/pcm_route.c @@ -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; diff --git a/src/pcm/pcm_share.c b/src/pcm/pcm_share.c index 9d845762..e64e55a6 100644 --- a/src/pcm/pcm_share.c +++ b/src/pcm/pcm_share.c @@ -31,7 +31,6 @@ #include #include #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; diff --git a/src/pcm/pcm_shm.c b/src/pcm/pcm_shm.c index c59a81ef..062a5398 100644 --- a/src/pcm/pcm_shm.c +++ b/src/pcm/pcm_shm.c @@ -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 index b8b5bc2c..00000000 --- a/src/pcm/pcm_surr.c +++ /dev/null @@ -1,1090 +0,0 @@ -/* - * PCM - Surround plugin - * Copyright (c) 2001 by Jaroslav Kysela - * - * 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 -#include -#include -#include -#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 = ¶ms->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 = ¶ms->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 index 5a41539a..00000000 --- a/src/pcm/surround.conf +++ /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; - } -} -- 2.11.0