mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	New async notification API. Removed obsolete surround. Cleaning
This commit is contained in:
		
							parent
							
								
									57469ec597
								
							
						
					
					
						commit
						157f47aedd
					
				
					 35 changed files with 436 additions and 1581 deletions
				
			
		| 
						 | 
				
			
			@ -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 \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										114
									
								
								src/async.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								src/async.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +25,6 @@
 | 
			
		|||
#include <sys/stat.h>
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
#include "local.h"
 | 
			
		||||
#include "list.h"
 | 
			
		||||
 | 
			
		||||
#ifndef DOC_HIDDEN
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,7 +34,6 @@
 | 
			
		|||
#include <unistd.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "local.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,6 @@
 | 
			
		|||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "local.h"
 | 
			
		||||
 | 
			
		||||
typedef struct _bag1 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1090
									
								
								src/pcm/pcm_surr.c
									
										
									
									
									
								
							
							
						
						
									
										1090
									
								
								src/pcm/pcm_surr.c
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -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;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue