move repository to Debian's GitLab
[osspd.git] / ossp-alsap.c
diff --git a/ossp-alsap.c b/ossp-alsap.c
deleted file mode 100644 (file)
index 72f3bd5..0000000
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
- * ossp-alsap - ossp DSP slave which forwards to alsa
- *
- * Copyright (C)      2009 Maarten Lankhorst <m.b.lankhorst@gmail.com>
- *
- * This file is released under the GPLv2.
- *
- * Why an alsa plugin as well? Just to show how much
- * the alsa userspace api sucks ;-)
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <libgen.h>
-#include <limits.h>
-#include <poll.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <alsa/asoundlib.h>
-#include <sys/soundcard.h>
-
-#include "ossp-slave.h"
-
-enum {
-       AFMT_FLOAT              = 0x00004000,
-       AFMT_S32_LE             = 0x00001000,
-       AFMT_S32_BE             = 0x00002000,
-};
-
-static size_t page_size;
-
-/* alsa structures */
-static snd_pcm_t *pcm[2];
-static snd_pcm_hw_params_t *hw_params;
-static snd_pcm_sw_params_t *sw_params;
-static int block;
-
-static unsigned int byte_counter[2];
-static snd_pcm_uframes_t mmap_pos[2];
-static int stream_corked[2];
-static int stream_notify;
-
-static struct format {
-       snd_pcm_format_t format;
-       snd_pcm_sframes_t rate;
-       int channels;
-} hw_format = { SND_PCM_FORMAT_U8, 8000, 1 };
-
-#if 0
-/* future mmap stuff */
-static size_t mmap_raw_size, mmap_size;
-static int mmap_fd[2] = { -1, -1 };
-static void *mmap_map[2];
-static uint64_t mmap_idx[2];           /* mmap pointer */
-static uint64_t mmap_last_idx[2];      /* last idx for get_ptr */
-static struct ring_buf mmap_stg[2];    /* staging ring buffer */
-static size_t mmap_lead[2];            /* lead bytes */
-static int mmap_sync[2];               /* sync with backend stream */
-#endif
-
-static snd_pcm_format_t fmt_oss_to_alsa(int fmt)
-{
-       switch (fmt) {
-       case AFMT_U8:                   return SND_PCM_FORMAT_U8;
-       case AFMT_A_LAW:                return SND_PCM_FORMAT_A_LAW;
-       case AFMT_MU_LAW:               return SND_PCM_FORMAT_MU_LAW;
-       case AFMT_S16_LE:               return SND_PCM_FORMAT_S16_LE;
-       case AFMT_S16_BE:               return SND_PCM_FORMAT_S16_BE;
-       case AFMT_FLOAT:                return SND_PCM_FORMAT_FLOAT;
-       case AFMT_S32_LE:               return SND_PCM_FORMAT_S32_LE;
-       case AFMT_S32_BE:               return SND_PCM_FORMAT_S32_BE;
-       default:                        return SND_PCM_FORMAT_U8;
-       }
-}
-
-static int fmt_alsa_to_oss(snd_pcm_format_t fmt)
-{
-       switch (fmt) {
-       case SND_PCM_FORMAT_U8:         return AFMT_U8;
-       case SND_PCM_FORMAT_A_LAW:      return AFMT_A_LAW;
-       case SND_PCM_FORMAT_MU_LAW:     return AFMT_MU_LAW;
-       case SND_PCM_FORMAT_S16_LE:     return AFMT_S16_LE;
-       case SND_PCM_FORMAT_S16_BE:     return AFMT_S16_BE;
-       case SND_PCM_FORMAT_FLOAT:      return AFMT_FLOAT;
-       case SND_PCM_FORMAT_S32_LE:     return AFMT_S32_LE;
-       case SND_PCM_FORMAT_S32_BE:     return AFMT_S32_BE;
-       default:                        return AFMT_U8;
-       }
-}
-
-static void flush_streams(int drain)
-{
-       /* FIXME: snd_pcm_drain appears to be able to deadlock,
-        * always drop or check state? */
-       if (drain) {
-               if (pcm[PLAY])
-                       snd_pcm_drain(pcm[PLAY]);
-               if (pcm[REC])
-                       snd_pcm_drain(pcm[REC]);
-       } else {
-               if (pcm[PLAY])
-                       snd_pcm_drop(pcm[PLAY]);
-               if (pcm[REC])
-                       snd_pcm_drop(pcm[REC]);
-       }
-
-       /* XXX: Really needed? */
-#if 0
-       if (pcm[PLAY]) {
-               snd_pcm_close(pcm[PLAY]);
-               snd_pcm_open(&pcm[PLAY], "default",
-                            SND_PCM_STREAM_PLAYBACK, block);
-       }
-       if (pcm[REC]) {
-               snd_pcm_close(pcm[REC]);
-               snd_pcm_open(&pcm[REC], "default",
-                            SND_PCM_STREAM_CAPTURE, block);
-       }
-#endif
-}
-
-static void kill_streams(void)
-{
-       flush_streams(0);
-}
-
-static int trigger_streams(int play, int rec)
-{
-       int ret = 0;
-
-       if (pcm[PLAY] && play >= 0) {
-               ret = snd_pcm_sw_params_set_start_threshold(pcm[PLAY], sw_params,
-                                                          play ? 1 : -1);
-               if (ret >= 0)
-                       snd_pcm_sw_params(pcm[PLAY], sw_params);
-       }
-       if (ret >= 0 && pcm[REC] && rec >= 0) {
-               ret = snd_pcm_sw_params_set_start_threshold(pcm[REC], sw_params,
-                                                           rec ? 1 : -1);
-               if (ret >= 0)
-                       snd_pcm_sw_params(pcm[REC], sw_params);
-       }
-
-       return ret;
-}
-
-static ssize_t alsap_mixer(enum ossp_opcode opcode,
-                          void *carg, void *din, size_t din_sz,
-                          void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-return -EBUSY;
-}
-
-static int set_hw_params(snd_pcm_t *pcm)
-{
-       int ret;
-       unsigned rate;
-
-       ret = snd_pcm_hw_params_any(pcm, hw_params);
-       if (ret >= 0)
-               ret = snd_pcm_hw_params_set_access(pcm, hw_params,
-                                                  SND_PCM_ACCESS_RW_INTERLEAVED);
-       rate = hw_format.rate;
-       if (ret >= 0)
-               ret = snd_pcm_hw_params_set_rate_minmax(pcm, hw_params,
-                                                       &rate, NULL,
-                                                       &rate, NULL);
-       if (ret >= 0)
-               ret = snd_pcm_hw_params_set_format(pcm, hw_params, hw_format.format);
-       if (ret >= 0)
-               ret = snd_pcm_hw_params_set_channels(pcm, hw_params,
-                                                    hw_format.channels);
-       if (ret >= 0)
-               ret = snd_pcm_hw_params(pcm, hw_params);
-       if (ret >= 0)
-               ret = snd_pcm_sw_params_current(pcm, sw_params);
-       if (ret >= 0)
-               ret = snd_pcm_sw_params(pcm, sw_params);
-       return ret;
-}
-
-static ssize_t alsap_open(enum ossp_opcode opcode,
-                         void *carg, void *din, size_t din_sz,
-                         void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-       struct ossp_dsp_open_arg *arg = carg;
-       int ret;
-       block = arg->flags & O_NONBLOCK ? SND_PCM_NONBLOCK : 0;
-       int access;
-//     block |= SND_PCM_ASYNC;
-       /* Woop dee dooo.. I love handling things in SIGIO (PAIN!!)
-        * Probably needed for MMAP
-        */
-
-       if (!hw_params)
-               ret = snd_pcm_hw_params_malloc(&hw_params);
-       if (ret < 0)
-               return ret;
-
-       if (!sw_params)
-               ret = snd_pcm_sw_params_malloc(&sw_params);
-       if (ret < 0)
-               return ret;
-
-       if (pcm[PLAY])
-               snd_pcm_close(pcm[PLAY]);
-       if (pcm[REC])
-               snd_pcm_close(pcm[REC]);
-       pcm[REC] = pcm[PLAY] = NULL;
-
-       access = arg->flags & O_ACCMODE;
-       if (access == O_WRONLY || access == O_RDWR) {
-               ret = snd_pcm_open(&pcm[PLAY], "default",
-                                  SND_PCM_STREAM_PLAYBACK, block);
-               if (ret >= 0)
-                       ret = set_hw_params(pcm[PLAY]);
-       }
-
-       if (ret >= 0 && (access == O_RDONLY || access == O_RDWR)) {
-               ret = snd_pcm_open(&pcm[REC], "default",
-                                  SND_PCM_STREAM_CAPTURE, block);
-               if (ret >= 0)
-                       ret = set_hw_params(pcm[REC]);
-       }
-
-       if (ret < 0) {
-               if (pcm[PLAY])
-                       snd_pcm_close(pcm[PLAY]);
-               if (pcm[REC])
-                       snd_pcm_close(pcm[REC]);
-               pcm[REC] = pcm[PLAY] = NULL;
-               return ret;
-       }
-       return 0;
-}
-
-static ssize_t alsap_write(enum ossp_opcode opcode,
-                          void *carg, void *din, size_t din_sz,
-                          void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-//     struct ossp_dsp_rw_arg *arg = carg;
-       int ret, insize;
-
-       insize = snd_pcm_bytes_to_frames(pcm[PLAY], din_sz);
-
-       if (snd_pcm_state(pcm[PLAY]) == SND_PCM_STATE_SETUP)
-               snd_pcm_prepare(pcm[PLAY]);
-
-//     snd_pcm_start(pcm[PLAY]);
-       ret = snd_pcm_writei(pcm[PLAY], din, insize);
-       if (ret < 0)
-               ret = snd_pcm_recover(pcm[PLAY], ret, 1);
-
-       if (ret >= 0)
-               return snd_pcm_frames_to_bytes(pcm[PLAY], ret);
-       else
-               return ret;
-}
-
-static ssize_t alsap_read(enum ossp_opcode opcode,
-                         void *carg, void *din, size_t din_sz,
-                         void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-//     struct ossp_dsp_rw_arg *arg = carg;
-       int ret, outsize;
-
-       outsize = snd_pcm_bytes_to_frames(pcm[REC], *dout_szp);
-
-       if (snd_pcm_state(pcm[REC]) == SND_PCM_STATE_SETUP)
-               snd_pcm_prepare(pcm[REC]);
-
-       ret = snd_pcm_readi(pcm[REC], dout, outsize);
-       if (ret < 0)
-               ret = snd_pcm_recover(pcm[REC], ret, 1);
-       if (ret >= 0)
-               *dout_szp = ret = snd_pcm_frames_to_bytes(pcm[REC], ret);
-       else
-               *dout_szp = 0;
-
-       return ret;
-}
-
-static ssize_t alsap_poll(enum ossp_opcode opcode,
-                         void *carg, void *din, size_t din_sz,
-                         void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-       unsigned revents = 0;
-
-       stream_notify |= *(int *)carg;
-
-       if (pcm[PLAY])
-               revents |= POLLOUT;
-       if (pcm[REC])
-               revents |= POLLIN;
-
-       *(unsigned *)rarg = revents;
-       return 0;
-}
-
-
-static ssize_t alsap_flush(enum ossp_opcode opcode,
-                          void *carg, void *din, size_t din_sz,
-                          void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-       flush_streams(opcode == OSSP_DSP_SYNC);
-       return 0;
-}
-
-static ssize_t alsap_post(enum ossp_opcode opcode,
-                         void *carg, void *din, size_t din_sz,
-                         void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-       int ret;
-
-       ret = trigger_streams(1, 1);
-       if (ret >= 0 && pcm[PLAY])
-               ret = snd_pcm_start(pcm[PLAY]);
-       if (pcm[REC])
-               ret = snd_pcm_start(pcm[REC]);
-       return ret;
-}
-
-static ssize_t alsap_get_param(enum ossp_opcode opcode,
-                              void *carg, void *din, size_t din_sz,
-                              void *rarg, void *dout, size_t *dout_szp,
-                              int tfd)
-{
-       int v = 0;
-
-       switch (opcode) {
-       case OSSP_DSP_GET_RATE:
-               return hw_format.rate;
-
-       case OSSP_DSP_GET_CHANNELS:
-               return hw_format.channels;
-
-       case OSSP_DSP_GET_FORMAT: {
-               v = fmt_alsa_to_oss(hw_format.format);
-               break;
-       }
-
-       case OSSP_DSP_GET_BLKSIZE: {
-               snd_pcm_uframes_t psize;
-               snd_pcm_hw_params_get_period_size(hw_params, &psize, NULL);
-               v = psize;
-               break;
-       }
-
-       case OSSP_DSP_GET_FORMATS:
-               v = AFMT_U8 | AFMT_A_LAW | AFMT_MU_LAW | AFMT_S16_LE |
-                       AFMT_S16_BE | AFMT_FLOAT | AFMT_S32_LE | AFMT_S32_BE;
-               break;
-
-       case OSSP_DSP_GET_TRIGGER:
-               if (!stream_corked[PLAY])
-                       v |= PCM_ENABLE_OUTPUT;
-               if (!stream_corked[REC])
-                       v |= PCM_ENABLE_INPUT;
-               break;
-
-       default:
-               assert(0);
-       }
-
-       *(int *)rarg = v;
-
-       return 0;
-}
-
-static ssize_t alsap_set_param(enum ossp_opcode opcode,
-                              void *carg, void *din, size_t din_sz,
-                              void *rarg, void *dout, size_t *dout_szp,
-                              int tfd)
-{
-       int v = *(int *)carg;
-       int ret = 0;
-
-       /* kill the streams before changing parameters */
-       kill_streams();
-
-       switch (opcode) {
-       case OSSP_DSP_SET_RATE: {
-               hw_format.rate = v;
-               break;
-       }
-
-       case OSSP_DSP_SET_CHANNELS: {
-               hw_format.channels = v;
-               break;
-       }
-
-       case OSSP_DSP_SET_FORMAT: {
-               snd_pcm_format_t format = fmt_oss_to_alsa(v);
-               hw_format.format = format;
-               break;
-       }
-
-       case OSSP_DSP_SET_SUBDIVISION:
-               if (!v)
-                       v = 1;
-#if 0
-               if (!v) {
-                       v = user_subdivision ?: 1;
-                       break;
-               }
-               user_frag_size = 0;
-               user_subdivision = v;
-               break;
-
-       case OSSP_DSP_SET_FRAGMENT:
-               user_subdivision = 0;
-               user_frag_size = 1 << (v & 0xffff);
-               user_max_frags = (v >> 16) & 0xffff;
-               if (user_frag_size < 4)
-                       user_frag_size = 4;
-               if (user_max_frags < 2)
-                       user_max_frags = 2;
-#else
-       case OSSP_DSP_SET_FRAGMENT:
-#endif
-               break;
-       default:
-               assert(0);
-       }
-
-       if (pcm[PLAY])
-               ret = set_hw_params(pcm[PLAY]);
-       if (ret >= 0 && pcm[REC])
-               ret = set_hw_params(pcm[REC]);
-
-       if (rarg)
-               *(int *)rarg = v;
-       return 0;
-}
-
-static ssize_t alsap_set_trigger(enum ossp_opcode opcode,
-                                void *carg, void *din, size_t din_sz,
-                                void *rarg, void *dout, size_t *dout_szp,
-                                int fd)
-{
-       int enable = *(int *)carg;
-
-       stream_corked[PLAY] = !!(enable & PCM_ENABLE_OUTPUT);
-       stream_corked[REC] = !!(enable & PCM_ENABLE_INPUT);
-
-       return trigger_streams(enable & PCM_ENABLE_OUTPUT,
-                              enable & PCM_ENABLE_INPUT);
-}
-
-static ssize_t alsap_get_space(enum ossp_opcode opcode,
-                              void *carg, void *din, size_t din_sz,
-                              void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-       int dir = (opcode == OSSP_DSP_GET_OSPACE) ? PLAY : REC;
-       int underrun = 0;
-       struct audio_buf_info info = { };
-       unsigned long bufsize;
-       snd_pcm_uframes_t avail, fragsize;
-       snd_pcm_state_t state;
-
-       if (!pcm[dir])
-               return -EINVAL;
-
-       state = snd_pcm_state(pcm[dir]);
-       if (state == SND_PCM_STATE_XRUN) {
-               snd_pcm_recover(pcm[dir], -EPIPE, 0);
-               underrun = 1;
-       } else if (state == SND_PCM_STATE_SUSPENDED) {
-               snd_pcm_recover(pcm[dir], -ESTRPIPE, 0);
-               underrun = 1;
-       }
-
-       snd_pcm_hw_params_current(pcm[dir], hw_params);
-       snd_pcm_hw_params_get_period_size(hw_params, &fragsize, NULL);
-       snd_pcm_hw_params_get_buffer_size(hw_params, &bufsize);
-       info.fragsize = snd_pcm_frames_to_bytes(pcm[dir], fragsize);
-       info.fragstotal = bufsize / fragsize;
-       if (!underrun) {
-               avail = snd_pcm_avail_update(pcm[dir]);
-               info.fragments = avail / fragsize;
-       } else
-               info.fragments = info.fragstotal;
-
-       info.bytes = info.fragsize * info.fragments;
-
-       *(struct audio_buf_info *)rarg = info;
-       return 0;
-}
-
-static ssize_t alsap_get_ptr(enum ossp_opcode opcode,
-                            void *carg, void *din, size_t din_sz,
-                            void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-       int dir = (opcode == OSSP_DSP_GET_OPTR) ? PLAY : REC;
-       struct count_info info = { };
-
-       if (!pcm[dir])
-               return -EIO;
-
-       snd_pcm_hw_params_current(pcm[dir], hw_params);
-       info.bytes = byte_counter[dir];
-       snd_pcm_hw_params_get_periods(hw_params, (unsigned int *)&info.blocks, NULL);
-       info.ptr = mmap_pos[dir];
-
-       *(struct count_info *)rarg = info;
-       return 0;
-}
-
-static ssize_t alsap_get_odelay(enum ossp_opcode opcode,
-                               void *carg, void *din, size_t din_sz,
-                               void *rarg, void *dout, size_t *dout_szp,
-                               int fd)
-{
-       snd_pcm_sframes_t delay;
-
-       if (!pcm[PLAY])
-               return -EIO;
-
-       if (snd_pcm_delay(pcm[PLAY], &delay) < 0)
-               return -EIO;
-
-       *(int *)rarg = snd_pcm_frames_to_bytes(pcm[PLAY], delay);
-       return 0;
-}
-
-static ossp_action_fn_t action_fn_tbl[OSSP_NR_OPCODES] = {
-       [OSSP_MIXER]            = alsap_mixer,
-       [OSSP_DSP_OPEN]         = alsap_open,
-       [OSSP_DSP_READ]         = alsap_read,
-       [OSSP_DSP_WRITE]        = alsap_write,
-       [OSSP_DSP_POLL]         = alsap_poll,
-#if 0
-       [OSSP_DSP_MMAP]         = alsap_mmap,
-       [OSSP_DSP_MUNMAP]       = alsap_munmap,
-#endif
-       [OSSP_DSP_RESET]        = alsap_flush,
-       [OSSP_DSP_SYNC]         = alsap_flush,
-       [OSSP_DSP_POST]         = alsap_post,
-       [OSSP_DSP_GET_RATE]     = alsap_get_param,
-       [OSSP_DSP_GET_CHANNELS] = alsap_get_param,
-       [OSSP_DSP_GET_FORMAT]   = alsap_get_param,
-       [OSSP_DSP_GET_BLKSIZE]  = alsap_get_param,
-       [OSSP_DSP_GET_FORMATS]  = alsap_get_param,
-       [OSSP_DSP_SET_RATE]     = alsap_set_param,
-       [OSSP_DSP_SET_CHANNELS] = alsap_set_param,
-       [OSSP_DSP_SET_FORMAT]   = alsap_set_param,
-       [OSSP_DSP_SET_SUBDIVISION] = alsap_set_param,
-       [OSSP_DSP_SET_FRAGMENT] = alsap_set_param,
-       [OSSP_DSP_GET_TRIGGER]  = alsap_get_param,
-       [OSSP_DSP_SET_TRIGGER]  = alsap_set_trigger,
-       [OSSP_DSP_GET_OSPACE]   = alsap_get_space,
-       [OSSP_DSP_GET_ISPACE]   = alsap_get_space,
-       [OSSP_DSP_GET_OPTR]     = alsap_get_ptr,
-       [OSSP_DSP_GET_IPTR]     = alsap_get_ptr,
-       [OSSP_DSP_GET_ODELAY]   = alsap_get_odelay,
-};
-
-static int action_pre(void)
-{
-       return 0;
-}
-
-static void action_post(void)
-{
-}
-
-int main(int argc, char **argv)
-{
-       int rc;
-
-       ossp_slave_init(argc, argv);
-
-       page_size = sysconf(_SC_PAGE_SIZE);
-
-       /* Okay, now we're open for business */
-       rc = 0;
-       do {
-               rc = ossp_slave_process_command(ossp_cmd_fd, action_fn_tbl,
-                                               action_pre, action_post);
-       } while (rc > 0);
-
-       return rc ? 1 : 0;
-}