summaryrefslogtreecommitdiffstats
path: root/libaudio/alsa_pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'libaudio/alsa_pcm.c')
-rw-r--r--libaudio/alsa_pcm.c405
1 files changed, 0 insertions, 405 deletions
diff --git a/libaudio/alsa_pcm.c b/libaudio/alsa_pcm.c
deleted file mode 100644
index 5673391..0000000
--- a/libaudio/alsa_pcm.c
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
-** Copyright 2010, The Android Open-Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "alsa_pcm"
-//#define LOG_NDEBUG 0
-#include <cutils/log.h>
-#include <cutils/config_utils.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-
-#include <linux/ioctl.h>
-
-#include "alsa_audio.h"
-
-#define __force
-#define __bitwise
-#define __user
-#include "asound.h"
-
-#define DEBUG 0
-
-/* alsa parameter manipulation cruft */
-
-#define PARAM_MAX SNDRV_PCM_HW_PARAM_LAST_INTERVAL
-
-static inline int param_is_mask(int p)
-{
- return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
- (p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
-}
-
-static inline int param_is_interval(int p)
-{
- return (p >= SNDRV_PCM_HW_PARAM_FIRST_INTERVAL) &&
- (p <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL);
-}
-
-static inline struct snd_interval *param_to_interval(struct snd_pcm_hw_params *p, int n)
-{
- return &(p->intervals[n - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]);
-}
-
-static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n)
-{
- return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
-}
-
-static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned bit)
-{
- if (bit >= SNDRV_MASK_MAX)
- return;
- if (param_is_mask(n)) {
- struct snd_mask *m = param_to_mask(p, n);
- m->bits[0] = 0;
- m->bits[1] = 0;
- m->bits[bit >> 5] |= (1 << (bit & 31));
- }
-}
-
-static void param_set_min(struct snd_pcm_hw_params *p, int n, unsigned val)
-{
- if (param_is_interval(n)) {
- struct snd_interval *i = param_to_interval(p, n);
- i->min = val;
- }
-}
-
-static void param_set_max(struct snd_pcm_hw_params *p, int n, unsigned val)
-{
- if (param_is_interval(n)) {
- struct snd_interval *i = param_to_interval(p, n);
- i->max = val;
- }
-}
-
-static void param_set_int(struct snd_pcm_hw_params *p, int n, unsigned val)
-{
- if (param_is_interval(n)) {
- struct snd_interval *i = param_to_interval(p, n);
- i->min = val;
- i->max = val;
- i->integer = 1;
- }
-}
-
-static void param_init(struct snd_pcm_hw_params *p)
-{
- int n;
- memset(p, 0, sizeof(*p));
- for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK;
- n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) {
- struct snd_mask *m = param_to_mask(p, n);
- m->bits[0] = ~0;
- m->bits[1] = ~0;
- }
- for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL;
- n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) {
- struct snd_interval *i = param_to_interval(p, n);
- i->min = 0;
- i->max = ~0;
- }
-}
-
-/* debugging gunk */
-
-#if DEBUG
-static const char *param_name[PARAM_MAX+1] = {
- [SNDRV_PCM_HW_PARAM_ACCESS] = "access",
- [SNDRV_PCM_HW_PARAM_FORMAT] = "format",
- [SNDRV_PCM_HW_PARAM_SUBFORMAT] = "subformat",
-
- [SNDRV_PCM_HW_PARAM_SAMPLE_BITS] = "sample_bits",
- [SNDRV_PCM_HW_PARAM_FRAME_BITS] = "frame_bits",
- [SNDRV_PCM_HW_PARAM_CHANNELS] = "channels",
- [SNDRV_PCM_HW_PARAM_RATE] = "rate",
- [SNDRV_PCM_HW_PARAM_PERIOD_TIME] = "period_time",
- [SNDRV_PCM_HW_PARAM_PERIOD_SIZE] = "period_size",
- [SNDRV_PCM_HW_PARAM_PERIOD_BYTES] = "period_bytes",
- [SNDRV_PCM_HW_PARAM_PERIODS] = "periods",
- [SNDRV_PCM_HW_PARAM_BUFFER_TIME] = "buffer_time",
- [SNDRV_PCM_HW_PARAM_BUFFER_SIZE] = "buffer_size",
- [SNDRV_PCM_HW_PARAM_BUFFER_BYTES] = "buffer_bytes",
- [SNDRV_PCM_HW_PARAM_TICK_TIME] = "tick_time",
-};
-
-static void param_dump(struct snd_pcm_hw_params *p)
-{
- int n;
-
- for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK;
- n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) {
- struct snd_mask *m = param_to_mask(p, n);
- LOGV("%s = %08x%08x\n", param_name[n],
- m->bits[1], m->bits[0]);
- }
- for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL;
- n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) {
- struct snd_interval *i = param_to_interval(p, n);
- LOGV("%s = (%d,%d) omin=%d omax=%d int=%d empty=%d\n",
- param_name[n], i->min, i->max, i->openmin,
- i->openmax, i->integer, i->empty);
- }
- LOGV("info = %08x\n", p->info);
- LOGV("msbits = %d\n", p->msbits);
- LOGV("rate = %d/%d\n", p->rate_num, p->rate_den);
- LOGV("fifo = %d\n", (int) p->fifo_size);
-}
-
-static void info_dump(struct snd_pcm_info *info)
-{
- LOGV("device = %d\n", info->device);
- LOGV("subdevice = %d\n", info->subdevice);
- LOGV("stream = %d\n", info->stream);
- LOGV("card = %d\n", info->card);
- LOGV("id = '%s'\n", info->id);
- LOGV("name = '%s'\n", info->name);
- LOGV("subname = '%s'\n", info->subname);
- LOGV("dev_class = %d\n", info->dev_class);
- LOGV("dev_subclass = %d\n", info->dev_subclass);
- LOGV("subdevices_count = %d\n", info->subdevices_count);
- LOGV("subdevices_avail = %d\n", info->subdevices_avail);
-}
-#else
-static void param_dump(struct snd_pcm_hw_params *p) {}
-static void info_dump(struct snd_pcm_info *info) {}
-#endif
-
-#define PCM_ERROR_MAX 128
-
-struct pcm {
- int fd;
- unsigned flags;
- int running:1;
- int underruns;
- unsigned buffer_size;
- char error[PCM_ERROR_MAX];
-};
-
-unsigned pcm_buffer_size(struct pcm *pcm)
-{
- return pcm->buffer_size;
-}
-
-const char* pcm_error(struct pcm *pcm)
-{
- return pcm->error;
-}
-
-static int oops(struct pcm *pcm, int e, const char *fmt, ...)
-{
- va_list ap;
- int sz;
-
- va_start(ap, fmt);
- vsnprintf(pcm->error, PCM_ERROR_MAX, fmt, ap);
- va_end(ap);
- sz = strlen(pcm->error);
-
- if (errno)
- snprintf(pcm->error + sz, PCM_ERROR_MAX - sz,
- ": %s", strerror(e));
- return -1;
-}
-
-int pcm_write(struct pcm *pcm, void *data, unsigned count)
-{
- struct snd_xferi x;
-
- if (pcm->flags & PCM_IN)
- return -EINVAL;
-
- x.buf = data;
- x.frames = (pcm->flags & PCM_MONO) ? (count / 2) : (count / 4);
-
- for (;;) {
- if (!pcm->running) {
- if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE))
- return oops(pcm, errno, "cannot prepare channel");
- if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x))
- return oops(pcm, errno, "cannot write initial data");
- pcm->running = 1;
- return 0;
- }
- if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) {
- pcm->running = 0;
- if (errno == EPIPE) {
- /* we failed to make our window -- try to restart */
- pcm->underruns++;
- continue;
- }
- return oops(pcm, errno, "cannot write stream data");
- }
- return 0;
- }
-}
-
-int pcm_read(struct pcm *pcm, void *data, unsigned count)
-{
- struct snd_xferi x;
-
- if (!(pcm->flags & PCM_IN))
- return -EINVAL;
-
- x.buf = data;
- x.frames = (pcm->flags & PCM_MONO) ? (count / 2) : (count / 4);
-
-// LOGV("read() %d frames", x.frames);
- for (;;) {
- if (!pcm->running) {
- if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE))
- return oops(pcm, errno, "cannot prepare channel");
- if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START))
- return oops(pcm, errno, "cannot start channel");
- pcm->running = 1;
- }
- if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) {
- pcm->running = 0;
- if (errno == EPIPE) {
- /* we failed to make our window -- try to restart */
- pcm->underruns++;
- continue;
- }
- return oops(pcm, errno, "cannot read stream data");
- }
-// LOGV("read() got %d frames", x.frames);
- return 0;
- }
-}
-
-static struct pcm bad_pcm = {
- .fd = -1,
-};
-
-int pcm_close(struct pcm *pcm)
-{
- if (pcm == &bad_pcm)
- return 0;
-
- if (pcm->fd >= 0)
- close(pcm->fd);
- pcm->running = 0;
- pcm->buffer_size = 0;
- pcm->fd = -1;
- return 0;
-}
-
-struct pcm *pcm_open(unsigned flags)
-{
- const char *dname;
- struct pcm *pcm;
- struct snd_pcm_info info;
- struct snd_pcm_hw_params params;
- struct snd_pcm_sw_params sparams;
- unsigned period_sz;
- unsigned period_cnt;
-
- LOGV("pcm_open(0x%08x)",flags);
-
- pcm = calloc(1, sizeof(struct pcm));
- if (!pcm)
- return &bad_pcm;
-
- if (flags & PCM_IN) {
- dname = "/dev/snd/pcmC0D0c";
- } else {
- dname = "/dev/snd/pcmC0D0p";
- }
-
- LOGV("pcm_open() period sz multiplier %d",
- ((flags & PCM_PERIOD_SZ_MASK) >> PCM_PERIOD_SZ_SHIFT) + 1);
- period_sz = 128 * (((flags & PCM_PERIOD_SZ_MASK) >> PCM_PERIOD_SZ_SHIFT) + 1);
- LOGV("pcm_open() period cnt %d",
- ((flags & PCM_PERIOD_CNT_MASK) >> PCM_PERIOD_CNT_SHIFT) + PCM_PERIOD_CNT_MIN);
- period_cnt = ((flags & PCM_PERIOD_CNT_MASK) >> PCM_PERIOD_CNT_SHIFT) + PCM_PERIOD_CNT_MIN;
-
- pcm->flags = flags;
- pcm->fd = open(dname, O_RDWR);
- if (pcm->fd < 0) {
- oops(pcm, errno, "cannot open device '%s'");
- return pcm;
- }
-
- if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_INFO, &info)) {
- oops(pcm, errno, "cannot get info - %s");
- goto fail;
- }
- info_dump(&info);
-
- LOGV("pcm_open() period_cnt %d period_sz %d channels %d",
- period_cnt, period_sz, (flags & PCM_MONO) ? 1 : 2);
-
- param_init(&params);
- param_set_mask(&params, SNDRV_PCM_HW_PARAM_ACCESS,
- SNDRV_PCM_ACCESS_RW_INTERLEAVED);
- param_set_mask(&params, SNDRV_PCM_HW_PARAM_FORMAT,
- SNDRV_PCM_FORMAT_S16_LE);
- param_set_mask(&params, SNDRV_PCM_HW_PARAM_SUBFORMAT,
- SNDRV_PCM_SUBFORMAT_STD);
- param_set_min(&params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, period_sz);
- param_set_int(&params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 16);
- param_set_int(&params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
- (flags & PCM_MONO) ? 16 : 32);
- param_set_int(&params, SNDRV_PCM_HW_PARAM_CHANNELS,
- (flags & PCM_MONO) ? 1 : 2);
- param_set_int(&params, SNDRV_PCM_HW_PARAM_PERIODS, period_cnt);
- param_set_int(&params, SNDRV_PCM_HW_PARAM_RATE, 44100);
-
- if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_PARAMS, &params)) {
- oops(pcm, errno, "cannot set hw params");
- goto fail;
- }
- param_dump(&params);
-
- memset(&sparams, 0, sizeof(sparams));
- sparams.tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
- sparams.period_step = 1;
- sparams.avail_min = 1;
- sparams.start_threshold = period_cnt * period_sz;
- sparams.stop_threshold = period_cnt * period_sz;
- sparams.xfer_align = period_sz / 2; /* needed for old kernels */
- sparams.silence_size = 0;
- sparams.silence_threshold = 0;
-
- if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sparams)) {
- oops(pcm, errno, "cannot set sw params");
- goto fail;
- }
-
- pcm->buffer_size = period_cnt * period_sz;
- pcm->underruns = 0;
- return pcm;
-
-fail:
- close(pcm->fd);
- pcm->fd = -1;
- return pcm;
-}
-
-int pcm_ready(struct pcm *pcm)
-{
- return pcm->fd >= 0;
-}