From 63f5a79562f8dfe7806f8877be796110141b2050 Mon Sep 17 00:00:00 2001 From: Abramo Bagnara Date: Sat, 8 Jan 2000 20:11:33 +0000 Subject: [PATCH] - splitted pcm channels in two different devices to handle mmap correctly - removed mmap control device - reordered pcm shared and not shared code - changed O_WRONLY oss pcm modifier in a more symmetric and elegant way - changed slightly control interface - added snd-debug-check - uniformed null pointer check - fixed a typo in linear plugin --- include/control.h | 11 +- include/pcm.h | 2 +- src/control/control.c | 84 ++++++----- src/pcm/pcm.c | 274 +++++++++++++++++++++--------------- src/pcm/pcm_local.h | 5 +- src/pcm/pcm_plugin_build.c | 13 +- src/pcm/plugin/interleave.c | 2 +- src/pcm/plugin/linear.c | 8 +- src/pcm/plugin/mulaw.c | 6 +- src/pcm/plugin/rate.c | 6 +- src/pcm/plugin/voices.c | 6 +- 11 files changed, 232 insertions(+), 185 deletions(-) diff --git a/include/control.h b/include/control.h index e89fc7f7..a4c9f408 100644 --- a/include/control.h +++ b/include/control.h @@ -42,13 +42,16 @@ int snd_ctl_switch_read(snd_ctl_t *handle, snd_switch_t * sw); int snd_ctl_switch_write(snd_ctl_t *handle, snd_switch_t * sw); int snd_ctl_hwdep_info(snd_ctl_t *handle, int dev, snd_hwdep_info_t * info); int snd_ctl_pcm_info(snd_ctl_t *handle, int dev, snd_pcm_info_t * info); -int snd_ctl_pcm_channel_info(snd_ctl_t *handle, int dev, int subdev, snd_pcm_channel_info_t * info); -int snd_ctl_pcm_prefer_subdevice(snd_ctl_t *handle, int dev, int subdev); +int snd_ctl_pcm_channel_info(snd_ctl_t *handle, int dev, int channel, int subdev, snd_pcm_channel_info_t * info); +int snd_ctl_pcm_channel_prefer_subdevice(snd_ctl_t *handle, int dev, int channel, int subdev); +int snd_ctl_pcm_channel_switch_list(snd_ctl_t *handle, int dev, int channel, snd_switch_list_t * list); int snd_ctl_pcm_playback_switch_list(snd_ctl_t *handle, int dev, snd_switch_list_t * list); -int snd_ctl_pcm_playback_switch_read(snd_ctl_t *handle, int dev, snd_switch_t * sw); -int snd_ctl_pcm_playback_switch_write(snd_ctl_t *handle, int dev, snd_switch_t * sw); int snd_ctl_pcm_capture_switch_list(snd_ctl_t *handle, int dev, snd_switch_list_t * list); +int snd_ctl_pcm_channel_switch_read(snd_ctl_t *handle, int dev, int channel, snd_switch_t * sw); +int snd_ctl_pcm_playback_switch_read(snd_ctl_t *handle, int dev, snd_switch_t * sw); int snd_ctl_pcm_capture_switch_read(snd_ctl_t *handle, int dev, snd_switch_t * sw); +int snd_ctl_pcm_channel_switch_write(snd_ctl_t *handle, int dev, int channel, snd_switch_t * sw); +int snd_ctl_pcm_playback_switch_write(snd_ctl_t *handle, int dev, snd_switch_t * sw); int snd_ctl_pcm_capture_switch_write(snd_ctl_t *handle, int dev, snd_switch_t * sw); int snd_ctl_mixer_info(snd_ctl_t *handle, int dev, snd_mixer_info_t * info); int snd_ctl_mixer_switch_list(snd_ctl_t *handle, int dev, snd_switch_list_t *list); diff --git a/include/pcm.h b/include/pcm.h index e6ffb772..8fe0a6cc 100644 --- a/include/pcm.h +++ b/include/pcm.h @@ -20,7 +20,7 @@ typedef struct snd_pcm_loopback snd_pcm_loopback_t; int snd_pcm_open(snd_pcm_t **handle, int card, int device, int mode); int snd_pcm_open_subdevice(snd_pcm_t **handle, int card, int device, int subdevice, int mode); int snd_pcm_close(snd_pcm_t *handle); -int snd_pcm_file_descriptor(snd_pcm_t *handle); +int snd_pcm_file_descriptor(snd_pcm_t *handle, int channel); int snd_pcm_nonblock_mode(snd_pcm_t *handle, int nonblock); int snd_pcm_info(snd_pcm_t *handle, snd_pcm_info_t * info); int snd_pcm_channel_info(snd_pcm_t *handle, snd_pcm_channel_info_t * info); diff --git a/src/control/control.c b/src/control/control.c index cc8560e9..cc17729d 100644 --- a/src/control/control.c +++ b/src/control/control.c @@ -171,15 +171,17 @@ int snd_ctl_pcm_info(snd_ctl_t *handle, int dev, snd_pcm_info_t * info) return 0; } -int snd_ctl_pcm_channel_info(snd_ctl_t *handle, int dev, int subdev, snd_pcm_channel_info_t * info) +int snd_ctl_pcm_channel_info(snd_ctl_t *handle, int dev, int chn, int subdev, snd_pcm_channel_info_t * info) { snd_ctl_t *ctl; ctl = handle; - if (!ctl || !info || dev < 0 || subdev < 0) + if (!ctl || !info || dev < 0 || chn < 0 || chn > 1 || subdev < 0) return -EINVAL; if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_DEVICE, &dev) < 0) return -errno; + if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_CHANNEL, &chn) < 0) + return -errno; if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_SUBDEVICE, &subdev) < 0) return -errno; if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_CHANNEL_INFO, info) < 0) @@ -187,102 +189,98 @@ int snd_ctl_pcm_channel_info(snd_ctl_t *handle, int dev, int subdev, snd_pcm_cha return 0; } -int snd_ctl_pcm_prefer_subdevice(snd_ctl_t *handle, int dev, int subdev) +int snd_ctl_pcm_channel_prefer_subdevice(snd_ctl_t *handle, int dev, int chn, int subdev) { snd_ctl_t *ctl; ctl = handle; - if (!ctl || dev < 0) + if (!ctl || dev < 0 || chn < 0 || chn > 1) return -EINVAL; if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_DEVICE, &dev) < 0) return -errno; + if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_CHANNEL, &chn) < 0) + return -errno; if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_PREFER_SUBDEVICE, &subdev) < 0) return -errno; return 0; } -int snd_ctl_pcm_playback_switch_list(snd_ctl_t *handle, int dev, snd_switch_list_t *list) +int snd_ctl_pcm_channel_switch_list(snd_ctl_t *handle, int dev, int chn, snd_switch_list_t *list) { snd_ctl_t *ctl; ctl = handle; - if (!ctl || dev < 0 || !list) + if (!ctl || dev < 0 || chn < 0 || chn > 1 || !list) return -EINVAL; if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_DEVICE, &dev) < 0) return -errno; - if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_PSWITCH_LIST, list) < 0) + if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_CHANNEL, &chn) < 0) + return -errno; + if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_SWITCH_LIST, list) < 0) return -errno; return 0; } -int snd_ctl_pcm_playback_switch_read(snd_ctl_t *handle, int dev, snd_switch_t * sw) +int snd_ctl_pcm_playback_switch_list(snd_ctl_t *handle, int dev, snd_switch_list_t *list) { - snd_ctl_t *ctl; + return snd_ctl_pcm_channel_switch_list(handle, dev, SND_PCM_CHANNEL_PLAYBACK, list); +} - ctl = handle; - if (!ctl || !sw || dev < 0 || sw->name[0] == '\0') - return -EINVAL; - if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_DEVICE, &dev) < 0) - return -errno; - if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_PSWITCH_READ, sw) < 0) - return -errno; - return 0; +int snd_ctl_pcm_capture_switch_list(snd_ctl_t *handle, int dev, snd_switch_list_t *list) +{ + return snd_ctl_pcm_channel_switch_list(handle, dev, SND_PCM_CHANNEL_CAPTURE, list); } -int snd_ctl_pcm_playback_switch_write(snd_ctl_t *handle, int dev, snd_switch_t * sw) +int snd_ctl_pcm_channel_switch_read(snd_ctl_t *handle, int dev, int chn, snd_switch_t * sw) { snd_ctl_t *ctl; ctl = handle; - if (!ctl || !sw || dev < 0 || sw->name[0] == '\0') + if (!ctl || !sw || dev < 0 || chn < 0 || chn > 1 || sw->name[0] == '\0') return -EINVAL; if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_DEVICE, &dev) < 0) return -errno; - if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_PSWITCH_WRITE, sw) < 0) + if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_CHANNEL, &chn) < 0) + return -errno; + if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_SWITCH_READ, sw) < 0) return -errno; return 0; } -int snd_ctl_pcm_capture_switch_list(snd_ctl_t *handle, int dev, snd_switch_list_t * list) +int snd_ctl_pcm_playback_switch_read(snd_ctl_t *handle, int dev, snd_switch_t * sw) { - snd_ctl_t *ctl; - - ctl = handle; - if (!ctl || !list || dev < 0) - return -EINVAL; - if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_DEVICE, &dev) < 0) - return -errno; - if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_CSWITCH_LIST, list) < 0) - return -errno; - return 0; + return snd_ctl_pcm_channel_switch_read(handle, dev, SND_PCM_CHANNEL_PLAYBACK, sw); } int snd_ctl_pcm_capture_switch_read(snd_ctl_t *handle, int dev, snd_switch_t * sw) +{ + return snd_ctl_pcm_channel_switch_read(handle, dev, SND_PCM_CHANNEL_CAPTURE, sw); +} + +int snd_ctl_pcm_channel_switch_write(snd_ctl_t *handle, int dev, int chn, snd_switch_t * sw) { snd_ctl_t *ctl; ctl = handle; - if (!ctl || !sw || dev < 0 || sw->name[0] == '\0') + if (!ctl || !sw || dev < 0 || chn < 0 || chn > 1 || sw->name[0] == '\0') return -EINVAL; if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_DEVICE, &dev) < 0) return -errno; - if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_CSWITCH_READ, sw) < 0) + if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_CHANNEL, &chn) < 0) + return -errno; + if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_SWITCH_WRITE, sw) < 0) return -errno; return 0; } -int snd_ctl_pcm_capture_switch_write(snd_ctl_t *handle, int dev, snd_switch_t * sw) +int snd_ctl_pcm_playback_switch_write(snd_ctl_t *handle, int dev, snd_switch_t * sw) { - snd_ctl_t *ctl; + return snd_ctl_pcm_channel_switch_write(handle, dev, SND_PCM_CHANNEL_PLAYBACK, sw); +} - ctl = handle; - if (!ctl || !sw || dev < 0 || sw->name[0] == '\0') - return -EINVAL; - if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_DEVICE, &dev) < 0) - return -errno; - if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_CSWITCH_WRITE, sw) < 0) - return -errno; - return 0; +int snd_ctl_pcm_capture_switch_write(snd_ctl_t *handle, int dev, snd_switch_t * sw) +{ + return snd_ctl_pcm_channel_switch_write(handle, dev, SND_PCM_CHANNEL_CAPTURE, sw); } int snd_ctl_mixer_info(snd_ctl_t *handle, int dev, snd_mixer_info_t * info) diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index dd91f5b6..177138e8 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -29,8 +29,8 @@ #include #include "pcm_local.h" -#define SND_FILE_PCM "/dev/snd/pcmC%iD%i" -#define SND_FILE_PCM_CONTROL "/dev/snd/pcmcontrol" +#define SND_FILE_PCM_PLAYBACK "/dev/snd/pcmC%iD%ip" +#define SND_FILE_PCM_CAPTURE "/dev/snd/pcmC%iD%ic" #define SND_PCM_VERSION_MAX SND_PROTOCOL_VERSION(1, 0, 0) int snd_pcm_open(snd_pcm_t **handle, int card, int device, int mode) @@ -38,66 +38,50 @@ int snd_pcm_open(snd_pcm_t **handle, int card, int device, int mode) return snd_pcm_open_subdevice(handle, card, device, -1, mode); } -int snd_pcm_open_subdevice(snd_pcm_t **handle, int card, int device, int subdevice, int mode) +static int snd_pcm_open_channel(int card, int device, int channel, int subdevice, int fmode, snd_ctl_t *ctl, int *ver) { - int fd, fmode, ver, err, attempt = 0; char filename[32]; - snd_pcm_t *pcm; - snd_ctl_t *ctl; + char *filefmt; + int err, fd; + int attempt = 0; snd_pcm_channel_info_t info; - - *handle = NULL; - - if (card < 0 || card >= SND_CARDS) - return -EINVAL; - if ((err = snd_ctl_open(&ctl, card)) < 0) - return err; - if ((mode & (SND_PCM_OPEN_PLAYBACK|SND_PCM_OPEN_CAPTURE)) == - (SND_PCM_OPEN_PLAYBACK|SND_PCM_OPEN_CAPTURE)) { - fmode = O_RDWR; - } else if (mode & SND_PCM_OPEN_PLAYBACK) { - fmode = O_WRONLY; - } else if (mode & SND_PCM_OPEN_CAPTURE) { - fmode = O_RDONLY; - } else { - snd_ctl_close(ctl); + switch (channel) { + case SND_PCM_CHANNEL_PLAYBACK: + filefmt = SND_FILE_PCM_PLAYBACK; + break; + case SND_PCM_CHANNEL_CAPTURE: + filefmt = SND_FILE_PCM_CAPTURE; + break; + default: return -EINVAL; } - if (mode & SND_PCM_OPEN_NONBLOCK) - fmode |= O_NONBLOCK; + if ((err = snd_ctl_pcm_channel_prefer_subdevice(ctl, device, channel, subdevice)) < 0) + return err; + sprintf(filename, filefmt, card, device); + __again: if (attempt++ > 3) { snd_ctl_close(ctl); return -EBUSY; } - if ((err = snd_ctl_pcm_prefer_subdevice(ctl, device, subdevice)) < 0) { - snd_ctl_close(ctl); - return err; - } - sprintf(filename, SND_FILE_PCM, card, device); if ((fd = open(filename, fmode)) < 0) { err = -errno; - snd_ctl_close(ctl); return err; } - if (ioctl(fd, SND_PCM_IOCTL_PVERSION, &ver) < 0) { + if (ioctl(fd, SND_PCM_IOCTL_PVERSION, ver) < 0) { err = -errno; close(fd); - snd_ctl_close(ctl); return err; } - if (SND_PROTOCOL_INCOMPATIBLE(ver, SND_PCM_VERSION_MAX)) { + if (SND_PROTOCOL_INCOMPATIBLE(*ver, SND_PCM_VERSION_MAX)) { close(fd); - snd_ctl_close(ctl); return -SND_ERROR_INCOMPATIBLE_VERSION; } - if (subdevice >= 0 && (mode & SND_PCM_OPEN_PLAYBACK) != 0) { + if (subdevice >= 0) { memset(&info, 0, sizeof(info)); - info.channel = SND_PCM_CHANNEL_PLAYBACK; if (ioctl(fd, SND_PCM_IOCTL_CHANNEL_INFO, &info) < 0) { err = -errno; close(fd); - snd_ctl_close(ctl); return err; } if (info.subdevice != subdevice) { @@ -105,89 +89,140 @@ int snd_pcm_open_subdevice(snd_pcm_t **handle, int card, int device, int subdevi goto __again; } } - if (subdevice >= 0 && (mode & SND_PCM_OPEN_CAPTURE) != 0) { - memset(&info, 0, sizeof(info)); - info.channel = SND_PCM_CHANNEL_CAPTURE; - if (ioctl(fd, SND_PCM_IOCTL_CHANNEL_INFO, &info) < 0) { - err = -errno; - close(fd); + return fd; +} + +int snd_pcm_open_subdevice(snd_pcm_t **handle, int card, int device, int subdevice, int mode) +{ + int fmode, ver, err; + snd_pcm_t *pcm; + snd_ctl_t *ctl; + int pfd = -1, cfd = -1; + + *handle = NULL; + + if (card < 0 || card >= SND_CARDS) + return -EINVAL; + if ((err = snd_ctl_open(&ctl, card)) < 0) + return err; + fmode = O_RDWR; + if (mode & SND_PCM_OPEN_NONBLOCK) + fmode |= O_NONBLOCK; + if (mode & SND_PCM_OPEN_PLAYBACK) { + pfd = snd_pcm_open_channel(card, device, SND_PCM_CHANNEL_PLAYBACK, + subdevice, fmode, ctl, &ver); + if (pfd < 0) { snd_ctl_close(ctl); - return err; + return pfd; } - if (info.subdevice != subdevice) { - close(fd); - goto __again; + } + if (mode & SND_PCM_OPEN_CAPTURE) { + cfd = snd_pcm_open_channel(card, device, SND_PCM_CHANNEL_CAPTURE, + subdevice, fmode, ctl, &ver); + if (cfd < 0) { + if (pfd >= 0) + close(pfd); + snd_ctl_close(ctl); + return cfd; } } snd_ctl_close(ctl); + if (pfd < 0 && cfd < 0) + return -EINVAL; pcm = (snd_pcm_t *) calloc(1, sizeof(snd_pcm_t)); if (pcm == NULL) { - close(fd); + if (pfd >= 0) + close(pfd); + if (cfd >= 0) + close(cfd); return -ENOMEM; } pcm->card = card; pcm->device = device; - pcm->fd = fd; + pcm->fd[SND_PCM_CHANNEL_PLAYBACK] = pfd; + pcm->fd[SND_PCM_CHANNEL_CAPTURE] = cfd; pcm->mode = mode; pcm->ver = ver; - pcm->mmap_ctrl_fd[0] = pcm->mmap_ctrl_fd[1] = -1; *handle = pcm; return 0; } int snd_pcm_close(snd_pcm_t *pcm) { - int res; + int res = -EINVAL; + int channel; if (!pcm) return -EINVAL; - snd_pcm_munmap(pcm, SND_PCM_CHANNEL_PLAYBACK); - snd_pcm_munmap(pcm, SND_PCM_CHANNEL_CAPTURE); - snd_pcm_plugin_clear(pcm, SND_PCM_CHANNEL_PLAYBACK); - snd_pcm_plugin_clear(pcm, SND_PCM_CHANNEL_CAPTURE); - res = close(pcm->fd) < 0 ? -errno : 0; + for (channel = 0; channel < 2; ++channel) { + snd_pcm_munmap(pcm, channel); + snd_pcm_plugin_clear(pcm, channel); + if (pcm->fd[channel] >= 0) + if (close(pcm->fd[channel])) + res = -errno; + } free(pcm); return res; } -int snd_pcm_file_descriptor(snd_pcm_t *pcm) +int snd_pcm_file_descriptor(snd_pcm_t *pcm, int channel) { if (!pcm) return -EINVAL; - return pcm->fd; + if (channel < 0 || channel > 1) + return -EINVAL; + return pcm->fd[channel]; } int snd_pcm_nonblock_mode(snd_pcm_t *pcm, int nonblock) { long flags; + int fd, channel; if (!pcm) return -EINVAL; - if ((flags = fcntl(pcm->fd, F_GETFL)) < 0) - return -errno; - if (nonblock) - flags |= O_NONBLOCK; - else - flags &= ~O_NONBLOCK; - if (fcntl(pcm->fd, F_SETFL, flags) < 0) - return -errno; + for (channel = 0; channel < 2; ++channel) { + fd = pcm->fd[channel]; + if (fd < 0) + continue; + if ((flags = fcntl(fd, F_GETFL)) < 0) + return -errno; + if (nonblock) + flags |= O_NONBLOCK; + else + flags &= ~O_NONBLOCK; + if (fcntl(fd, F_SETFL, flags) < 0) + return -errno; + } return 0; } int snd_pcm_info(snd_pcm_t *pcm, snd_pcm_info_t * info) { + int fd, channel; if (!pcm || !info) return -EINVAL; - if (ioctl(pcm->fd, SND_PCM_IOCTL_INFO, info) < 0) + for (channel = 0; channel < 2; ++channel) { + fd = pcm->fd[channel]; + if (fd >= 0) + break; + } + if (ioctl(fd, SND_PCM_IOCTL_INFO, info) < 0) return -errno; return 0; } int snd_pcm_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info) { + int fd; if (!pcm || !info) return -EINVAL; - if (ioctl(pcm->fd, SND_PCM_IOCTL_CHANNEL_INFO, info) < 0) + if (info->channel < 0 || info->channel > 1) + return -EINVAL; + fd = pcm->fd[info->channel]; + if (fd < 0) + return -EINVAL; + if (ioctl(fd, SND_PCM_IOCTL_CHANNEL_INFO, info) < 0) return -errno; return 0; } @@ -195,12 +230,16 @@ int snd_pcm_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info) int snd_pcm_channel_params(snd_pcm_t *pcm, snd_pcm_channel_params_t * params) { int err; + int fd; if (!pcm || !params) return -EINVAL; if (params->channel < 0 || params->channel > 1) return -EINVAL; - if (ioctl(pcm->fd, SND_PCM_IOCTL_CHANNEL_PARAMS, params) < 0) + fd = pcm->fd[params->channel]; + if (fd < 0) + return -EINVAL; + if (ioctl(fd, SND_PCM_IOCTL_CHANNEL_PARAMS, params) < 0) return -errno; pcm->setup_is_valid[params->channel] = 0; memset(&pcm->setup[params->channel], 0, sizeof(snd_pcm_channel_setup_t)); @@ -213,14 +252,18 @@ int snd_pcm_channel_params(snd_pcm_t *pcm, snd_pcm_channel_params_t * params) int snd_pcm_channel_setup(snd_pcm_t *pcm, snd_pcm_channel_setup_t * setup) { + int fd; if (!pcm || !setup) return -EINVAL; if (setup->channel < 0 || setup->channel > 1) return -EINVAL; + fd = pcm->fd[setup->channel]; + if (fd < 0) + return -EINVAL; if (pcm->setup_is_valid[setup->channel]) { memcpy(setup, &pcm->setup[setup->channel], sizeof(*setup)); } else { - if (ioctl(pcm->fd, SND_PCM_IOCTL_CHANNEL_SETUP, setup) < 0) + if (ioctl(fd, SND_PCM_IOCTL_CHANNEL_SETUP, setup) < 0) return -errno; memcpy(&pcm->setup[setup->channel], setup, sizeof(*setup)); pcm->setup_is_valid[setup->channel] = 1; @@ -230,9 +273,13 @@ int snd_pcm_channel_setup(snd_pcm_t *pcm, snd_pcm_channel_setup_t * setup) int snd_pcm_channel_status(snd_pcm_t *pcm, snd_pcm_channel_status_t * status) { + int fd; if (!pcm || !status) return -EINVAL; - if (ioctl(pcm->fd, SND_PCM_IOCTL_CHANNEL_STATUS, status) < 0) + fd = pcm->fd[status->channel]; + if (fd < 0) + return -EINVAL; + if (ioctl(fd, SND_PCM_IOCTL_CHANNEL_STATUS, status) < 0) return -errno; return 0; } @@ -241,7 +288,9 @@ int snd_pcm_playback_prepare(snd_pcm_t *pcm) { if (!pcm) return -EINVAL; - if (ioctl(pcm->fd, SND_PCM_IOCTL_PLAYBACK_PREPARE) < 0) + if (pcm->fd[SND_PCM_CHANNEL_PLAYBACK] < 0) + return -EINVAL; + if (ioctl(pcm->fd[SND_PCM_CHANNEL_PLAYBACK], SND_PCM_IOCTL_CHANNEL_PREPARE) < 0) return -errno; return 0; } @@ -250,7 +299,9 @@ int snd_pcm_capture_prepare(snd_pcm_t *pcm) { if (!pcm) return -EINVAL; - if (ioctl(pcm->fd, SND_PCM_IOCTL_CAPTURE_PREPARE) < 0) + if (pcm->fd[SND_PCM_CHANNEL_CAPTURE] < 0) + return -EINVAL; + if (ioctl(pcm->fd[SND_PCM_CHANNEL_CAPTURE], SND_PCM_IOCTL_CHANNEL_PREPARE) < 0) return -errno; return 0; } @@ -271,7 +322,9 @@ int snd_pcm_playback_go(snd_pcm_t *pcm) { if (!pcm) return -EINVAL; - if (ioctl(pcm->fd, SND_PCM_IOCTL_PLAYBACK_GO) < 0) + if (pcm->fd[SND_PCM_CHANNEL_PLAYBACK] < 0) + return -EINVAL; + if (ioctl(pcm->fd[SND_PCM_CHANNEL_PLAYBACK], SND_PCM_IOCTL_CHANNEL_GO) < 0) return -errno; return 0; } @@ -280,7 +333,9 @@ int snd_pcm_capture_go(snd_pcm_t *pcm) { if (!pcm) return -EINVAL; - if (ioctl(pcm->fd, SND_PCM_IOCTL_CAPTURE_GO) < 0) + if (pcm->fd[SND_PCM_CHANNEL_CAPTURE] < 0) + return -EINVAL; + if (ioctl(pcm->fd[SND_PCM_CHANNEL_CAPTURE], SND_PCM_IOCTL_CHANNEL_GO) < 0) return -errno; return 0; } @@ -301,7 +356,9 @@ int snd_pcm_sync_go(snd_pcm_t *pcm, snd_pcm_sync_t *sync) { if (!pcm || !sync) return -EINVAL; - if (ioctl(pcm->fd, SND_PCM_IOCTL_SYNC_GO, sync) < 0) + if (pcm->fd[SND_PCM_CHANNEL_PLAYBACK] < 0) + return -EINVAL; + if (ioctl(pcm->fd[SND_PCM_CHANNEL_PLAYBACK], SND_PCM_IOCTL_SYNC_GO, sync) < 0) return -errno; return 0; } @@ -310,7 +367,9 @@ int snd_pcm_drain_playback(snd_pcm_t *pcm) { if (!pcm) return -EINVAL; - if (ioctl(pcm->fd, SND_PCM_IOCTL_DRAIN_PLAYBACK) < 0) + if (pcm->fd[SND_PCM_CHANNEL_PLAYBACK] < 0) + return -EINVAL; + if (ioctl(pcm->fd[SND_PCM_CHANNEL_PLAYBACK], SND_PCM_IOCTL_CHANNEL_DRAIN) < 0) return -errno; return 0; } @@ -319,7 +378,9 @@ int snd_pcm_flush_playback(snd_pcm_t *pcm) { if (!pcm) return -EINVAL; - if (ioctl(pcm->fd, SND_PCM_IOCTL_FLUSH_PLAYBACK) < 0) + if (pcm->fd[SND_PCM_CHANNEL_PLAYBACK] < 0) + return -EINVAL; + if (ioctl(pcm->fd[SND_PCM_CHANNEL_PLAYBACK], SND_PCM_IOCTL_CHANNEL_FLUSH) < 0) return -errno; return 0; } @@ -328,7 +389,9 @@ int snd_pcm_flush_capture(snd_pcm_t *pcm) { if (!pcm) return -EINVAL; - if (ioctl(pcm->fd, SND_PCM_IOCTL_FLUSH_CAPTURE) < 0) + if (pcm->fd[SND_PCM_CHANNEL_CAPTURE] < 0) + return -EINVAL; + if (ioctl(pcm->fd[SND_PCM_CHANNEL_CAPTURE], SND_PCM_IOCTL_CHANNEL_FLUSH) < 0) return -errno; return 0; } @@ -349,7 +412,9 @@ int snd_pcm_playback_pause(snd_pcm_t *pcm, int enable) { if (!pcm) return -EINVAL; - if (ioctl(pcm->fd, SND_PCM_IOCTL_PLAYBACK_PAUSE, &enable) < 0) + if (pcm->fd[SND_PCM_CHANNEL_PLAYBACK] < 0) + return -EINVAL; + if (ioctl(pcm->fd[SND_PCM_CHANNEL_PLAYBACK], SND_PCM_IOCTL_CHANNEL_PAUSE, &enable) < 0) return -errno; return 0; } @@ -371,7 +436,9 @@ ssize_t snd_pcm_write(snd_pcm_t *pcm, const void *buffer, size_t size) if (!pcm || (!buffer && size > 0) || size < 0) return -EINVAL; - result = write(pcm->fd, buffer, size); + if (pcm->fd[SND_PCM_CHANNEL_PLAYBACK] < 0) + return -EINVAL; + result = write(pcm->fd[SND_PCM_CHANNEL_PLAYBACK], buffer, size); if (result < 0) return -errno; return result; @@ -383,7 +450,9 @@ ssize_t snd_pcm_read(snd_pcm_t *pcm, void *buffer, size_t size) if (!pcm || (!buffer && size > 0) || size < 0) return -EINVAL; - result = read(pcm->fd, buffer, size); + if (pcm->fd[SND_PCM_CHANNEL_CAPTURE] < 0) + return -EINVAL; + result = read(pcm->fd[SND_PCM_CHANNEL_CAPTURE], buffer, size); if (result < 0) return -errno; return result; @@ -392,8 +461,7 @@ ssize_t snd_pcm_read(snd_pcm_t *pcm, void *buffer, size_t size) int snd_pcm_mmap(snd_pcm_t *pcm, int channel, snd_pcm_mmap_control_t **control, void **buffer) { snd_pcm_channel_info_t info; - snd_pcm_mmap_select_t sel; - int err, ctrl_fd, ver, prot; + int err, fd, prot; void *caddr, *daddr; if (control) @@ -402,48 +470,26 @@ int snd_pcm_mmap(snd_pcm_t *pcm, int channel, snd_pcm_mmap_control_t **control, *buffer = NULL; if (!pcm || channel < 0 || channel > 1 || !control || !buffer) return -EINVAL; + fd = pcm->fd[channel]; + if (fd < 0) + return -EINVAL; memset(&info, 0, sizeof(info)); info.channel = channel; if ((err = snd_pcm_channel_info(pcm, &info))<0) return err; - ctrl_fd = open(SND_FILE_PCM_CONTROL, O_RDWR); - if (ctrl_fd < 0) + caddr = mmap(NULL, sizeof(snd_pcm_mmap_control_t), PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, fd, SND_PCM_MMAP_OFFSET_CONTROL); + if (caddr == (caddr_t)-1 || caddr == NULL) return -errno; - if (ioctl(ctrl_fd, SND_PCM_CTRL_IOCTL_PVERSION, &ver) < 0) { - err = -errno; - close(ctrl_fd); - return err; - } - if (pcm->ver != ver) { - close(ctrl_fd); - return -SND_ERROR_INCOMPATIBLE_VERSION; - } - sel.card = pcm->card; - sel.device = pcm->device; - sel.subdevice = info.subdevice; - sel.channel = channel; - if (ioctl(ctrl_fd, SND_PCM_CTRL_IOCTL_SELECT, &sel) < 0) { - err = -errno; - close(ctrl_fd); - return err; - } - caddr = mmap(NULL, sizeof(snd_pcm_mmap_control_t), PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, ctrl_fd, SND_PCM_MMAP_OFFSET_CONTROL); - if (caddr == (caddr_t)-1 || caddr == NULL) { - close(ctrl_fd); - return -errno; - } prot = channel == SND_PCM_CHANNEL_PLAYBACK ? PROT_WRITE : PROT_READ; - daddr = mmap(NULL, info.mmap_size, prot, MAP_FILE|MAP_SHARED, ctrl_fd, SND_PCM_MMAP_OFFSET_DATA); + daddr = mmap(NULL, info.mmap_size, prot, MAP_FILE|MAP_SHARED, fd, SND_PCM_MMAP_OFFSET_DATA); if (daddr == (caddr_t)-1 || daddr == NULL) { err = -errno; munmap(caddr, sizeof(snd_pcm_mmap_control_t)); - close(ctrl_fd); return err; } *control = pcm->mmap_caddr[channel] = caddr; *buffer = pcm->mmap_daddr[channel] = daddr; pcm->mmap_size[channel] = info.mmap_size; - pcm->mmap_ctrl_fd[channel] = ctrl_fd; return 0; } @@ -460,9 +506,5 @@ int snd_pcm_munmap(snd_pcm_t *pcm, int channel) pcm->mmap_daddr[channel] = NULL; pcm->mmap_size[channel] = 0; } - if (pcm->mmap_ctrl_fd[channel] >= 0) { - close(pcm->mmap_ctrl_fd[channel]); - pcm->mmap_ctrl_fd[channel] = -1; - } return 0; } diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index 7fd9714a..0ba30893 100644 --- a/src/pcm/pcm_local.h +++ b/src/pcm/pcm_local.h @@ -24,12 +24,11 @@ struct snd_pcm { int card; int device; - int fd; int mode; int ver; + int fd[2]; int setup_is_valid[2]; snd_pcm_channel_setup_t setup[2]; - int mmap_ctrl_fd[2]; snd_pcm_mmap_control_t *mmap_caddr[2]; char *mmap_daddr[2]; long mmap_size[2]; @@ -46,7 +45,7 @@ unsigned int snd_pcm_plugin_formats(unsigned int formats); int snd_pcm_plugin_hwparams(snd_pcm_channel_params_t *params, snd_pcm_channel_info_t *hwinfo, snd_pcm_channel_params_t *hwparams); -int snd_pcm_plugin_format(snd_pcm_t *pcm, +int snd_pcm_plugin_format(snd_pcm_t *pcm, snd_pcm_channel_params_t *params, snd_pcm_channel_params_t *hwparams, snd_pcm_channel_info_t *hwinfo); diff --git a/src/pcm/pcm_plugin_build.c b/src/pcm/pcm_plugin_build.c index 410d3aca..10a24d8d 100644 --- a/src/pcm/pcm_plugin_build.c +++ b/src/pcm/pcm_plugin_build.c @@ -40,7 +40,7 @@ ssize_t snd_pcm_plugin_transfer_size(PLUGIN_BASE *pb, int channel, size_t drv_si { snd_pcm_plugin_t *plugin, *plugin_prev, *plugin_next; - if (!pb || (channel != SND_PCM_CHANNEL_PLAYBACK && + if (pb == NULL || (channel != SND_PCM_CHANNEL_PLAYBACK && channel != SND_PCM_CHANNEL_CAPTURE)) return -EINVAL; if (drv_size == 0) @@ -71,7 +71,7 @@ ssize_t snd_pcm_plugin_hardware_size(PLUGIN_BASE *pb, int channel, size_t trf_si { snd_pcm_plugin_t *plugin, *plugin_prev, *plugin_next; - if (!pb || (channel != SND_PCM_CHANNEL_PLAYBACK && + if (pb == NULL || (channel != SND_PCM_CHANNEL_PLAYBACK && channel != SND_PCM_CHANNEL_CAPTURE)) return -EINVAL; if (trf_size == 0) @@ -237,14 +237,19 @@ int snd_pcm_plugin_format(PLUGIN_BASE *pb, snd_pcm_plugin_t *plugin; int err; - if (params->channel == SND_PCM_CHANNEL_PLAYBACK) { + switch (params->channel) { + case SND_PCM_CHANNEL_PLAYBACK: memcpy(&dstparams, hwparams, sizeof(*hwparams)); srcparams = hwparams; memcpy(srcparams, params, sizeof(*params)); - } else { + break; + case SND_PCM_CHANNEL_CAPTURE: memcpy(&dstparams, params, sizeof(*params)); srcparams = params; memcpy(srcparams, hwparams, sizeof(*hwparams)); + break; + default: + return -EINVAL; } memcpy(&tmpparams, srcparams, sizeof(*srcparams)); diff --git a/src/pcm/plugin/interleave.c b/src/pcm/plugin/interleave.c index cd1a17d8..24dbae47 100644 --- a/src/pcm/plugin/interleave.c +++ b/src/pcm/plugin/interleave.c @@ -191,7 +191,7 @@ int snd_pcm_plugin_build_interleave(snd_pcm_format_t *src_format, combination_t cmd; int size; - if (!r_plugin) + if (r_plugin == NULL) return -EINVAL; *r_plugin = NULL; diff --git a/src/pcm/plugin/linear.c b/src/pcm/plugin/linear.c index eabb5fc6..7bca5735 100644 --- a/src/pcm/plugin/linear.c +++ b/src/pcm/plugin/linear.c @@ -321,7 +321,7 @@ static ssize_t linear_src_size(snd_pcm_plugin_t *plugin, size_t size) { struct linear_private_data *data; - if (!plugin || size <= 0) + if (plugin == NULL || size <= 0) return -EINVAL; data = (struct linear_private_data *)snd_pcm_plugin_extra_data(plugin); if (data == NULL) @@ -333,7 +333,7 @@ static ssize_t linear_dst_size(snd_pcm_plugin_t *plugin, size_t size) { struct linear_private_data *data; - if (!plugin || size <= 0) + if (plugin == NULL || size <= 0) return -EINVAL; data = (struct linear_private_data *)snd_pcm_plugin_extra_data(plugin); if (data == NULL) @@ -351,7 +351,7 @@ int snd_pcm_plugin_build_linear(snd_pcm_format_t *src_format, int src_endian, dst_endian, sign, src_width, dst_width; int src_sample_size, dst_sample_size; - if (!r_plugin) + if (r_plugin == NULL) return -EINVAL; *r_plugin = NULL; @@ -424,7 +424,7 @@ int snd_pcm_plugin_build_linear(snd_pcm_format_t *src_format, if (src_endian < 0) src_endian = 0; if (dst_endian < 0) - src_endian = 0; + dst_endian = 0; func = convert_functions[src_width][dst_width][src_endian][dst_endian][sign]; diff --git a/src/pcm/plugin/mulaw.c b/src/pcm/plugin/mulaw.c index 44b23830..b5b40b80 100644 --- a/src/pcm/plugin/mulaw.c +++ b/src/pcm/plugin/mulaw.c @@ -378,7 +378,7 @@ static ssize_t mulaw_src_size(snd_pcm_plugin_t *plugin, size_t size) { struct mulaw_private_data *data; - if (!plugin || size <= 0) + if (plugin == NULL || size <= 0) return -EINVAL; data = (struct mulaw_private_data *)snd_pcm_plugin_extra_data(plugin); switch (data->cmd) { @@ -406,7 +406,7 @@ static ssize_t mulaw_dst_size(snd_pcm_plugin_t *plugin, size_t size) { struct mulaw_private_data *data; - if (!plugin || size <= 0) + if (plugin == NULL || size <= 0) return -EINVAL; data = (struct mulaw_private_data *)snd_pcm_plugin_extra_data(plugin); switch (data->cmd) { @@ -438,7 +438,7 @@ int snd_pcm_plugin_build_mulaw(snd_pcm_format_t *src_format, snd_pcm_plugin_t *plugin; combination_t cmd; - if (!r_plugin) + if (r_plugin == NULL) return -EINVAL; *r_plugin = NULL; diff --git a/src/pcm/plugin/rate.c b/src/pcm/plugin/rate.c index 0c03b66d..5842d336 100644 --- a/src/pcm/plugin/rate.c +++ b/src/pcm/plugin/rate.c @@ -239,7 +239,7 @@ static ssize_t rate_src_size(snd_pcm_plugin_t *plugin, size_t size) struct rate_private_data *data; ssize_t res; - if (!plugin || size <= 0) + if (plugin == NULL || size <= 0) return -EINVAL; data = (struct rate_private_data *)snd_pcm_plugin_extra_data(plugin); if (data->expand) { @@ -271,7 +271,7 @@ static ssize_t rate_dst_size(snd_pcm_plugin_t *plugin, size_t size) struct rate_private_data *data; ssize_t res; - if (!plugin || size <= 0) + if (plugin == NULL || size <= 0) return -EINVAL; data = (struct rate_private_data *)snd_pcm_plugin_extra_data(plugin); if (data->expand) { @@ -366,7 +366,7 @@ int snd_pcm_plugin_build_rate(snd_pcm_format_t *src_format, snd_pcm_plugin_t *plugin; int voice; - if (!r_plugin) + if (r_plugin == NULL) return -EINVAL; *r_plugin = NULL; diff --git a/src/pcm/plugin/voices.c b/src/pcm/plugin/voices.c index 34b9992e..7997600e 100644 --- a/src/pcm/plugin/voices.c +++ b/src/pcm/plugin/voices.c @@ -148,7 +148,7 @@ static ssize_t voices_src_size(snd_pcm_plugin_t *plugin, size_t size) { struct voices_private_data *data; - if (!plugin || size <= 0) + if (plugin == NULL || size <= 0) return -EINVAL; data = (struct voices_private_data *)snd_pcm_plugin_extra_data(plugin); return (size * data->src_voices) / data->dst_voices; @@ -158,7 +158,7 @@ static ssize_t voices_dst_size(snd_pcm_plugin_t *plugin, size_t size) { struct voices_private_data *data; - if (!plugin || size <= 0) + if (plugin == NULL || size <= 0) return -EINVAL; data = (struct voices_private_data *)snd_pcm_plugin_extra_data(plugin); return (size * data->dst_voices) / data->src_voices; @@ -171,7 +171,7 @@ int snd_pcm_plugin_build_voices(snd_pcm_format_t *src_format, struct voices_private_data *data; snd_pcm_plugin_t *plugin; - if (!r_plugin) + if (r_plugin == NULL) return -EINVAL; *r_plugin = NULL; -- 2.47.1