mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
Added support for async. Added error callback (and begun to use it). First implementation of pcm_share
This commit is contained in:
parent
d07934a537
commit
dcc88ffaa7
20 changed files with 1363 additions and 32 deletions
|
|
@ -353,6 +353,9 @@ int pcm_shm_cmd(client_t *client)
|
|||
ctrl->cmd = 0;
|
||||
pcm = client->device.pcm.handle;
|
||||
switch (cmd) {
|
||||
case SND_PCM_IOCTL_ASYNC:
|
||||
ctrl->result = snd_pcm_async(pcm, ctrl->u.async.sig, ctrl->u.async.pid);
|
||||
break;
|
||||
case SND_PCM_IOCTL_INFO:
|
||||
ctrl->result = snd_pcm_info(pcm, &ctrl->u.info);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -26,14 +26,19 @@
|
|||
#define SND_PCM_IOCTL_MUNMAP_DATA _IO ('A', 0xf4)
|
||||
#define SND_PCM_IOCTL_MUNMAP_CONTROL _IO ('A', 0xf5)
|
||||
#define SND_PCM_IOCTL_MUNMAP_STATUS _IO ('A', 0xf6)
|
||||
#define SND_PCM_IOCTL_MMAP_FORWARD _IOW('A', 0xf7, size_t)
|
||||
#define SND_PCM_IOCTL_MMAP_FORWARD _IO ('A', 0xf7)
|
||||
#define SND_PCM_IOCTL_AVAIL_UPDATE _IO ('A', 0xf8)
|
||||
#define SND_PCM_IOCTL_CLOSE _IO ('A', 0xf9)
|
||||
#define SND_PCM_IOCTL_ASYNC _IO ('A', 0xf9)
|
||||
#define SND_PCM_IOCTL_CLOSE _IO ('A', 0xfa)
|
||||
|
||||
typedef struct {
|
||||
long result;
|
||||
int cmd;
|
||||
union {
|
||||
struct {
|
||||
int sig;
|
||||
pid_t pid;
|
||||
} async;
|
||||
snd_pcm_info_t info;
|
||||
snd_pcm_params_t params;
|
||||
snd_pcm_params_info_t params_info;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
****************************************************************************/
|
||||
|
||||
#define SND_PCM_NONBLOCK 0x0001
|
||||
#define SND_PCM_ASYNC 0x0002
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -117,6 +118,7 @@ typedef enum {
|
|||
SND_PCM_TYPE_LBSERVER,
|
||||
} snd_pcm_type_t;
|
||||
|
||||
extern void (*snd_pcm_error)(const char *file, int line, const char *function, const char *fmt, ...);
|
||||
|
||||
int snd_pcm_open(snd_pcm_t **handle, char *name,
|
||||
int stream, int mode);
|
||||
|
|
@ -136,6 +138,7 @@ snd_pcm_type_t snd_pcm_type(snd_pcm_t *pcm);
|
|||
int snd_pcm_close(snd_pcm_t *pcm);
|
||||
int snd_pcm_poll_descriptor(snd_pcm_t *pcm);
|
||||
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_pcm_info(snd_pcm_t *pcm, snd_pcm_info_t *info);
|
||||
int snd_pcm_params_info(snd_pcm_t *pcm, snd_pcm_params_info_t *info);
|
||||
int snd_pcm_params(snd_pcm_t *pcm, snd_pcm_params_t *params);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ EXTRA_LTLIBRARIES = libpcm.la
|
|||
|
||||
libpcm_la_SOURCES = pcm.c pcm_hw.c pcm_plugin.c pcm_linear.c pcm_route.c \
|
||||
pcm_mulaw.c pcm_alaw.c pcm_adpcm.c pcm_rate.c pcm_plug.c \
|
||||
pcm_misc.c pcm_mmap.c pcm_multi.c pcm_client.c pcm_file.c
|
||||
pcm_misc.c pcm_mmap.c pcm_multi.c pcm_client.c pcm_file.c \
|
||||
pcm_share.c
|
||||
noinst_HEADERS = pcm_local.h pcm_plugin.h
|
||||
|
||||
all: libpcm.la
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/poll.h>
|
||||
#include <dlfcn.h>
|
||||
|
|
@ -83,7 +84,7 @@ int snd_pcm_nonblock(snd_pcm_t *pcm, int nonblock)
|
|||
{
|
||||
int err;
|
||||
assert(pcm);
|
||||
if ((err = pcm->ops->nonblock(pcm->fast_op_arg, nonblock)) < 0)
|
||||
if ((err = pcm->ops->nonblock(pcm->op_arg, nonblock)) < 0)
|
||||
return err;
|
||||
if (nonblock)
|
||||
pcm->mode |= SND_PCM_NONBLOCK;
|
||||
|
|
@ -92,6 +93,12 @@ int snd_pcm_nonblock(snd_pcm_t *pcm, int nonblock)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int snd_pcm_async(snd_pcm_t *pcm, int sig, pid_t pid)
|
||||
{
|
||||
assert(pcm);
|
||||
return pcm->ops->async(pcm->op_arg, sig, pid);
|
||||
}
|
||||
|
||||
int snd_pcm_info(snd_pcm_t *pcm, snd_pcm_info_t *info)
|
||||
{
|
||||
assert(pcm && info);
|
||||
|
|
@ -1037,3 +1044,14 @@ ssize_t snd_pcm_write_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *areas,
|
|||
return err;
|
||||
}
|
||||
|
||||
void snd_pcm_error_default(const char *file, int line, const char *function, const char *fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, fmt);
|
||||
fprintf(stderr, "ALSA PCM lib %s:%i:(%s) ", file, line, function);
|
||||
vfprintf(stderr, fmt, arg);
|
||||
putc('\n', stderr);
|
||||
va_end(arg);
|
||||
}
|
||||
|
||||
void (*snd_pcm_error)(const char *file, int line, const char *function, const char *fmt, ...) = snd_pcm_error_default;
|
||||
|
|
|
|||
|
|
@ -544,6 +544,7 @@ struct snd_pcm_ops snd_pcm_adpcm_ops = {
|
|||
channel_setup: snd_pcm_plugin_channel_setup,
|
||||
dump: snd_pcm_adpcm_dump,
|
||||
nonblock: snd_pcm_plugin_nonblock,
|
||||
async: snd_pcm_plugin_async,
|
||||
mmap_status: snd_pcm_plugin_mmap_status,
|
||||
mmap_control: snd_pcm_plugin_mmap_control,
|
||||
mmap_data: snd_pcm_plugin_mmap_data,
|
||||
|
|
|
|||
|
|
@ -412,6 +412,7 @@ struct snd_pcm_ops snd_pcm_alaw_ops = {
|
|||
channel_setup: snd_pcm_plugin_channel_setup,
|
||||
dump: snd_pcm_alaw_dump,
|
||||
nonblock: snd_pcm_plugin_nonblock,
|
||||
async: snd_pcm_plugin_async,
|
||||
mmap_status: snd_pcm_plugin_mmap_status,
|
||||
mmap_control: snd_pcm_plugin_mmap_control,
|
||||
mmap_data: snd_pcm_plugin_mmap_data,
|
||||
|
|
|
|||
|
|
@ -175,6 +175,22 @@ static int snd_pcm_client_shm_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonb
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int snd_pcm_client_async(snd_pcm_t *pcm, int sig, pid_t pid)
|
||||
{
|
||||
snd_pcm_client_t *client = pcm->private;
|
||||
snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
|
||||
int err;
|
||||
ctrl->cmd = SND_PCM_IOCTL_ASYNC;
|
||||
ctrl->u.async.sig = sig;
|
||||
if (pid == 0)
|
||||
pid = getpid();
|
||||
ctrl->u.async.pid = pid;
|
||||
err = snd_pcm_client_shm_action(pcm);
|
||||
if (err < 0)
|
||||
return err;
|
||||
return ctrl->result;
|
||||
}
|
||||
|
||||
static int snd_pcm_client_shm_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
|
||||
{
|
||||
snd_pcm_client_t *client = pcm->private;
|
||||
|
|
@ -550,6 +566,7 @@ struct snd_pcm_ops snd_pcm_client_ops = {
|
|||
channel_setup: snd_pcm_client_shm_channel_setup,
|
||||
dump: snd_pcm_client_dump,
|
||||
nonblock: snd_pcm_client_shm_nonblock,
|
||||
async: snd_pcm_client_async,
|
||||
mmap_status: snd_pcm_client_shm_mmap_status,
|
||||
mmap_control: snd_pcm_client_shm_mmap_control,
|
||||
mmap_data: snd_pcm_client_shm_mmap_data,
|
||||
|
|
|
|||
|
|
@ -50,6 +50,12 @@ static int snd_pcm_file_nonblock(snd_pcm_t *pcm, int nonblock)
|
|||
return snd_pcm_nonblock(file->slave, nonblock);
|
||||
}
|
||||
|
||||
static int snd_pcm_file_async(snd_pcm_t *pcm, int sig, pid_t pid)
|
||||
{
|
||||
snd_pcm_file_t *file = pcm->private;
|
||||
return snd_pcm_async(file->slave, sig, pid);
|
||||
}
|
||||
|
||||
static int snd_pcm_file_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
|
||||
{
|
||||
snd_pcm_file_t *file = pcm->private;
|
||||
|
|
@ -342,6 +348,7 @@ struct snd_pcm_ops snd_pcm_file_ops = {
|
|||
channel_setup: snd_pcm_file_channel_setup,
|
||||
dump: snd_pcm_file_dump,
|
||||
nonblock: snd_pcm_file_nonblock,
|
||||
async: snd_pcm_file_async,
|
||||
mmap_status: snd_pcm_file_mmap_status,
|
||||
mmap_control: snd_pcm_file_mmap_control,
|
||||
mmap_data: snd_pcm_file_mmap_data,
|
||||
|
|
|
|||
143
src/pcm/pcm_hw.c
143
src/pcm/pcm_hw.c
|
|
@ -22,6 +22,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
|
@ -29,6 +30,10 @@
|
|||
#include <sys/mman.h>
|
||||
#include "pcm_local.h"
|
||||
|
||||
#ifndef F_SETSIG
|
||||
#define F_SETSIG 10
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
int card, device, subdevice;
|
||||
|
|
@ -44,9 +49,10 @@ static int snd_pcm_hw_close(snd_pcm_t *pcm)
|
|||
snd_pcm_hw_t *hw = pcm->private;
|
||||
int fd = hw->fd;
|
||||
free(hw);
|
||||
if (fd >= 0)
|
||||
if (close(fd))
|
||||
return -errno;
|
||||
if (close(fd)) {
|
||||
ERR("close failed\n");
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -56,14 +62,53 @@ static int snd_pcm_hw_nonblock(snd_pcm_t *pcm, int nonblock)
|
|||
snd_pcm_hw_t *hw = pcm->private;
|
||||
int fd = hw->fd;
|
||||
|
||||
if ((flags = fcntl(fd, F_GETFL)) < 0)
|
||||
if ((flags = fcntl(fd, F_GETFL)) < 0) {
|
||||
ERR("F_GETFL failed");
|
||||
return -errno;
|
||||
}
|
||||
if (nonblock)
|
||||
flags |= O_NONBLOCK;
|
||||
else
|
||||
flags &= ~O_NONBLOCK;
|
||||
if (fcntl(fd, F_SETFL, flags) < 0)
|
||||
if (fcntl(fd, F_SETFL, flags) < 0) {
|
||||
ERR("F_SETFL for O_NONBLOCK failed");
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_pcm_hw_async(snd_pcm_t *pcm, int sig, pid_t pid)
|
||||
{
|
||||
long flags;
|
||||
snd_pcm_hw_t *hw = pcm->private;
|
||||
int fd = hw->fd;
|
||||
|
||||
if ((flags = fcntl(fd, F_GETFL)) < 0) {
|
||||
ERR("F_GETFL failed");
|
||||
return -errno;
|
||||
}
|
||||
if (sig >= 0)
|
||||
flags |= O_ASYNC;
|
||||
else
|
||||
flags &= ~O_ASYNC;
|
||||
if (fcntl(fd, F_SETFL, flags) < 0) {
|
||||
ERR("F_SETFL for O_ASYNC failed");
|
||||
return -errno;
|
||||
}
|
||||
if (sig < 0)
|
||||
return 0;
|
||||
if (sig == 0)
|
||||
sig = SIGIO;
|
||||
if (fcntl(fd, F_SETSIG, sig) < 0) {
|
||||
ERR("F_SETSIG failed");
|
||||
return -errno;
|
||||
}
|
||||
if (pid == 0)
|
||||
pid = getpid();
|
||||
if (fcntl(fd, F_SETOWN, pid) < 0) {
|
||||
ERR("F_SETOWN failed");
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -71,8 +116,10 @@ static int snd_pcm_hw_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
|
|||
{
|
||||
snd_pcm_hw_t *hw = pcm->private;
|
||||
int fd = hw->fd;
|
||||
if (ioctl(fd, SND_PCM_IOCTL_INFO, info) < 0)
|
||||
if (ioctl(fd, SND_PCM_IOCTL_INFO, info) < 0) {
|
||||
ERR("SND_PCM_IOCTL_INFO failed");
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -80,8 +127,10 @@ static int snd_pcm_hw_params_info(snd_pcm_t *pcm, snd_pcm_params_info_t * info)
|
|||
{
|
||||
snd_pcm_hw_t *hw = pcm->private;
|
||||
int fd = hw->fd;
|
||||
if (ioctl(fd, SND_PCM_IOCTL_PARAMS_INFO, info) < 0)
|
||||
if (ioctl(fd, SND_PCM_IOCTL_PARAMS_INFO, info) < 0) {
|
||||
ERR("SND_PCM_IOCTL_PARAMS_INFO failed");
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -89,8 +138,10 @@ static int snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_params_t * params)
|
|||
{
|
||||
snd_pcm_hw_t *hw = pcm->private;
|
||||
int fd = hw->fd;
|
||||
if (ioctl(fd, SND_PCM_IOCTL_PARAMS, params) < 0)
|
||||
if (ioctl(fd, SND_PCM_IOCTL_PARAMS, params) < 0) {
|
||||
ERR("SND_PCM_IOCTL_PARAMS failed");
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -98,8 +149,10 @@ static int snd_pcm_hw_setup(snd_pcm_t *pcm, snd_pcm_setup_t * setup)
|
|||
{
|
||||
snd_pcm_hw_t *hw = pcm->private;
|
||||
int fd = hw->fd;
|
||||
if (ioctl(fd, SND_PCM_IOCTL_SETUP, setup) < 0)
|
||||
if (ioctl(fd, SND_PCM_IOCTL_SETUP, setup) < 0) {
|
||||
ERR("SND_PCM_IOCTL_SETUP failed");
|
||||
return -errno;
|
||||
}
|
||||
if (setup->mmap_shape == SND_PCM_MMAP_UNSPECIFIED) {
|
||||
if (setup->xfer_mode == SND_PCM_XFER_INTERLEAVED)
|
||||
setup->mmap_shape = SND_PCM_MMAP_INTERLEAVED;
|
||||
|
|
@ -115,8 +168,10 @@ static int snd_pcm_hw_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info
|
|||
{
|
||||
snd_pcm_hw_t *hw = pcm->private;
|
||||
int fd = hw->fd;
|
||||
if (ioctl(fd, SND_PCM_IOCTL_CHANNEL_INFO, info) < 0)
|
||||
if (ioctl(fd, SND_PCM_IOCTL_CHANNEL_INFO, info) < 0) {
|
||||
ERR("SND_PCM_IOCTL_CHANNEL_INFO failed");
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -124,8 +179,10 @@ static int snd_pcm_hw_channel_params(snd_pcm_t *pcm, snd_pcm_channel_params_t *
|
|||
{
|
||||
snd_pcm_hw_t *hw = pcm->private;
|
||||
int fd = hw->fd;
|
||||
if (ioctl(fd, SND_PCM_IOCTL_CHANNEL_PARAMS, params) < 0)
|
||||
if (ioctl(fd, SND_PCM_IOCTL_CHANNEL_PARAMS, params) < 0) {
|
||||
ERR("SND_PCM_IOCTL_CHANNEL_PARAMS failed");
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -133,8 +190,10 @@ static int snd_pcm_hw_channel_setup(snd_pcm_t *pcm, snd_pcm_channel_setup_t * se
|
|||
{
|
||||
snd_pcm_hw_t *hw = pcm->private;
|
||||
int fd = hw->fd;
|
||||
if (ioctl(fd, SND_PCM_IOCTL_CHANNEL_SETUP, setup) < 0)
|
||||
if (ioctl(fd, SND_PCM_IOCTL_CHANNEL_SETUP, setup) < 0) {
|
||||
ERR("SND_PCM_IOCTL_CHANNEL_SETUP failed");
|
||||
return -errno;
|
||||
}
|
||||
if (hw->mmap_emulation) {
|
||||
if (pcm->setup.mmap_shape == SND_PCM_MMAP_INTERLEAVED) {
|
||||
setup->running_area.addr = pcm->mmap_data;
|
||||
|
|
@ -157,8 +216,10 @@ static int snd_pcm_hw_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
|
|||
{
|
||||
snd_pcm_hw_t *hw = pcm->private;
|
||||
int fd = hw->fd;
|
||||
if (ioctl(fd, SND_PCM_IOCTL_STATUS, status) < 0)
|
||||
if (ioctl(fd, SND_PCM_IOCTL_STATUS, status) < 0) {
|
||||
ERR("SND_PCM_IOCTL_STATUS failed");
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -171,8 +232,10 @@ static int snd_pcm_hw_delay(snd_pcm_t *pcm, ssize_t *delayp)
|
|||
{
|
||||
snd_pcm_hw_t *hw = pcm->private;
|
||||
int fd = hw->fd;
|
||||
if (ioctl(fd, SND_PCM_IOCTL_DELAY, delayp) < 0)
|
||||
if (ioctl(fd, SND_PCM_IOCTL_DELAY, delayp) < 0) {
|
||||
ERR("SND_PCM_IOCTL_DELAY failed");
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -180,8 +243,10 @@ static int snd_pcm_hw_prepare(snd_pcm_t *pcm)
|
|||
{
|
||||
snd_pcm_hw_t *hw = pcm->private;
|
||||
int fd = hw->fd;
|
||||
if (ioctl(fd, SND_PCM_IOCTL_PREPARE) < 0)
|
||||
if (ioctl(fd, SND_PCM_IOCTL_PREPARE) < 0) {
|
||||
ERR("SND_PCM_IOCTL_PREPARE failed");
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -189,8 +254,10 @@ static int snd_pcm_hw_start(snd_pcm_t *pcm)
|
|||
{
|
||||
snd_pcm_hw_t *hw = pcm->private;
|
||||
int fd = hw->fd;
|
||||
if (ioctl(fd, SND_PCM_IOCTL_START) < 0)
|
||||
if (ioctl(fd, SND_PCM_IOCTL_START) < 0) {
|
||||
ERR("SND_PCM_IOCTL_START failed");
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -198,8 +265,10 @@ static int snd_pcm_hw_drop(snd_pcm_t *pcm)
|
|||
{
|
||||
snd_pcm_hw_t *hw = pcm->private;
|
||||
int fd = hw->fd;
|
||||
if (ioctl(fd, SND_PCM_IOCTL_DROP) < 0)
|
||||
if (ioctl(fd, SND_PCM_IOCTL_DROP) < 0) {
|
||||
ERR("SND_PCM_IOCTL_DROP failed");
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -207,8 +276,10 @@ static int snd_pcm_hw_drain(snd_pcm_t *pcm)
|
|||
{
|
||||
snd_pcm_hw_t *hw = pcm->private;
|
||||
int fd = hw->fd;
|
||||
if (ioctl(fd, SND_PCM_IOCTL_DRAIN) < 0)
|
||||
if (ioctl(fd, SND_PCM_IOCTL_DRAIN) < 0) {
|
||||
ERR("SND_PCM_IOCTL_DRAIN failed");
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -216,8 +287,10 @@ static int snd_pcm_hw_pause(snd_pcm_t *pcm, int enable)
|
|||
{
|
||||
snd_pcm_hw_t *hw = pcm->private;
|
||||
int fd = hw->fd;
|
||||
if (ioctl(fd, SND_PCM_IOCTL_PAUSE, enable) < 0)
|
||||
if (ioctl(fd, SND_PCM_IOCTL_PAUSE, enable) < 0) {
|
||||
ERR("SND_PCM_IOCTL_PAUSE failed");
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -301,8 +374,10 @@ static int snd_pcm_hw_mmap_status(snd_pcm_t *pcm)
|
|||
void *ptr;
|
||||
ptr = mmap(NULL, sizeof(snd_pcm_mmap_status_t), PROT_READ, MAP_FILE|MAP_SHARED,
|
||||
hw->fd, SND_PCM_MMAP_OFFSET_STATUS);
|
||||
if (ptr == MAP_FAILED || ptr == NULL)
|
||||
if (ptr == MAP_FAILED || ptr == NULL) {
|
||||
ERR("status mmap failed");
|
||||
return -errno;
|
||||
}
|
||||
pcm->mmap_status = ptr;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -313,8 +388,10 @@ static int snd_pcm_hw_mmap_control(snd_pcm_t *pcm)
|
|||
void *ptr;
|
||||
ptr = mmap(NULL, sizeof(snd_pcm_mmap_control_t), PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,
|
||||
hw->fd, SND_PCM_MMAP_OFFSET_CONTROL);
|
||||
if (ptr == MAP_FAILED || ptr == NULL)
|
||||
if (ptr == MAP_FAILED || ptr == NULL) {
|
||||
ERR("control mmap failed");
|
||||
return -errno;
|
||||
}
|
||||
pcm->mmap_control = ptr;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -333,8 +410,10 @@ static int snd_pcm_hw_mmap_data(snd_pcm_t *pcm)
|
|||
ptr = mmap(NULL, pcm->setup.mmap_bytes,
|
||||
prot, MAP_FILE|MAP_SHARED,
|
||||
hw->fd, SND_PCM_MMAP_OFFSET_DATA);
|
||||
if (ptr == MAP_FAILED || ptr == NULL)
|
||||
if (ptr == MAP_FAILED || ptr == NULL) {
|
||||
ERR("data mmap failed");
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
pcm->mmap_data = ptr;
|
||||
return 0;
|
||||
|
|
@ -342,15 +421,19 @@ static int snd_pcm_hw_mmap_data(snd_pcm_t *pcm)
|
|||
|
||||
static int snd_pcm_hw_munmap_status(snd_pcm_t *pcm)
|
||||
{
|
||||
if (munmap((void*)pcm->mmap_status, sizeof(*pcm->mmap_status)) < 0)
|
||||
if (munmap((void*)pcm->mmap_status, sizeof(*pcm->mmap_status)) < 0) {
|
||||
ERR("status munmap failed");
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_pcm_hw_munmap_control(snd_pcm_t *pcm)
|
||||
{
|
||||
if (munmap(pcm->mmap_control, sizeof(*pcm->mmap_control)) < 0)
|
||||
if (munmap(pcm->mmap_control, sizeof(*pcm->mmap_control)) < 0) {
|
||||
ERR("control munmap failed");
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -360,8 +443,10 @@ static int snd_pcm_hw_munmap_data(snd_pcm_t *pcm)
|
|||
if (hw->mmap_emulation)
|
||||
free(pcm->mmap_data);
|
||||
else
|
||||
if (munmap(pcm->mmap_data, pcm->setup.mmap_bytes) < 0)
|
||||
if (munmap(pcm->mmap_data, pcm->setup.mmap_bytes) < 0) {
|
||||
ERR("data munmap failed");
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -377,15 +462,14 @@ static ssize_t snd_pcm_hw_mmap_forward(snd_pcm_t *pcm, size_t size)
|
|||
static ssize_t snd_pcm_hw_avail_update(snd_pcm_t *pcm)
|
||||
{
|
||||
snd_pcm_hw_t *hw = pcm->private;
|
||||
int fd = hw->fd;
|
||||
size_t avail;
|
||||
ssize_t err;
|
||||
if (pcm->setup.ready_mode == SND_PCM_READY_ASAP ||
|
||||
pcm->setup.xrun_mode == SND_PCM_XRUN_ASAP) {
|
||||
ssize_t d;
|
||||
int err = ioctl(fd, SND_PCM_IOCTL_DELAY, &d);
|
||||
int err = snd_pcm_hw_delay(pcm, &d);
|
||||
if (err < 0)
|
||||
return -errno;
|
||||
return err;
|
||||
}
|
||||
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
|
||||
avail = snd_pcm_mmap_playback_avail(pcm);
|
||||
|
|
@ -441,6 +525,7 @@ struct snd_pcm_ops snd_pcm_hw_ops = {
|
|||
channel_setup: snd_pcm_hw_channel_setup,
|
||||
dump: snd_pcm_hw_dump,
|
||||
nonblock: snd_pcm_hw_nonblock,
|
||||
async: snd_pcm_hw_async,
|
||||
mmap_status: snd_pcm_hw_mmap_status,
|
||||
mmap_control: snd_pcm_hw_mmap_control,
|
||||
mmap_data: snd_pcm_hw_mmap_data,
|
||||
|
|
@ -509,6 +594,8 @@ int snd_pcm_hw_open_subdevice(snd_pcm_t **handlep, int card, int device, int sub
|
|||
fmode = O_RDWR;
|
||||
if (mode & SND_PCM_NONBLOCK)
|
||||
fmode |= O_NONBLOCK;
|
||||
if (mode & SND_PCM_ASYNC)
|
||||
fmode |= O_ASYNC;
|
||||
if ((fd = open(filename, fmode)) < 0) {
|
||||
ret = -errno;
|
||||
goto __end;
|
||||
|
|
|
|||
|
|
@ -255,6 +255,7 @@ struct snd_pcm_ops snd_pcm_linear_ops = {
|
|||
channel_setup: snd_pcm_plugin_channel_setup,
|
||||
dump: snd_pcm_linear_dump,
|
||||
nonblock: snd_pcm_plugin_nonblock,
|
||||
async: snd_pcm_plugin_async,
|
||||
mmap_status: snd_pcm_plugin_mmap_status,
|
||||
mmap_control: snd_pcm_plugin_mmap_control,
|
||||
mmap_data: snd_pcm_plugin_mmap_data,
|
||||
|
|
|
|||
|
|
@ -26,9 +26,16 @@
|
|||
#include <errno.h>
|
||||
#include "asoundlib.h"
|
||||
|
||||
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
|
||||
#define ERR(...) snd_pcm_error(__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
|
||||
#else
|
||||
#define ERR(args...) snd_pcm_error(__FILE__, __LINE__, __FUNCTION__, ##args)
|
||||
#endif
|
||||
|
||||
struct snd_pcm_ops {
|
||||
int (*close)(snd_pcm_t *pcm);
|
||||
int (*nonblock)(snd_pcm_t *pcm, int nonblock);
|
||||
int (*async)(snd_pcm_t *pcm, int sig, pid_t pid);
|
||||
int (*info)(snd_pcm_t *pcm, snd_pcm_info_t *info);
|
||||
int (*params_info)(snd_pcm_t *pcm, snd_pcm_params_info_t *info);
|
||||
int (*params)(snd_pcm_t *pcm, snd_pcm_params_t *params);
|
||||
|
|
|
|||
|
|
@ -429,6 +429,7 @@ struct snd_pcm_ops snd_pcm_mulaw_ops = {
|
|||
channel_setup: snd_pcm_plugin_channel_setup,
|
||||
dump: snd_pcm_mulaw_dump,
|
||||
nonblock: snd_pcm_plugin_nonblock,
|
||||
async: snd_pcm_plugin_async,
|
||||
mmap_status: snd_pcm_plugin_mmap_status,
|
||||
mmap_control: snd_pcm_plugin_mmap_control,
|
||||
mmap_data: snd_pcm_plugin_mmap_data,
|
||||
|
|
|
|||
|
|
@ -72,6 +72,13 @@ static int snd_pcm_multi_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int snd_pcm_multi_async(snd_pcm_t *pcm, int sig, pid_t pid)
|
||||
{
|
||||
snd_pcm_multi_t *multi = pcm->private;
|
||||
snd_pcm_t *slave_0 = multi->slaves[0].pcm;
|
||||
return snd_pcm_async(slave_0, sig, pid);
|
||||
}
|
||||
|
||||
static int snd_pcm_multi_info(snd_pcm_t *pcm, snd_pcm_info_t *info)
|
||||
{
|
||||
snd_pcm_multi_t *multi = pcm->private;
|
||||
|
|
@ -504,6 +511,7 @@ struct snd_pcm_ops snd_pcm_multi_ops = {
|
|||
channel_setup: snd_pcm_multi_channel_setup,
|
||||
dump: snd_pcm_multi_dump,
|
||||
nonblock: snd_pcm_multi_nonblock,
|
||||
async: snd_pcm_multi_async,
|
||||
mmap_status: snd_pcm_multi_mmap_status,
|
||||
mmap_control: snd_pcm_multi_mmap_control,
|
||||
mmap_data: snd_pcm_multi_mmap_data,
|
||||
|
|
|
|||
|
|
@ -189,6 +189,12 @@ static int snd_pcm_plug_nonblock(snd_pcm_t *pcm, int nonblock)
|
|||
return snd_pcm_nonblock(plug->slave, nonblock);
|
||||
}
|
||||
|
||||
static int snd_pcm_plug_async(snd_pcm_t *pcm, int sig, pid_t pid)
|
||||
{
|
||||
snd_pcm_plug_t *plug = pcm->private;
|
||||
return snd_pcm_async(plug->slave, sig, pid);
|
||||
}
|
||||
|
||||
static int snd_pcm_plug_info(snd_pcm_t *pcm, snd_pcm_info_t *info)
|
||||
{
|
||||
snd_pcm_plug_t *plug = pcm->private;
|
||||
|
|
@ -658,6 +664,7 @@ struct snd_pcm_ops snd_pcm_plug_ops = {
|
|||
channel_setup: snd_pcm_plug_channel_setup,
|
||||
dump: snd_pcm_plug_dump,
|
||||
nonblock: snd_pcm_plug_nonblock,
|
||||
async: snd_pcm_plug_async,
|
||||
mmap_status: snd_pcm_plug_mmap_status,
|
||||
mmap_control: snd_pcm_plug_mmap_control,
|
||||
mmap_data: snd_pcm_plug_mmap_data,
|
||||
|
|
|
|||
|
|
@ -39,6 +39,12 @@ int snd_pcm_plugin_nonblock(snd_pcm_t *pcm, int nonblock)
|
|||
return snd_pcm_nonblock(plugin->slave, nonblock);
|
||||
}
|
||||
|
||||
int snd_pcm_plugin_async(snd_pcm_t *pcm, int sig, pid_t pid)
|
||||
{
|
||||
snd_pcm_plugin_t *plugin = pcm->private;
|
||||
return snd_pcm_async(plugin->slave, sig, pid);
|
||||
}
|
||||
|
||||
int snd_pcm_plugin_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
|
||||
{
|
||||
snd_pcm_plugin_t *plugin = pcm->private;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ typedef struct {
|
|||
|
||||
int snd_pcm_plugin_close(snd_pcm_t *pcm);
|
||||
int snd_pcm_plugin_nonblock(snd_pcm_t *pcm, int nonblock);
|
||||
int snd_pcm_plugin_async(snd_pcm_t *pcm, int sig, pid_t pid);
|
||||
int snd_pcm_plugin_info(snd_pcm_t *pcm, snd_pcm_info_t * info);
|
||||
int snd_pcm_plugin_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info);
|
||||
int snd_pcm_plugin_channel_params(snd_pcm_t *pcm, snd_pcm_channel_params_t * params);
|
||||
|
|
|
|||
|
|
@ -576,6 +576,7 @@ struct snd_pcm_ops snd_pcm_rate_ops = {
|
|||
channel_setup: snd_pcm_plugin_channel_setup,
|
||||
dump: snd_pcm_rate_dump,
|
||||
nonblock: snd_pcm_plugin_nonblock,
|
||||
async: snd_pcm_plugin_async,
|
||||
mmap_status: snd_pcm_plugin_mmap_status,
|
||||
mmap_control: snd_pcm_plugin_mmap_control,
|
||||
mmap_data: snd_pcm_plugin_mmap_data,
|
||||
|
|
|
|||
|
|
@ -695,6 +695,7 @@ struct snd_pcm_ops snd_pcm_route_ops = {
|
|||
channel_setup: snd_pcm_route_channel_setup,
|
||||
dump: snd_pcm_route_dump,
|
||||
nonblock: snd_pcm_plugin_nonblock,
|
||||
async: snd_pcm_plugin_async,
|
||||
mmap_status: snd_pcm_plugin_mmap_status,
|
||||
mmap_control: snd_pcm_plugin_mmap_control,
|
||||
mmap_data: snd_pcm_plugin_mmap_data,
|
||||
|
|
|
|||
1155
src/pcm/pcm_share.c
Normal file
1155
src/pcm/pcm_share.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue