summaryrefslogtreecommitdiff
path: root/lib/libsalsa/pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libsalsa/pcm.c')
-rw-r--r--lib/libsalsa/pcm.c3114
1 files changed, 3114 insertions, 0 deletions
diff --git a/lib/libsalsa/pcm.c b/lib/libsalsa/pcm.c
new file mode 100644
index 0000000..a305e54
--- /dev/null
+++ b/lib/libsalsa/pcm.c
@@ -0,0 +1,3114 @@
+/*
+ * Copyright (c) 2004 by Hannu Savolainen < hannu@opensound.com>
+ *
+ * Parts of the code is derived from the alsa-lib package that is
+ * copyrighted by Jaroslav Kysela and the other ALSA team members.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#define USE_VERSIONED_SYMBOLS
+#define DO_VERSIONING
+#define HAVE_ELF
+#define PERIOD_SIZE 128
+
+#include "local.h"
+
+#define PCMTYPE(v) [SND_PCM_TYPE_##v] = #v
+#define STATE(v) [SND_PCM_STATE_##v] = #v
+#define STREAM(v) [SND_PCM_STREAM_##v] = #v
+#define READY(v) [SND_PCM_READY_##v] = #v
+#define XRUN(v) [SND_PCM_XRUN_##v] = #v
+#define SILENCE(v) [SND_PCM_SILENCE_##v] = #v
+#define TSTAMP(v) [SND_PCM_TSTAMP_##v] = #v
+#define ACCESS(v) [SND_PCM_ACCESS_##v] = #v
+#define START(v) [SND_PCM_START_##v] = #v
+#define HW_PARAM(v) [SND_PCM_HW_PARAM_##v] = #v
+#define SW_PARAM(v) [SND_PCM_SW_PARAM_##v] = #v
+#define FORMAT(v) [SND_PCM_FORMAT_##v] = #v
+#define SUBFORMAT(v) [SND_PCM_SUBFORMAT_##v] = #v
+
+#define FORMATD(v, d) [SND_PCM_FORMAT_##v] = d
+#define SUBFORMATD(v, d) [SND_PCM_SUBFORMAT_##v] = d
+
+static const char *snd_pcm_stream_names[] = {
+ STREAM (PLAYBACK),
+ STREAM (CAPTURE),
+};
+
+static const char *snd_pcm_state_names[] = {
+ STATE (OPEN),
+ STATE (SETUP),
+ STATE (PREPARED),
+ STATE (RUNNING),
+ STATE (XRUN),
+ STATE (DRAINING),
+ STATE (PAUSED),
+ STATE (SUSPENDED),
+ STATE (DISCONNECTED),
+};
+
+static const char *snd_pcm_access_names[] = {
+ ACCESS (MMAP_INTERLEAVED),
+ ACCESS (MMAP_NONINTERLEAVED),
+ ACCESS (MMAP_COMPLEX),
+ ACCESS (RW_INTERLEAVED),
+ ACCESS (RW_NONINTERLEAVED),
+};
+
+static const char *snd_pcm_format_descriptions[] = {
+ FORMATD (S8, "Signed 8 bit"),
+ FORMATD (U8, "Unsigned 8 bit"),
+ FORMATD (S16_LE, "Signed 16 bit Little Endian"),
+ FORMATD (S16_BE, "Signed 16 bit Big Endian"),
+ FORMATD (U16_LE, "Unsigned 16 bit Little Endian"),
+ FORMATD (U16_BE, "Unsigned 16 bit Big Endian"),
+ FORMATD (S24_LE, "Signed 24 bit Little Endian"),
+ FORMATD (S24_BE, "Signed 24 bit Big Endian"),
+ FORMATD (U24_LE, "Unsigned 24 bit Little Endian"),
+ FORMATD (U24_BE, "Unsigned 24 bit Big Endian"),
+ FORMATD (S32_LE, "Signed 32 bit Little Endian"),
+ FORMATD (S32_BE, "Signed 32 bit Big Endian"),
+ FORMATD (U32_LE, "Unsigned 32 bit Little Endian"),
+ FORMATD (U32_BE, "Unsigned 32 bit Big Endian"),
+ FORMATD (FLOAT_LE, "Float 32 bit Little Endian"),
+ FORMATD (FLOAT_BE, "Float 32 bit Big Endian"),
+ FORMATD (FLOAT64_LE, "Float 64 bit Little Endian"),
+ FORMATD (FLOAT64_BE, "Float 64 bit Big Endian"),
+ FORMATD (IEC958_SUBFRAME_LE, "IEC-958 Little Endian"),
+ FORMATD (IEC958_SUBFRAME_BE, "IEC-958 Big Endian"),
+ FORMATD (MU_LAW, "Mu-Law"),
+ FORMATD (A_LAW, "A-Law"),
+ FORMATD (IMA_ADPCM, "Ima-ADPCM"),
+ FORMATD (MPEG, "MPEG"),
+ FORMATD (GSM, "GSM"),
+ FORMATD (SPECIAL, "Special"),
+ FORMATD (S24_3LE, "Signed 24 bit Little Endian in 3bytes"),
+ FORMATD (S24_3BE, "Signed 24 bit Big Endian in 3bytes"),
+ FORMATD (U24_3LE, "Unsigned 24 bit Little Endian in 3bytes"),
+ FORMATD (U24_3BE, "Unsigned 24 bit Big Endian in 3bytes"),
+ FORMATD (S20_3LE, "Signed 20 bit Little Endian in 3bytes"),
+ FORMATD (S20_3BE, "Signed 20 bit Big Endian in 3bytes"),
+ FORMATD (U20_3LE, "Unsigned 20 bit Little Endian in 3bytes"),
+ FORMATD (U20_3BE, "Unsigned 20 bit Big Endian in 3bytes"),
+ FORMATD (S18_3LE, "Signed 18 bit Little Endian in 3bytes"),
+ FORMATD (S18_3BE, "Signed 18 bit Big Endian in 3bytes"),
+ FORMATD (U18_3LE, "Unsigned 18 bit Little Endian in 3bytes"),
+ FORMATD (U18_3BE, "Unsigned 18 bit Big Endian in 3bytes"),
+};
+
+struct _snd_pcm
+{
+ int fd;
+ int state;
+ oss_audioinfo info;
+ int stream, oss_mode;
+ int frame_size, sample_size, period_size;
+ int channels;
+ int periods;
+ snd_pcm_channel_area_t *area;
+};
+
+struct _snd_pcm_format_mask
+{
+ unsigned int mask;
+};
+
+struct _snd_pcm_status
+{
+ int dummy;
+};
+
+struct _snd_pcm_sw_params
+{
+ int dummy;
+};
+
+struct _snd_pcm_hw_params
+{
+ int speed;
+ int fmt, channels;
+ int oss_fmt;
+
+ oss_audioinfo *info;
+ snd_pcm_t *pcm;
+
+ int frame_size;
+ int sample_bits;
+ int access;
+};
+
+static int
+parse_device (const char *nme, char *dspname)
+{
+ char *s;
+ oss_audioinfo ai;
+ int card = 0, port = 0, i;
+ char tmp[256], *name = tmp;
+
+ strcpy (name, nme);
+
+ if (name[0] != 'h')
+ return 0;
+ if (name[1] != 'w')
+ return 0;
+ if (name[2] != ':')
+ return 0;
+
+ name += 3;
+ s = name;
+
+ while (*s && *s != ',')
+ s++;
+
+ if (*s == ',')
+ {
+ int n = 0;
+
+ *s++ = 0;
+ if (sscanf (name, "%d", &card) != 1)
+ return 0;
+ if (sscanf (s, "%d", &port) != 1)
+ return 0;
+
+ n = -1;
+ for (i = 0; i < sysinfo.numaudios; i++)
+ {
+ ai.dev = i;
+ if (ioctl (mixer_fd, SNDCTL_AUDIOINFO, &ai) == -1)
+ continue;
+
+ if (ai.card_number != card)
+ continue;
+
+ n++;
+ if (port < n)
+ continue;
+
+ sprintf (dspname, "/dev/dsp%d", i);
+ return 1;
+ }
+ return 0;
+ }
+ if (sscanf (name, "%d", &card) != 1)
+ return 0;
+
+ for (i = 0; i < sysinfo.numaudios; i++)
+ {
+ ai.dev = i;
+ if (ioctl (mixer_fd, SNDCTL_AUDIOINFO, &ai) == -1)
+ continue;
+
+ if (ai.card_number == card)
+ {
+ port = i;
+ sprintf (dspname, "/dev/dsp%d", port);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * \brief Opens a PCM
+ * \param pcmp Returned PCM handle
+ * \param name ASCII identifier of the PCM handle
+ * \param stream Wanted stream
+ * \param mode Open mode (see #SND_PCM_NONBLOCK, #SND_PCM_ASYNC)
+ * \return 0 on success otherwise a negative error code
+ */
+int
+snd_pcm_open (snd_pcm_t ** pcmp, const char *name,
+ snd_pcm_stream_t stream, int mode)
+{
+ snd_pcm_t *pcm;
+ int oss_mode = O_WRONLY;
+ char dspname[32];
+ const char *devdsp;
+
+ if ((devdsp = getenv("OSS_AUDIODEV")) == NULL)
+ devdsp = "/dev/dsp";
+
+ ALIB_INIT ();
+
+ if (!alib_appcheck ())
+ return -ENODEV;
+
+ *pcmp = NULL;
+
+ dbg_printf ("snd_pcm_open(%s, %x)\n", name, stream);
+
+ if (mode != 0)
+ dbg_printf2 ("snd_pcm_open: mode=0x%x - not emulated.\n", mode);
+
+ if (strcmp (name, "default") == 0)
+ name = devdsp;
+ else
+ {
+ if (!parse_device (name, dspname))
+ {
+#if 0
+ fprintf (stderr, "OSS asound - Bad PCM device '%s'\n", name);
+ return -ENOENT;
+#else
+ strcpy (dspname, devdsp);
+#endif
+ }
+
+ name = dspname;
+ }
+
+ if ((pcm = malloc (sizeof (*pcm))) == NULL)
+ return -ENOMEM;
+
+ switch (stream)
+ {
+ case SND_PCM_STREAM_CAPTURE:
+ oss_mode = O_RDONLY;
+ break;
+ case SND_PCM_STREAM_PLAYBACK:
+ oss_mode = O_WRONLY;
+ break;
+ default:
+ fprintf (stderr, "snd_pcm_open: Bad stream %d\n", stream);
+ return -EINVAL;
+ }
+
+ memset (pcm, 0, sizeof (*pcm));
+ pcm->stream = stream;
+ pcm->frame_size = 2;
+ pcm->sample_size = 1;
+ pcm->channels = 2;
+ pcm->oss_mode = oss_mode;
+ pcm->state = SND_PCM_STATE_OPEN;
+ pcm->period_size = PERIOD_SIZE;
+ pcm->periods = 4;
+
+ if ((pcm->fd = open (name, oss_mode, 0)) == -1)
+ {
+ int err = errno;
+ free (pcm);
+ return -err;
+ }
+
+ pcm->info.dev = -1;
+ if (ioctl (pcm->fd, SNDCTL_ENGINEINFO, &pcm->info) == -1)
+ {
+ int err = errno;
+ close (pcm->fd);
+ free (pcm);
+ return -err;
+ }
+
+ dbg_printf ("Opened %s='%s' = %d\n", name, pcm->info.name, pcm->fd);
+ *pcmp = pcm;
+ return 0;
+}
+
+/**
+ * \brief close PCM handle
+ * \param pcm PCM handle
+ * \return 0 on success otherwise a negative error code
+ *
+ * Closes the specified PCM handle and frees all associated
+ * resources.
+ */
+int
+snd_pcm_close (snd_pcm_t * pcm)
+{
+ if (pcm == NULL)
+ return -1;
+ close (pcm->fd);
+ if (pcm->area != NULL)
+ free (pcm->area);
+ free (pcm);
+ return 0;
+}
+
+/**
+ * \brief Convert frames in bytes for a PCM
+ * \param pcm PCM handle
+ * \param frames quantity in frames
+ * \return quantity expressed in bytes
+ */
+ssize_t
+snd_pcm_frames_to_bytes (snd_pcm_t * pcm, snd_pcm_sframes_t frames)
+{
+// printf("snd_pcm_frames_to_bytes(%d)\n", frames);
+ return frames * pcm->frame_size;
+}
+
+/**
+ * \brief Convert bytes in frames for a PCM
+ * \param pcm PCM handle
+ * \param bytes quantity in bytes
+ * \return quantity expressed in frames
+ */
+snd_pcm_sframes_t
+snd_pcm_bytes_to_frames (snd_pcm_t * pcm, ssize_t bytes)
+{
+ dbg_printf3 ("snd_pcm_bytes_to_frames(%d)=%d\n", bytes,
+ bytes / pcm->frame_size);
+ return bytes / pcm->frame_size;
+}
+
+/**
+ * \brief Stop a PCM preserving pending frames
+ * \param pcm PCM handle
+ * \return 0 on success otherwise a negative error code
+ * \retval -ESTRPIPE a suspend event occurred
+ *
+ * For playback wait for all pending frames to be played and then stop
+ * the PCM.
+ * For capture stop PCM permitting to retrieve residual frames.
+ *
+ * For stopping the PCM stream immediately, use \link ::snd_pcm_drop() \endlink
+ * instead.
+ */
+int
+snd_pcm_drain (snd_pcm_t * pcm)
+{
+ dbg_printf2 ("snd_pcm_drain()\n");
+ ioctl (pcm->fd, SNDCTL_DSP_SYNC, NULL);
+ return 0;
+}
+
+/**
+ * \brief Stop a PCM dropping pending frames
+ * \param pcm PCM handle
+ * \return 0 on success otherwise a negative error code
+ *
+ * This function stops the PCM <i>immediately</i>.
+ * The pending samples on the buffer are ignored.
+ *
+ * For processing all pending samples, use \link ::snd_pcm_drain() \endlink
+ * instead.
+ */
+int
+snd_pcm_drop (snd_pcm_t * pcm)
+{
+ dbg_printf2 ("snd_pcm_drop()\n");
+ ioctl (pcm->fd, SNDCTL_DSP_HALT, NULL);
+ return 0;
+}
+
+/** \brief Install one PCM hardware configuration chosen from a configuration sp
+ace and #snd_pcm_prepare it
+ * \param pcm PCM handle
+ * \param params Configuration space definition container
+ * \return 0 on success otherwise a negative error code
+ *
+ * The configuration is chosen fixing single parameters in this order:
+ * first access, first format, first subformat, min channels, min rate,
+ * min period time, max buffer size, min tick time
+ *
+ * After this call, #snd_pcm_prepare() is called automatically and
+ * the stream is brought to \c #SND_PCM_STATE_PREPARED state.
+ */
+int
+snd_pcm_hw_params (snd_pcm_t * pcm, snd_pcm_hw_params_t * params)
+{
+ int tmp;
+
+ dbg_printf ("snd_pcm_hw_params(%d, %d ch, %x)\n",
+ params->speed, params->channels, params->oss_fmt);
+
+ tmp = params->oss_fmt;
+ if (ioctl (pcm->fd, SNDCTL_DSP_SETFMT, &tmp) == -1)
+ return -errno;
+ if (tmp != params->oss_fmt)
+ return -EINVAL;
+
+ tmp = params->channels;
+ if (ioctl (pcm->fd, SNDCTL_DSP_CHANNELS, &tmp) == -1)
+ return -errno;
+ if (tmp != params->channels)
+ return -EINVAL;
+ pcm->channels = tmp;
+
+ tmp = params->speed;
+ if (ioctl (pcm->fd, SNDCTL_DSP_SPEED, &tmp) == -1)
+ return -errno;
+ if (tmp != params->speed)
+ return -EINVAL;
+
+ tmp = params->channels * params->sample_bits;
+ pcm->frame_size = params->frame_size = tmp / 8;
+ pcm->sample_size = pcm->frame_size / pcm->channels;
+ dbg_printf ("Frame size = %d\n", params->frame_size);
+ return 0;
+}
+
+
+/**
+ * \brief Fill params with a full configuration space for a PCM
+ * \param pcm PCM handle
+ * \param params Configuration space
+ */
+int
+snd_pcm_hw_params_any (snd_pcm_t * pcm, snd_pcm_hw_params_t * params)
+{
+ dbg_printf ("snd_pcm_hw_params_any()\n");
+
+ memset (params, 0, sizeof (params));
+ if (ioctl (pcm->fd, SNDCTL_DSP_CHANNELS, &params->channels) == -1)
+ return -errno;
+ pcm->channels = params->channels;
+ if (ioctl (pcm->fd, SNDCTL_DSP_SETFMT, &params->oss_fmt) == -1)
+ return -errno;
+ if (ioctl (pcm->fd, SNDCTL_DSP_SPEED, &params->speed) == -1)
+ return -errno;
+ dbg_printf ("Rate %d, channels %d, fmt %x\n", params->speed,
+ params->channels, params->oss_fmt);
+
+// TODO
+ params->frame_size = 2 * params->channels;
+ params->sample_bits = 16;
+
+ params->info = &pcm->info;
+ params->pcm = pcm;
+ return 0;
+}
+
+/**
+ * \brief Restrict a configuration space to contain only one access type
+ * \param pcm PCM handle
+ * \param params Configuration space
+ * \param access access type
+ * \return 0 otherwise a negative error code if configuration space would become empty
+ */
+int
+snd_pcm_hw_params_set_access (snd_pcm_t * pcm, snd_pcm_hw_params_t * params,
+ snd_pcm_access_t access)
+{
+ dbg_printf2 ("snd_pcm_hw_params_set_access(%x/%s)\n", access,
+ snd_pcm_access_names[access]);
+ params->access = access;
+ if (access == SND_PCM_ACCESS_RW_INTERLEAVED)
+ return 0;
+ if (access == SND_PCM_ACCESS_MMAP_INTERLEAVED)
+ return 0;
+ return -EINVAL;
+}
+
+/**
+ * \brief Restrict a configuration space to contain only one buffer size
+ * \param pcm PCM handle
+ * \param params Configuration space
+ * \param val buffer size in frames
+ * \return 0 otherwise a negative error code if configuration space would become empty
+ *
+ * Wanted exact value is <,=,> val following dir (-1,0,1)
+ */
+int
+snd_pcm_hw_params_set_buffer_size (snd_pcm_t * pcm,
+ snd_pcm_hw_params_t * params,
+ snd_pcm_uframes_t val)
+{
+ dbg_printf ("snd_pcm_hw_params_set_buffer_size()\n");
+
+ return 0;
+}
+
+int
+snd_pcm_hw_params_set_buffer_size_min (snd_pcm_t * pcm,
+ snd_pcm_hw_params_t * params,
+ snd_pcm_uframes_t * val)
+{
+ dbg_printf ("snd_pcm_hw_params_set_buffer_size_min()\n");
+
+ return 0;
+}
+
+/**
+ * \brief Restrict a configuration space to have buffer size nearest to a target
+ * \param pcm PCM handle
+ * \param params Configuration space
+ * \param val approximate target buffer size in frames / returned chosen approxi
+mate target buffer size in frames
+ * \return 0 otherwise a negative error code if configuration space is empty
+ *
+ * target/chosen exact value is <,=,> val following dir (-1,0,1)
+ */
+int
+__snd_pcm_hw_params_set_buffer_size_near (snd_pcm_t * pcm,
+ snd_pcm_hw_params_t * params,
+ snd_pcm_uframes_t * val)
+{
+ dbg_printf ("snd_pcm_hw_params_set_buffer_size_near(%d)\n", *val);
+ return 0;
+}
+
+/**
+ * \brief Restrict a configuration space to contain only one channels count
+ * \param pcm PCM handle
+ * \param params Configuration space
+ * \param val channels count
+ * \return 0 otherwise a negative error code if configuration space would become empty
+ */
+int
+snd_pcm_hw_params_set_channels (snd_pcm_t * pcm, snd_pcm_hw_params_t * params,
+ unsigned int val)
+{
+ dbg_printf2 ("snd_pcm_hw_params_set_channels(%d)\n", val);
+
+ params->channels = val;
+
+ if (ioctl (pcm->fd, SNDCTL_DSP_CHANNELS, &params->channels) < 0)
+ return -errno;
+
+ if (params->channels != val)
+ return -EINVAL;
+ pcm->channels = params->channels;
+ return 0;
+}
+
+int
+__snd_pcm_hw_params_set_channels_near (snd_pcm_t * pcm,
+ snd_pcm_hw_params_t * params,
+ unsigned int *val)
+{
+ dbg_printf2 ("snd_pcm_hw_params_set_channels_near(%d)\n", *val);
+
+ params->channels = *val;
+
+ if (ioctl (pcm->fd, SNDCTL_DSP_CHANNELS, &params->channels) < 0)
+ return -errno;
+
+ *val = params->channels;
+ pcm->channels = params->channels;
+ return 0;
+}
+
+/**
+ * \brief Restrict a configuration space to contain only one format
+ * \param pcm PCM handle
+ * \param params Configuration space
+ * \param format format
+ * \return 0 otherwise a negative error code
+ */
+int
+snd_pcm_hw_params_set_format (snd_pcm_t * pcm, snd_pcm_hw_params_t * params,
+ snd_pcm_format_t format)
+{
+ int err = -EINVAL;
+ int tmp;
+
+ dbg_printf2 ("snd_pcm_hw_params_set_format(%d)\n", format);
+ if (format == SND_PCM_FORMAT_U8)
+ {
+ params->fmt = format;
+ params->oss_fmt = AFMT_U8;
+ params->sample_bits = 8;
+ err = 0;
+ }
+
+ if (format == SND_PCM_FORMAT_S16_LE)
+ {
+ params->fmt = format;
+ params->oss_fmt = AFMT_S16_LE;
+ params->sample_bits = 16;
+ err = 0;
+ }
+
+ if (err < 0)
+ return err;
+
+ tmp = params->oss_fmt;
+ if (ioctl (pcm->fd, SNDCTL_DSP_SETFMT, &tmp) < 0)
+ return -errno;
+
+ if (tmp != params->oss_fmt)
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * \brief Extract format from a configuration space
+ * \param params Configuration space
+ * \param format returned format
+ * \return format otherwise a negative error code if not exactly one is present
+ */
+int INTERNAL (snd_pcm_hw_params_get_format) (const snd_pcm_hw_params_t *
+ params,
+ snd_pcm_format_t * format)
+{
+ dbg_printf ("snd_pcm_hw_params_get_format(params=%x)\n", params);
+
+ *format = params->fmt;
+}
+
+/**
+ * \brief Verify if a format is available inside a configuration space for a PCM * \param pcm PCM handle
+ * \param params Configuration space
+ * \param format format
+ * \return 0 if available a negative error code otherwise
+ */
+int
+snd_pcm_hw_params_test_format (snd_pcm_t * pcm, snd_pcm_hw_params_t * params,
+ snd_pcm_format_t format)
+{
+ dbg_printf2 ("snd_pcm_hw_params_test_format()\n");
+
+ if (format == SND_PCM_FORMAT_U8)
+ return 0;
+ if (format == SND_PCM_FORMAT_S16_LE)
+ return 0;
+
+ return -EINVAL;
+}
+
+/**
+ * \brief Restrict a configuration space to contain only one periods count
+ * \param pcm PCM handle
+ * \param params Configuration space
+ * \param val approximate periods per buffer
+ * \param dir Sub unit direction
+ * \return 0 otherwise a negative error code if configuration space would become empty
+ *
+ * Wanted exact value is <,=,> val following dir (-1,0,1)
+ */
+int
+snd_pcm_hw_params_set_periods (snd_pcm_t * pcm, snd_pcm_hw_params_t * params,
+ unsigned int val, int dir)
+{
+ dbg_printf
+ ("snd_pcm_hw_params_set_periods(pcm=%x, params=%x, val=%d, dir=%d)\n",
+ pcm, params, val, dir);
+ pcm->periods = val;
+
+ return 0;
+}
+
+/**
+ * \brief Restrict a configuration space to contain only integer periods counts
+ * \param pcm PCM handle
+ * \param params Configuration space
+ * \return 0 otherwise a negative error code if configuration space would become empty
+ */
+int
+snd_pcm_hw_params_set_periods_integer (snd_pcm_t * pcm,
+ snd_pcm_hw_params_t * params)
+{
+ dbg_printf ("snd_pcm_hw_params_set_periods_integer()\n");
+ return 0;
+}
+
+/** * \brief Restrict a configuration space with a minimum periods count
+ * \param pcm PCM handle * \param params Configuration space
+ * \param val approximate minimum periods per buffer (on return filled with actual minimum)
+ * \param dir Sub unit direction (on return filled with actual direction) * \return 0 otherwise a negative error code if configuration space would become
+ empty *
+ * Wanted/actual exact minimum is <,=,> val following dir (-1,0,1) */
+int
+snd_pcm_hw_params_set_periods_min (snd_pcm_t * pcm,
+ snd_pcm_hw_params_t * params,
+ unsigned int *val, int *dir)
+{
+ dbg_printf ("snd_pcm_hw_params_set_periods_min(%x, %x)\n", val, dir);
+ return 0;
+}
+
+/**
+ * \brief Restrict a configuration space with a maximum periods count
+ * \param pcm PCM handle
+ * \param params Configuration space
+ * \param val approximate maximum periods per buffer (on return filled with actual maximum)
+ * \param dir Sub unit direction (on return filled with actual direction)
+ * \return 0 otherwise a negative error code if configuration space would become empty
+ *
+ * Wanted/actual exact maximum is <,=,> val following dir (-1,0,1)
+ */
+int
+snd_pcm_hw_params_set_periods_max (snd_pcm_t * pcm,
+ snd_pcm_hw_params_t * params,
+ unsigned int *val, int *dir)
+{
+ dbg_printf ("snd_pcm_hw_params_set_periods_max(%x, %x)\n", val, dir);
+ return 0;
+ return -EINVAL;
+}
+
+/**
+ * \brief Restrict a configuration space to contain only one rate
+ * \param pcm PCM handle
+ * \param params Configuration space
+ * \param val approximate rate
+ * \param dir Sub unit direction
+ * \return 0 otherwise a negative error code if configuration space would become empty
+ *
+ * Wanted exact value is <,=,> val following dir (-1,0,1)
+ */
+int
+snd_pcm_hw_params_set_rate (snd_pcm_t * pcm, snd_pcm_hw_params_t * params,
+ unsigned int val, int dir)
+{
+ dbg_printf2 ("snd_pcm_hw_params_set_rate(%d, %d)\n", val, dir);
+
+ params->speed = val;
+
+ if (ioctl (pcm->fd, SNDCTL_DSP_SPEED, &params->speed) < 0)
+ return -errno;
+
+ if (val != params->speed)
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * \brief Extract rate from a configuration space
+ * \param params Configuration space
+ * \param val Returned approximate rate
+ * \param dir Sub unit direction
+ * \return 0 otherwise a negative error code if not exactly one is present
+ *
+ * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
+ */
+int INTERNAL (snd_pcm_hw_params_get_rate) (const snd_pcm_hw_params_t * params,
+ unsigned int *val, int *dir)
+{
+ dbg_printf ("snd_pcm_hw_params_get_rate(params=%x)=%d\n",
+ params, params->speed);
+
+ *val = params->speed;
+ *dir = 0;
+ return 0;
+}
+
+/**
+ * \brief Restrict a configuration space to have rate nearest to a target
+ * \param pcm PCM handle
+ * \param params Configuration space
+ * \param val approximate target rate / returned approximate set rate
+ * \return 0 otherwise a negative error code if configuration space is empty
+ *
+ * target/chosen exact value is <,=,> val following dir (-1,0,1)
+ */
+int
+__snd_pcm_hw_params_set_rate_near (snd_pcm_t * pcm,
+ snd_pcm_hw_params_t * params,
+ unsigned int *val, int *dir)
+{
+ dbg_printf2 ("snd_pcm_hw_params_set_rate_near(%d)\n", *val);
+
+ params->speed = *val;
+
+ if (ioctl (pcm->fd, SNDCTL_DSP_SPEED, &params->speed) < 0)
+ return -errno;
+
+ *val = params->speed;
+ return 0;
+}
+
+/**
+ * \brief get size of #snd_pcm_hw_params_t
+ * \return size in bytes
+ */
+size_t
+snd_pcm_hw_params_sizeof ()
+{
+ return sizeof (snd_pcm_hw_params_t);
+}
+
+/**
+ * \brief set nonblock mode
+ * \param pcm PCM handle
+ * \param nonblock 0 = block, 1 = nonblock mode
+ * \return 0 on success otherwise a negative error code
+ */
+int
+snd_pcm_nonblock (snd_pcm_t * pcm, int nonblock)
+{
+ dbg_printf2 ("snd_pcm_nonblock(%d)\n", nonblock);
+
+ if (nonblock == 0)
+ return 0;
+
+ return -EINVAL;
+}
+
+/**
+ * \brief Prepare PCM for use
+ * \param pcm PCM handle
+ * \return 0 on success otherwise a negative error code
+ */
+int
+snd_pcm_prepare (snd_pcm_t * pcm)
+{
+ dbg_printf2 ("snd_pcm_prepare()\n");
+ return 0;
+}
+
+/**
+ * \brief Read interleaved frames from a PCM
+ * \param pcm PCM handle
+ * \param buffer frames containing buffer
+ * \param size frames to be written
+ * \return a positive number of frames actually read otherwise a
+ * negative error code
+ * \retval -EBADFD PCM is not in the right state (#SND_PCM_STATE_PREPARED or #SN
+D_PCM_STATE_RUNNING)
+ * \retval -EPIPE an overrun occurred
+ * \retval -ESTRPIPE a suspend event occurred (stream is suspended and waiting f
+or an application recovery)
+ *
+ * If the blocking behaviour was selected, then routine waits until
+ * all requested bytes are filled. The count of bytes can be less only
+ * if a signal or underrun occurred.
+ *
+ * If the non-blocking behaviour is selected, then routine doesn't wait at all.
+ */
+snd_pcm_sframes_t
+snd_pcm_readi (snd_pcm_t * pcm, void *buffer, snd_pcm_uframes_t size)
+{
+ int l;
+
+ dbg_printf3 ("snd_pcm_readi(%d)\n", pcm->fd);
+
+ pcm->state = SND_PCM_STATE_RUNNING;
+
+ l = size * pcm->frame_size;
+
+ if ((l = read (pcm->fd, buffer, l)) == -1)
+ return -errno;
+ return l / pcm->frame_size;
+}
+
+/** \brief Remove PCM hardware configuration and free associated resources
+ * \param pcm PCM handle
+ * \return 0 on success otherwise a negative error code
+ */
+int
+snd_pcm_hw_free (snd_pcm_t * pcm)
+{
+ dbg_printf ("snd_pcm_hw_free()\n");
+
+ return 0;
+}
+
+/**
+ * \brief Remove a PCM from a linked group
+ * \param pcm PCM handle
+ * \return 0 on success otherwise a negative error code
+ */
+int
+snd_pcm_unlink (snd_pcm_t * pcm)
+{
+ dbg_printf ("snd_pcm_unlink()\n");
+
+ return 0;
+}
+
+/**
+ * \brief Extract tick time from a configuration space
+ * \param params Configuration space
+ * \param val Returned approximate tick duration in us
+ * \param dir Sub unit direction
+ * \return 0 otherwise a negative error code if not exactly one is present
+ *
+ * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
+ */
+int INTERNAL (snd_pcm_hw_params_get_tick_time) (const snd_pcm_hw_params_t *
+ params, unsigned int *val,
+ int *dir)
+{
+ dbg_printf ("snd_pcm_hw_params_get_tick_time()\n");
+
+ *val = 1;
+ *dir = 0;
+ return 0;
+}
+
+/**
+ * \brief Write interleaved frames to a PCM
+ * \param pcm PCM handle
+ * \param buffer frames containing buffer
+ * \param size frames to be written
+ * \return a positive number of frames actually written otherwise a
+ * negative error code
+ * \retval -EBADFD PCM is not in the right state (#SND_PCM_STATE_PREPARED or #SN
+D_PCM_STATE_RUNNING)
+ * \retval -EPIPE an underrun occurred
+ * \retval -ESTRPIPE a suspend event occurred (stream is suspended and waiting f
+or an application recovery)
+ *
+ * If the blocking behaviour is selected, then routine waits until
+ * all requested bytes are played or put to the playback ring buffer.
+ * The count of bytes can be less only if a signal or underrun occurred.
+ *
+ * If the non-blocking behaviour is selected, then routine doesn't wait at all.
+ */
+snd_pcm_sframes_t
+snd_pcm_writei (snd_pcm_t * pcm, const void *buffer, snd_pcm_uframes_t size)
+{
+ int l;
+
+ dbg_printf3 ("snd_pcm_writei(%d)\n", size);
+
+ pcm->state = SND_PCM_STATE_RUNNING;
+
+ l = size * pcm->frame_size;
+
+ if ((l = write (pcm->fd, buffer, l)) == -1)
+ return -errno;
+ return l / pcm->frame_size;
+}
+
+/**
+ * \brief Resume from suspend, no samples are lost
+ * \param pcm PCM handle
+ * \return 0 on success otherwise a negative error code
+ * \retval -EAGAIN resume can't be proceed immediately (audio hardware is probab
+ly still suspended)
+ * \retval -ENOSYS hardware doesn't support this feature
+ *
+ * This function can be used when the stream is in the suspend state
+ * to do the fine resume from this state. Not all hardware supports
+ * this feature, when an -ENOSYS error is returned, use the \link ::snd_pcm_prep
+are() \endlink
+ * function to recovery.
+ */
+int
+snd_pcm_resume (snd_pcm_t * pcm)
+{
+ dbg_printf ("snd_pcm_resume()\n");
+ return -EINVAL;
+}
+
+/**
+ * \brief allocate an invalid #snd_pcm_status_t using standard malloc
+ * \param ptr returned pointer
+ * \return 0 on success otherwise negative error code
+ */
+int
+snd_pcm_status_malloc (snd_pcm_status_t ** ptr)
+{
+ assert (ptr);
+ *ptr = calloc (1, sizeof (snd_pcm_status_t));
+ if (!*ptr)
+ return -ENOMEM;
+ return 0;
+}
+
+/**
+ * \brief frees a previously allocated #snd_pcm_status_t
+ * \param pointer to object to free
+ */
+void
+snd_pcm_status_free (snd_pcm_status_t * obj)
+{
+ free (obj);
+}
+
+
+/**
+ * \brief Obtain status (runtime) information for PCM handle
+ * \param pcm PCM handle
+ * \param status Status container
+ * \return 0 on success otherwise a negative error code
+ */
+int
+snd_pcm_status (snd_pcm_t * pcm, snd_pcm_status_t * status)
+{
+ dbg_printf ("snd_pcm_status()\n");
+ return -EINVAL;
+}
+
+/**
+ * \brief Get state from a PCM status container (see #snd_pcm_state)
+ * \return PCM state
+ */
+snd_pcm_state_t
+snd_pcm_status_get_state (const snd_pcm_status_t * obj)
+{
+ dbg_printf ("snd_pcm_status_get_state()\n");
+ return -EINVAL;
+}
+
+/**
+ * \brief Get number of frames available from a PCM status container (see #snd_pcm_avail_update)
+ * \return Number of frames ready to be read/written
+ */
+snd_pcm_uframes_t
+snd_pcm_status_get_avail (const snd_pcm_status_t * obj)
+{
+ dbg_printf ("snd_pcm_status_get_avail()\n");
+
+ return 1;
+}
+
+/**
+ * \brief get size of #snd_pcm_status_t
+ * \return size in bytes
+ */
+size_t
+snd_pcm_status_sizeof ()
+{
+ return sizeof (snd_pcm_status_t);
+}
+
+/**
+ * \brief Dump PCM info
+ * \param pcm PCM handle
+ * \param out Output handle
+ * \return 0 on success otherwise a negative error code
+ */
+int
+snd_pcm_dump (snd_pcm_t * pcm, snd_output_t * out)
+{
+ dbg_printf ("snd_pcm_dump()\n");
+ return 0;
+}
+
+void
+snd_pcm_hw_params_copy (snd_pcm_hw_params_t * dst,
+ const snd_pcm_hw_params_t * src)
+{
+ memcpy (dst, src, sizeof (*dst));
+}
+
+void
+snd_pcm_hw_params_free (snd_pcm_hw_params_t * p)
+{
+ free (p);
+}
+
+int
+snd_pcm_hw_params_can_mmap_sample_resolution (const snd_pcm_hw_params_t *
+ params)
+{
+ return 0;
+}
+
+int
+snd_pcm_hw_params_can_overrange (const snd_pcm_hw_params_t * params)
+{
+ return 0;
+}
+
+int
+snd_pcm_hw_params_can_pause (const snd_pcm_hw_params_t * params)
+{
+ return 0;
+}
+
+int
+snd_pcm_hw_params_can_resume (const snd_pcm_hw_params_t * params)
+{
+ return 0;
+}
+
+int
+snd_pcm_hw_params_can_sync_start (const snd_pcm_hw_params_t * params)
+{
+ return 1;
+}
+
+int
+snd_pcm_hw_params_get_channels (const snd_pcm_hw_params_t * params,
+ unsigned int *val)
+{
+ *val = params->channels;
+ return 0;
+}
+
+int INTERNAL (snd_pcm_hw_params_get_channels_min) (const snd_pcm_hw_params_t *
+ params, unsigned int *val)
+{
+ *val = params->info->min_channels;
+ return 0;
+}
+
+int INTERNAL (snd_pcm_hw_params_get_channels_max) (const snd_pcm_hw_params_t *
+ params, unsigned int *val)
+{
+ *val = params->info->max_channels;
+ return 0;
+}
+
+int INTERNAL (snd_pcm_hw_params_get_rate_min) (const snd_pcm_hw_params_t *
+ params, unsigned int *val,
+ int *dir)
+{
+ *val = params->info->min_rate;
+ return 0;
+}
+
+int INTERNAL (snd_pcm_hw_params_get_rate_max) (const snd_pcm_hw_params_t *
+ params, unsigned int *val,
+ int *dir)
+{
+ *val = params->info->max_rate;
+ return 0;
+}
+
+// int snd_pcm_hw_params_get_(const snd_pcm_hw_params_t *params, unsigned int *val) { return 0;}
+
+/**
+ * \brief get name of PCM sample format
+ * \param format PCM sample format
+ * \return ascii name of PCM sample format
+ */
+const char *
+snd_pcm_format_name (snd_pcm_format_t format)
+{
+ if (format > SND_PCM_FORMAT_LAST)
+ return NULL;
+ return snd_pcm_format_names[format];
+}
+
+/**
+ * \brief Return PCM state
+ * \param pcm PCM handle
+ * \return PCM state #snd_pcm_state_t of given PCM handle
+ *
+ * This is a faster way to obtain only the PCM state without calling
+ * \link ::snd_pcm_status() \endlink.
+ */
+snd_pcm_state_t
+snd_pcm_state (snd_pcm_t * pcm)
+{
+ dbg_printf3 ("snd_pcm_state()\n");
+ return pcm->state;
+}
+
+/**
+ * \brief allocate an invalid #snd_pcm_info_t using standard malloc
+ * \param ptr returned pointer
+ * \return 0 on success otherwise negative error code
+ */
+int
+snd_pcm_info_malloc (snd_pcm_info_t ** ptr)
+{
+ assert (ptr);
+ *ptr = calloc (1, sizeof (snd_pcm_info_t));
+ if (!*ptr)
+ return -ENOMEM;
+ return 0;
+}
+
+/**
+ * \brief frees a previously allocated #snd_pcm_info_t
+ * \param pointer to object to free
+ */
+void
+snd_pcm_info_free (snd_pcm_info_t * obj)
+{
+ free (obj);
+}
+
+
+/**
+ * \brief Obtain general (static) information for PCM handle
+ * \param pcm PCM handle
+ * \param info Information container
+ * \return 0 on success otherwise a negative error code
+ */
+int
+snd_pcm_info (snd_pcm_t * pcm, snd_pcm_info_t * info)
+{
+ dbg_printf ("snd_pcm_info()\n");
+ memset (info, 0, sizeof (*info));
+ info->ainfo = &pcm->info;
+
+ return 0;
+}
+
+/**
+ * \brief Get card from a PCM info container
+ * \param obj PCM info container
+ * \return card number otherwise a negative error code if not associable to a card
+ */
+int
+snd_pcm_info_get_card (const snd_pcm_info_t * obj)
+{
+ dbg_printf ("snd_pcm_info_get_card()\n");
+ return obj->ainfo->card_number;
+}
+
+/**
+ * \brief Get device from a PCM info container
+ * \param obj PCM info container
+ * \return device number
+ */
+unsigned int
+snd_pcm_info_get_device (const snd_pcm_info_t * obj)
+{
+ dbg_printf ("snd_pcm_info_get_device()\n");
+ return obj->ainfo->dev;
+}
+
+/**
+ * \brief Get name from a PCM info container
+ * \param obj PCM info container
+ * \return name of PCM
+ */
+const char *
+snd_pcm_info_get_name (const snd_pcm_info_t * obj)
+{
+ dbg_printf ("snd_pcm_info_get_name()\n");
+
+ return obj->ainfo->name;
+}
+
+/**
+ * \brief Get subdevice from a PCM info container
+ * \param obj PCM info container
+ * \return subdevice number
+ */
+unsigned int
+snd_pcm_info_get_subdevice (const snd_pcm_info_t * obj)
+{
+ dbg_printf ("snd_pcm_info_get_subdevice()\n");
+ return 0;
+}
+
+/**
+ * \brief Set wanted device inside a PCM info container (see #snd_ctl_pcm_info)
+ * \param obj PCM info container
+ * \param val Device number
+ */
+void
+snd_pcm_info_set_device (snd_pcm_info_t * obj, unsigned int val)
+{
+ dbg_printf ("snd_pcm_info_set_device()\n");
+}
+
+/**
+ * \brief Set wanted subdevice inside a PCM info container (see #snd_ctl_pcm_info)
+ * \param obj PCM info container
+ * \param val Subdevice number
+ */
+void
+snd_pcm_info_set_subdevice (snd_pcm_info_t * obj, unsigned int val)
+{
+ dbg_printf ("snd_pcm_info_set_subdevice()\n");
+}
+
+void
+snd_pcm_info_set_stream (snd_pcm_info_t * obj, snd_pcm_stream_t val)
+{
+ dbg_printf ("snd_pcm_info_set_stream()\n");
+}
+
+/**
+ * \brief get size of #snd_pcm_info_t
+ * \return size in bytes
+ */
+size_t
+snd_pcm_info_sizeof ()
+{
+ return sizeof (snd_pcm_info_t);
+}
+
+
+/**
+ * \brief Return number of frames ready to be read/written
+ * \param pcm PCM handle
+ * \return a positive number of frames ready otherwise a negative
+ * error code
+ *
+ * On capture does all the actions needed to transport to application
+ * level all the ready frames across underlying layers.
+ *
+ * Using of this function is useless for the standard read/write
+ * operations. Use it only for mmap access. See to #snd_pcm_delay.
+ */
+snd_pcm_sframes_t
+snd_pcm_avail_update (snd_pcm_t * pcm)
+{
+ audio_buf_info bi;
+
+ if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
+ {
+ if (ioctl (pcm->fd, SNDCTL_DSP_GETOSPACE, &bi) == -1)
+ return -errno;
+ }
+ else
+ {
+ if (ioctl (pcm->fd, SNDCTL_DSP_GETISPACE, &bi) == -1)
+ return -errno;
+ }
+
+ dbg_printf3 ("snd_pcm_avail_update(pcm=%x)=%d\n", pcm,
+ bi.bytes / pcm->frame_size);
+ return bi.bytes / pcm->frame_size;
+}
+
+/**
+ * \brief Obtain delay for a running PCM handle
+ * \param pcm PCM handle
+ * \param delayp Returned delay in frames
+ * \return 0 on success otherwise a negative error code
+ *
+ * Delay is distance between current application frame position and
+ * sound frame position.
+ * It's positive and less than buffer size in normal situation,
+ * negative on playback underrun and greater than buffer size on
+ * capture overrun.
+ *
+ * Note this function does not update the actual r/w pointer
+ * for applications. The function #snd_pcm_avail_update()
+ * have to be called before any begin+commit operation.
+ */
+int
+snd_pcm_delay (snd_pcm_t * pcm, snd_pcm_sframes_t * delayp)
+{
+ int tmp;
+
+ if (ioctl (pcm->fd, SNDCTL_DSP_GETODELAY, &tmp) < 0)
+ return -errno;
+
+ *delayp = tmp / pcm->frame_size;
+ return 0;
+}
+
+/**
+ * \brief Return bits needed to store a PCM sample
+ * \param format Sample format
+ * \return bits per sample, a negative error code if not applicable
+ */
+int
+snd_pcm_format_physical_width (snd_pcm_format_t format)
+{
+ switch (format)
+ {
+ case SNDRV_PCM_FORMAT_S8:
+ case SNDRV_PCM_FORMAT_U8:
+ return 8;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ case SNDRV_PCM_FORMAT_S16_BE:
+ case SNDRV_PCM_FORMAT_U16_LE:
+ case SNDRV_PCM_FORMAT_U16_BE:
+ return 16;
+ case SNDRV_PCM_FORMAT_S18_3LE:
+ case SNDRV_PCM_FORMAT_S18_3BE:
+ case SNDRV_PCM_FORMAT_U18_3LE:
+ case SNDRV_PCM_FORMAT_U18_3BE:
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ case SNDRV_PCM_FORMAT_S20_3BE:
+ case SNDRV_PCM_FORMAT_U20_3LE:
+ case SNDRV_PCM_FORMAT_U20_3BE:
+ case SNDRV_PCM_FORMAT_S24_3LE:
+ case SNDRV_PCM_FORMAT_S24_3BE:
+ case SNDRV_PCM_FORMAT_U24_3LE:
+ case SNDRV_PCM_FORMAT_U24_3BE:
+ return 24;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ case SNDRV_PCM_FORMAT_S24_BE:
+ case SNDRV_PCM_FORMAT_U24_LE:
+ case SNDRV_PCM_FORMAT_U24_BE:
+ case SNDRV_PCM_FORMAT_S32_LE:
+ case SNDRV_PCM_FORMAT_S32_BE:
+ case SNDRV_PCM_FORMAT_U32_LE:
+ case SNDRV_PCM_FORMAT_U32_BE:
+ case SNDRV_PCM_FORMAT_FLOAT_LE:
+ case SNDRV_PCM_FORMAT_FLOAT_BE:
+ case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
+ case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
+ return 32;
+ case SNDRV_PCM_FORMAT_FLOAT64_LE:
+ case SNDRV_PCM_FORMAT_FLOAT64_BE:
+ return 64;
+ case SNDRV_PCM_FORMAT_MU_LAW:
+ case SNDRV_PCM_FORMAT_A_LAW:
+ return 8;
+ case SNDRV_PCM_FORMAT_IMA_ADPCM:
+ return 4;
+ default:
+ return -EINVAL;
+ }
+}
+
+/**
+ * \brief Return bytes needed to store a quantity of PCM sample
+ * \param format Sample format
+ * \param samples Samples count
+ * \return bytes needed, a negative error code if not integer or unknown
+ */
+ssize_t
+snd_pcm_format_size (snd_pcm_format_t format, size_t samples)
+{
+ switch (format)
+ {
+ case SNDRV_PCM_FORMAT_S8:
+ case SNDRV_PCM_FORMAT_U8:
+ return samples;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ case SNDRV_PCM_FORMAT_S16_BE:
+ case SNDRV_PCM_FORMAT_U16_LE:
+ case SNDRV_PCM_FORMAT_U16_BE:
+ return samples * 2;
+ case SNDRV_PCM_FORMAT_S18_3LE:
+ case SNDRV_PCM_FORMAT_S18_3BE:
+ case SNDRV_PCM_FORMAT_U18_3LE:
+ case SNDRV_PCM_FORMAT_U18_3BE:
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ case SNDRV_PCM_FORMAT_S20_3BE:
+ case SNDRV_PCM_FORMAT_U20_3LE:
+ case SNDRV_PCM_FORMAT_U20_3BE:
+ case SNDRV_PCM_FORMAT_S24_3LE:
+ case SNDRV_PCM_FORMAT_S24_3BE:
+ case SNDRV_PCM_FORMAT_U24_3LE:
+ case SNDRV_PCM_FORMAT_U24_3BE:
+ return samples * 3;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ case SNDRV_PCM_FORMAT_S24_BE:
+ case SNDRV_PCM_FORMAT_U24_LE:
+ case SNDRV_PCM_FORMAT_U24_BE:
+ case SNDRV_PCM_FORMAT_S32_LE:
+ case SNDRV_PCM_FORMAT_S32_BE:
+ case SNDRV_PCM_FORMAT_U32_LE:
+ case SNDRV_PCM_FORMAT_U32_BE:
+ case SNDRV_PCM_FORMAT_FLOAT_LE:
+ case SNDRV_PCM_FORMAT_FLOAT_BE:
+ return samples * 4;
+ case SNDRV_PCM_FORMAT_FLOAT64_LE:
+ case SNDRV_PCM_FORMAT_FLOAT64_BE:
+ return samples * 8;
+ case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
+ case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
+ return samples * 4;
+ case SNDRV_PCM_FORMAT_MU_LAW:
+ case SNDRV_PCM_FORMAT_A_LAW:
+ return samples;
+ case SNDRV_PCM_FORMAT_IMA_ADPCM:
+ if (samples & 1)
+ return -EINVAL;
+ return samples / 2;
+ default:
+ assert (0);
+ return -EINVAL;
+ }
+}
+
+/**
+ * \brief Dump a PCM hardware configuration space
+ * \param params Configuration space
+ * \param out Output handle
+ * \return 0 on success otherwise a negative error code
+ */
+int
+snd_pcm_hw_params_dump (snd_pcm_hw_params_t * params, snd_output_t * out)
+{
+ return 0;
+}
+
+/**
+ * \brief Extract buffer size from a configuration space
+ * \param params Configuration space
+ * \param val Returned buffer size in frames
+ * \return 0 otherwise a negative error code if not exactly one is present
+ */
+int
+__snd_pcm_hw_params_get_buffer_size (const snd_pcm_hw_params_t * params,
+ snd_pcm_uframes_t * val)
+{
+ *val = 65536;
+
+ return 0;
+}
+
+int
+snd_pcm_hw_params_get_buffer_size_min (const snd_pcm_hw_params_t * params,
+ snd_pcm_uframes_t * val)
+{
+ *val = 65536;
+
+ return 0;
+}
+
+int
+snd_pcm_hw_params_get_buffer_size_max (const snd_pcm_hw_params_t * params,
+ snd_pcm_uframes_t * val)
+{
+ *val = 65536;
+
+ return 0;
+}
+
+/**
+ * \brief Extract access type from a configuration space
+ * \param params Configuration space
+ * \param access Returned value
+ * \return access type otherwise a negative error code if not exactly one is present
+ */
+int INTERNAL (snd_pcm_hw_params_get_access) (const snd_pcm_hw_params_t *
+ params,
+ snd_pcm_access_t * access)
+{
+ dbg_printf ("snd_pcm_hw_params_get_access()\n"), *access = params->access;
+
+ return 0;
+}
+
+/**
+ * \brief Extract period size from a configuration space
+ * \param params Configuration space
+ * \param val Returned approximate period size in frames
+ * \param dir Sub unit direction
+ * \return 0 otherwise a negative error code if not exactly one is present
+ *
+ * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
+ */
+int
+__snd_pcm_hw_params_get_period_size (const snd_pcm_hw_params_t * params,
+ snd_pcm_uframes_t * val, int *dir)
+{
+ dbg_printf ("snd_pcm_hw_params_get_period_size(params=%x)=%d\n",
+ params, params->pcm->period_size);
+ *val = params->pcm->period_size;
+ if (dir) *dir = 0;
+ return 0;
+}
+
+int
+snd_pcm_hw_params_get_period_size_min (const snd_pcm_hw_params_t * params,
+ snd_pcm_uframes_t * val, int *dir)
+{
+ dbg_printf ("snd_pcm_hw_params_get_period_size_min(params=%x)=%d\n",
+ params, params->pcm->period_size);
+ *val = params->pcm->period_size;
+ if (dir) *dir = 0;
+ return 0;
+}
+
+int
+snd_pcm_hw_params_get_period_size_max (const snd_pcm_hw_params_t * params,
+ snd_pcm_uframes_t * val, int *dir)
+{
+ dbg_printf ("snd_pcm_hw_params_get_period_size_min(params=%x)=%d\n",
+ params, params->pcm->period_size);
+ *val = params->pcm->period_size;
+ if (dir) *dir = 0;
+ return 0;
+}
+
+/**
+ * \brief Extract periods from a configuration space
+ * \param params Configuration space
+ * \param val approximate periods per buffer
+ * \param dir Sub unit direction
+ * \return 0 otherwise a negative error code if not exactly one is present
+ *
+ * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
+ */
+int INTERNAL (snd_pcm_hw_params_get_periods) (const snd_pcm_hw_params_t *
+ params, unsigned int *val,
+ int *dir)
+{
+ dbg_printf ("snd_pcm_hw_params_get_periods(params=%x)=%d\n",
+ params, params->pcm->periods);
+
+ *val = params->pcm->periods;
+
+ return 0;
+}
+
+/**
+ * \brief Restrict a configuration space to have period size nearest to a target * \param pcm PCM handle
+ * \param params Configuration space
+ * \param val approximate target period size in frames / returned chosen approximate target period size
+ * \return 0 otherwise a negative error code if configuration space is empty
+ *
+ * target/chosen exact value is <,=,> val following dir (-1,0,1)
+ */
+int
+__snd_pcm_hw_params_set_period_size_near (snd_pcm_t * pcm,
+ snd_pcm_hw_params_t * params,
+ snd_pcm_uframes_t * val, int *dir)
+{
+ dbg_printf
+ ("snd_pcm_hw_params_set_period_size_near(pcm=%x, params=%x, val=%d, dir=%d)\n",
+ pcm, params, *val, dir?*dir:-1);
+ pcm->period_size = *val;
+ return 0;
+}
+
+/**
+ * \brief Restrict a configuration space to have buffer time nearest to a target * \param pcm PCM handle
+ * \param params Configuration space
+ * \param val approximate target buffer duration in us / returned chosen approximate target buffer duration
+ * \return 0 otherwise a negative error code if configuration space is empty
+ *
+ * target/chosen exact value is <,=,> val following dir (-1,0,1)
+ */
+int
+__snd_pcm_hw_params_set_period_time_near (snd_pcm_t * pcm,
+ snd_pcm_hw_params_t * params,
+ unsigned int *val, int *dir)
+{
+ dbg_printf2 ("snd_pcm_hw_params_set_period_time_near()\n");
+ return 0;
+}
+
+/**
+ * \brief Application request to access a portion of direct (mmap) area
+ * \param pcm PCM handle
+ * \param areas Returned mmap channel areas
+ * \param offset Returned mmap area offset in area steps (== frames)
+ * \param frames mmap area portion size in frames (wanted on entry, contiguous available on exit)
+ * \return 0 on success otherwise a negative error code
+ *
+ * It is necessary to call the snd_pcm_avail_update() function directly before
+ * this call. Otherwise, this function can return a wrong count of available frames.
+ *
+ * The function should be called before a sample-direct area can be accessed.
+ * The resulting size parameter is always less or equal to the input count of frames
+ * and can be zero, if no frames can be processed (the ring buffer is full).
+ *
+ * See the snd_pcm_mmap_commit() function to finish the frame processing in
+ * the direct areas.
+ */
+int
+snd_pcm_mmap_begin (snd_pcm_t * pcm,
+ const snd_pcm_channel_area_t ** areas,
+ snd_pcm_uframes_t * offset, snd_pcm_uframes_t * frames)
+{
+ dbg_printf2 ("snd_pcm_mmap_begin(frames=%d)\n", *frames);
+ if (pcm->area == NULL)
+ {
+ pcm->area = malloc (sizeof (*pcm->area) * pcm->channels);
+ pcm->area[0].addr = malloc (65536);
+ pcm->area[0].first = 0;
+ pcm->area[0].step = pcm->frame_size * 8;
+ pcm->area[1].addr = pcm->area[0].addr + pcm->sample_size;
+ pcm->area[1].first = 0;
+ pcm->area[1].step = pcm->frame_size * 8;
+ }
+
+ *areas = pcm->area;
+ *offset = 0;
+ if (*frames * pcm->frame_size > 65536)
+ *frames = 65536 / pcm->frame_size;
+ return 0;
+}
+
+/**
+ * \brief Application has completed the access to area requested with #snd_pcm_mmap_begin
+ * \param pcm PCM handle
+ * \param offset area offset in area steps (== frames)
+ * \param size area portion size in frames
+ * \return count of transferred frames otherwise a negative error code
+ *
+ * You should pass this function the offset value that
+ * snd_pcm_mmap_begin() returned. The frames parameter should hold the
+ * number of frames you have written or read to/from the audio
+ * buffer. The frames parameter must never exceed the contiguous frames
+ * count that snd_pcm_mmap_begin() returned. Each call to snd_pcm_mmap_begin()
+ * must be followed by a call to snd_pcm_mmap_commit().
+ *
+ * Example:
+\code
+ double phase = 0;
+ const snd_pcm_area_t *areas;
+ snd_pcm_sframes_t avail, size, commitres;
+ snd_pcm_uframes_t offset, frames;
+ int err;
+
+ avail = snd_pcm_avail_update(pcm);
+ if (avail < 0)
+ error(avail);
+ // at this point, we can transfer at least 'avail' frames
+
+ // we want to process frames in chunks (period_size)
+ if (avail < period_size)
+ goto _skip;
+ size = period_size;
+ // it is possible that contiguous areas are smaller, thus we use a loop
+ while (size > 0) {
+ frames = size;
+
+ err = snd_pcm_mmap_begin(pcm_handle, &areas, &offset, &frames);
+ if (err < 0)
+ error(err);
+ // this function fills the areas from offset with count of frames
+ generate_sine(areas, offset, frames, &phase);
+ commitres = snd_pcm_mmap_commit(pcm_handle, offset, frames);
+ if (commitres < 0 || commitres != frames)
+ error(commitres >= 0 ? -EPIPE : commitres);
+
+ size -= frames;
+ }
+ _skip:
+\endcode
+ *
+ * Look to the \ref example_test_pcm "Sine-wave generator" example
+ * for more details about the generate_sine function.
+ */
+snd_pcm_sframes_t
+snd_pcm_mmap_commit (snd_pcm_t * pcm,
+ snd_pcm_uframes_t offset, snd_pcm_uframes_t frames)
+{
+ dbg_printf2 ("snd_pcm_mmap_commit(frames=%d, offs=%d)\n", frames, offset);
+
+ if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
+ return snd_pcm_writei (pcm, pcm->area[0].addr, frames);
+
+ if (pcm->stream == SND_PCM_STREAM_CAPTURE)
+ return snd_pcm_readi (pcm, pcm->area[0].addr, frames);
+
+ return -EFAULT;
+}
+
+/**
+ * \brief Restrict a configuration space to have buffer time nearest to a target * \param pcm PCM handle
+ * \param params Configuration space
+ * \param val approximate target buffer duration in us / returned chosen approximate target buffer duration
+ * \return 0 otherwise a negative error code if configuration space is empty
+ *
+ * target/chosen exact value is <,=,> val following dir (-1,0,1)
+ */
+int
+__snd_pcm_hw_params_set_buffer_time_near (snd_pcm_t * pcm,
+ snd_pcm_hw_params_t * params,
+ unsigned int *val, int *dir)
+{
+ *val = 10;
+ dbg_printf2 ("snd_pcm_hw_params_set_buffer_time_near()\n");
+ return 0;
+}
+
+/**
+ * \brief Pause/resume PCM
+ * \param pcm PCM handle
+ * \param pause 0 = resume, 1 = pause
+ * \return 0 on success otherwise a negative error code
+ *
+ * Note that this function works only on the hardware which supports
+ * pause feature. You can check it via \link ::snd_pcm_hw_params_can_pause() \endlink
+ * function.
+ */
+int
+snd_pcm_pause (snd_pcm_t * pcm, int enable)
+{
+ dbg_printf ("snd_pcm_pause()\n");
+ return -EINVAL;
+}
+
+/**
+ * \brief Start a PCM
+ * \param pcm PCM handle
+ * \return 0 on success otherwise a negative error code
+ */
+int
+snd_pcm_start (snd_pcm_t * pcm)
+{
+ dbg_printf ("snd_pcm_start()\n");
+ return 0;
+}
+
+/**
+ * \brief Convert samples in bytes for a PCM
+ * \param pcm PCM handle
+ * \param samples quantity in samples
+ * \return quantity expressed in bytes
+ */
+ssize_t
+snd_pcm_samples_to_bytes (snd_pcm_t * pcm, long samples)
+{
+ dbg_printf2 ("snd_pcm_samples_to_bytes(%d)=%d\n", samples,
+ samples * pcm->sample_size);
+ return samples * pcm->sample_size;
+}
+
+
+/**
+ * \brief Dump status
+ * \param status Status container
+ * \param out Output handle
+ * \return 0 on success otherwise a negative error code
+ */
+int
+snd_pcm_status_dump (snd_pcm_status_t * status, snd_output_t * out)
+{
+ return 0;
+}
+
+/** \brief Install PCM software configuration defined by params
+ * \param pcm PCM handle
+ * \param params Configuration container
+ * \return 0 on success otherwise a negative error code
+ */
+int
+snd_pcm_sw_params (snd_pcm_t * pcm, snd_pcm_sw_params_t * params)
+{
+ dbg_printf2 ("snd_pcm_sw_params()\n");
+ // NOP
+ return 0;
+}
+
+/**
+ * \brief Return current software configuration for a PCM
+ * \param pcm PCM handle
+ * \param params Software configuration container
+ * \return 0 on success otherwise a negative error code
+ */
+int
+snd_pcm_sw_params_current (snd_pcm_t * pcm, snd_pcm_sw_params_t * params)
+{
+ dbg_printf2 ("snd_pcm_sw_params_current()\n");
+ // NOP
+ return 0;
+}
+
+/**
+ * \brief Dump a software configuration
+ * \param params Software configuration container
+ * \param out Output handle
+ * \return 0 on success otherwise a negative error code
+ */
+int
+snd_pcm_sw_params_dump (snd_pcm_sw_params_t * params, snd_output_t * out)
+{
+ return 0;
+}
+
+/**
+ * \brief Set start threshold inside a software configuration container
+ * \param pcm PCM handle
+ * \param params Software configuration container
+ * \param val Start threshold in frames
+ * \return 0 otherwise a negative error code
+ *
+ * PCM is automatically started when playback frames available to PCM
+ * are >= threshold or when requested capture frames are >= threshold
+ */
+int
+snd_pcm_sw_params_set_start_threshold (snd_pcm_t * pcm,
+ snd_pcm_sw_params_t * params,
+ snd_pcm_uframes_t val)
+{
+ dbg_printf2 ("snd_pcm_sw_params_set_start_threshold(%d)\n", val);
+ // NOP
+ return 0;
+}
+
+/**
+ * \brief get size of #snd_pcm_sw_params_t
+ * \return size in bytes
+ */
+size_t
+snd_pcm_sw_params_sizeof ()
+{
+ return sizeof (snd_pcm_sw_params_t);
+}
+
+/**
+ * \brief Restrict a configuration space to have periods count nearest to a target
+ * \param pcm PCM handle
+ * \param params Configuration space
+ * \param val approximate target periods per buffer / returned chosen approximate target periods per buffer
+ * \return 0 otherwise a negative error code if configuration space is empty
+ *
+ * target/chosen exact value is <,=,> val following dir (-1,0,1)
+ */
+int INTERNAL (snd_pcm_hw_params_set_periods_near) (snd_pcm_t * pcm,
+ snd_pcm_hw_params_t *
+ params, unsigned int *val,
+ int *dir)
+{
+ dbg_printf
+ ("snd_pcm_hw_params_set_periods_near(pcm=%x, params=%x, val=%d, dir=%d)\n");
+ pcm->periods = *val;
+ return 0;
+}
+
+/**
+ * \brief get poll descriptors
+ * \param pcm PCM handle
+ * \param pfds array of poll descriptors
+ * \param space space in the poll descriptor array
+ * \return count of filled descriptors
+ *
+ * This function fills the given poll descriptor structs for the specified
+ * PCM handle. The poll desctiptor array should have the size returned by
+ * \link ::snd_pcm_poll_descriptors_count() \endlink function.
+ *
+ * The result is intended for direct use with the poll() syscall.
+ *
+ * For reading the returned events of poll descriptor after poll() system
+ * call, use \link ::snd_pcm_poll_descriptors_revents() \endlink function.
+ * The field values in pollfd structs may be bogus regarding the stream
+ * direction from the application perspective (POLLIN might not imply read
+ * direction and POLLOUT might not imply write), but
+ * the \link ::snd_pcm_poll_descriptors_revents() \endlink function
+ * does the right "demangling".
+ *
+ * You can use output from this function as arguments for the select()
+ * syscall, too.
+ */
+int
+snd_pcm_poll_descriptors (snd_pcm_t * pcm, struct pollfd *pfds,
+ unsigned int space)
+{
+ dbg_printf2 ("snd_pcm_poll_descriptors(pcm=%x)\n", pcm);
+
+ pfds->fd = pcm->fd;
+ pfds->events = 0;
+ pfds->revents = 0;
+
+ if (pcm->oss_mode == O_WRONLY || pcm->oss_mode == O_RDWR)
+ pfds->events = POLLOUT;
+ if (pcm->oss_mode == O_RDONLY || pcm->oss_mode == O_RDWR)
+ pfds->events = POLLIN;
+
+ return 1;
+}
+
+/**
+ * \brief get count of poll descriptors for PCM handle
+ * \param pcm PCM handle
+ * \return count of poll descriptors
+ */
+int
+snd_pcm_poll_descriptors_count (snd_pcm_t * pcm)
+{
+ dbg_printf ("snd_pcm_poll_descriptors_count()\n");
+
+ return 1;
+}
+
+/**
+ * \brief get returned events from poll descriptors
+ * \param pcm PCM handle
+ * \param pfds array of poll descriptors
+ * \param nfds count of poll descriptors
+ * \param revents returned events
+ * \return zero if success, otherwise a negative error code
+ *
+ * This function does "demangling" of the revents mask returned from
+ * the poll() syscall to correct semantics (POLLIN = read, POLLOUT = write).
+ *
+ * Note: The null event also exists. Even if poll() or select()
+ * syscall returned that some events are waiting, this function might
+ * return empty set of events. In this case, application should
+ * do next event waiting using poll() or select().
+ */
+int
+snd_pcm_poll_descriptors_revents (snd_pcm_t * pcm, struct pollfd *pfds,
+ unsigned int nfds, unsigned short *revents)
+{
+ dbg_printf3 ("snd_pcm_poll_descriptors_revents()\n");
+
+ *revents = pfds->revents;
+ return 0;
+}
+
+/**
+ * \brief allocate an invalid #snd_pcm_hw_params_t using standard malloc
+ * \param ptr returned pointer
+ * \return 0 on success otherwise negative error code
+ */
+int
+snd_pcm_hw_params_malloc (snd_pcm_hw_params_t ** ptr)
+{
+ *ptr = calloc (1, sizeof (snd_pcm_hw_params_t));
+ if (!*ptr)
+ return -ENOMEM;
+ return 0;
+}
+
+/**
+ * \brief frees a previously allocated #snd_pcm_sw_params_t
+ * \param pointer to object to free
+ */
+void
+snd_pcm_sw_params_free (snd_pcm_sw_params_t * obj)
+{
+ free (obj);
+}
+
+/**
+ * \brief Write non interleaved frames to a PCM
+ * \param pcm PCM handle
+ * \param bufs frames containing buffers (one for each channel)
+ * \param size frames to be written
+ * \return a positive number of frames actually written otherwise a
+ * negative error code
+ * \retval -EBADFD PCM is not in the right state (#SND_PCM_STATE_PREPARED or #SND_PCM_STATE_RUNNING)
+ * \retval -EPIPE an underrun occurred
+ * \retval -ESTRPIPE a suspend event occurred (stream is suspended and waiting for an application recovery)
+ *
+ * If the blocking behaviour is selected, then routine waits until
+ * all requested bytes are played or put to the playback ring buffer.
+ * The count of bytes can be less only if a signal or underrun occurred.
+ *
+ * If the non-blocking behaviour is selected, then routine doesn't wait at all.
+ */
+snd_pcm_sframes_t
+snd_pcm_writen (snd_pcm_t * pcm, void **bufs, snd_pcm_uframes_t size)
+{
+ dbg_printf ("snd_pcm_writen()\n");
+ // Not supported
+ return -EINVAL;
+}
+
+/**
+ * \brief Read non interleaved frames to a PCM
+ * \param pcm PCM handle
+ * \param bufs frames containing buffers (one for each channel)
+ * \param size frames to be written
+ * \return a positive number of frames actually read otherwise a
+ * negative error code
+ * \retval -EBADFD PCM is not in the right state (#SND_PCM_STATE_PREPARED or #SND_PCM_STATE_RUNNING)
+ * \retval -EPIPE an overrun occurred
+ * \retval -ESTRPIPE a suspend event occurred (stream is suspended and waiting for an application recovery)
+ *
+ * If the blocking behaviour was selected, then routine waits until
+ * all requested bytes are filled. The count of bytes can be less only
+ * if a signal or underrun occurred.
+ *
+ * If the non-blocking behaviour is selected, then routine doesn't wait at all.
+ */
+snd_pcm_sframes_t
+snd_pcm_readn (snd_pcm_t * pcm, void **bufs, snd_pcm_uframes_t size)
+{
+ dbg_printf ("snd_pcm_readn()\n");
+ // Not supported
+ return -EINVAL;
+}
+
+/**
+ * \brief Get trigger timestamp from a PCM status container
+ * \param ptr Pointer to returned timestamp
+ */
+void
+snd_pcm_status_get_trigger_tstamp (const snd_pcm_status_t * obj,
+ snd_timestamp_t * ptr)
+{
+ dbg_printf ("snd_pcm_status_get_trigger_tstamp()\n");
+ ptr->tv_sec = 0;
+ ptr->tv_usec = 0;
+}
+
+/**
+ * \brief Set xfer align inside a software configuration container
+ * \param pcm PCM handle
+ * \param params Software configuration container
+ * \param val Chunk size (frames are attempted to be transferred in chunks)
+ * \return 0 otherwise a negative error code
+ */
+int
+snd_pcm_sw_params_set_xfer_align (snd_pcm_t * pcm,
+ snd_pcm_sw_params_t * params,
+ snd_pcm_uframes_t val)
+{
+ dbg_printf ("snd_pcm_sw_params_set_xfer_align(%d)\n", val);
+ // TODO
+ return 0;
+}
+
+/**
+ * \brief Get xfer align from a software configuration container
+ * \param params Software configuration container
+ * \param val returned chunk size (frames are attempted to be transferred in chunks)
+ * \param 0 otherwise a negative error code
+ */
+int INTERNAL (snd_pcm_sw_params_get_xfer_align) (const snd_pcm_sw_params_t *
+ params,
+ snd_pcm_uframes_t * val)
+{
+ dbg_printf ("snd_pcm_sw_params_get_xfer_align()\n");
+
+ return 8;
+}
+
+/**
+ * \brief Set avail min inside a software configuration container
+ * \param pcm PCM handle
+ * \param params Software configuration container
+ * \param val Minimum avail frames to consider PCM ready
+ * \return 0 otherwise a negative error code
+ *
+ * Note: This is similar to setting an OSS wakeup point. The valid
+ * values for 'val' are determined by the specific hardware. Most PC
+ * sound cards can only accept power of 2 frame counts (i.e. 512,
+ * 1024, 2048). You cannot use this as a high resolution timer - it
+ * is limited to how often the sound card hardware raises an
+ * interrupt. Note that you can greatly improve the reponses using
+ * \ref snd_pcm_sw_params_set_sleep_min where another timing source
+ * is used.
+ */
+int
+snd_pcm_sw_params_set_avail_min (snd_pcm_t * pcm ATTRIBUTE_UNUSED,
+ snd_pcm_sw_params_t * params,
+ snd_pcm_uframes_t val)
+{
+ dbg_printf ("snd_pcm_sw_params_set_avail_min()\n");
+ // NOP
+ return 0;
+}
+
+/**
+ * \brief Set minimum number of ticks to sleep inside a software configuration container
+ * \param pcm PCM handle
+ * \param params Software configuration container
+ * \param val Minimum ticks to sleep or 0 to disable the use of tick timer
+ * \return 0 otherwise a negative error code
+ */
+int
+snd_pcm_sw_params_set_sleep_min (snd_pcm_t * pcm ATTRIBUTE_UNUSED,
+ snd_pcm_sw_params_t * params,
+ unsigned int val)
+{
+ dbg_printf ("snd_pcm_sw_params_set_sleep_min()\n");
+ // NOP
+
+ return 0;
+}
+
+/**
+ * \brief Wait for a PCM to become ready
+ * \param pcm PCM handle
+ * \param timeout maximum time in milliseconds to wait
+ * \return a positive value on success otherwise a negative error code
+ * (-EPIPE for the xrun and -ESTRPIPE for the suspended status,
+ * others for general errors)
+ * \retval 0 timeout occurred
+ * \retval 1 PCM stream is ready for I/O
+ */
+int
+snd_pcm_wait (snd_pcm_t * pcm, int timeout)
+{
+ fd_set fds, *readfds = NULL, *writefds = NULL;
+ struct timeval wait, *w = NULL;
+
+ dbg_printf ("snd_pcm_wait(%d)\n", timeout);
+
+ FD_ZERO (&fds);
+ FD_SET (pcm->fd, &fds);
+
+ if (timeout > 0)
+ {
+ wait.tv_sec = timeout / 1000;
+ wait.tv_usec = (timeout % 1000) * 1000;
+ w = &wait;
+ }
+
+ if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
+ writefds = &fds;
+ else
+ readfds = &fds;
+
+ dbg_printf ("select(%d, %x, %x, NULL, %x)\n",
+ pcm->fd + 1, readfds, writefds, w);
+ if (select (pcm->fd + 1, readfds, writefds, NULL, w) == -1)
+ return -errno;
+
+ return FD_ISSET (pcm->fd, &fds);
+}
+
+/**
+ * \brief allocate an invalid #snd_pcm_sw_params_t using standard malloc
+ * \param ptr returned pointer
+ * \return 0 on success otherwise negative error code
+ */
+int
+snd_pcm_sw_params_malloc (snd_pcm_sw_params_t ** ptr)
+{
+ *ptr = calloc (1, sizeof (snd_pcm_sw_params_t));
+ if (!*ptr)
+ return -ENOMEM;
+ return 0;
+}
+
+/**
+ * \brief Extract period time from a configuration space
+ * \param params Configuration space
+ * \param val Returned approximate period duration in us
+ * \param dir Sub unit direction
+ * \return 0 otherwise a negative error code if not exactly one is present
+ *
+ * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
+ */
+int INTERNAL (snd_pcm_hw_params_get_period_time) (const snd_pcm_hw_params_t *
+ params, unsigned int *val,
+ int *dir)
+{
+ dbg_printf ("snd_pcm_hw_params_get_period_time()\n");
+ // TODO
+ return -EINVAL;
+}
+
+int INTERNAL (snd_pcm_hw_params_get_buffer_time) (const snd_pcm_hw_params_t *
+ params, unsigned int *val,
+ int *dir)
+{
+ dbg_printf ("snd_pcm_hw_params_get_buffer_time()\n");
+ // What's this?
+ return -EINVAL;
+}
+
+struct _snd_mask
+{
+ unsigned int bits[4];
+};
+
+struct _snd_pcm_access_mask
+{
+ unsigned int bits[4];
+};
+
+#define MASK_OFS(v) (v/32)
+#define MASK_BIT(v) (1<<(v%32))
+
+/**
+ * \brief reset all bits in a #snd_pcm_access_mask_t
+ * \param mask pointer to mask
+ */
+void
+snd_pcm_access_mask_none (snd_pcm_access_mask_t * mask)
+{
+ dbg_printf ("snd_pcm_access_mask_none()\n");
+ memset (mask, 0, sizeof (*mask));
+}
+
+/**
+ * \brief make an access type present in a #snd_pcm_access_mask_t
+ * \param mask pointer to mask
+ * \param val access type
+ */
+void
+snd_pcm_access_mask_set (snd_pcm_access_mask_t * mask, snd_pcm_access_t val)
+{
+ dbg_printf ("snd_pcm_access_mask_t(%d)\n", val);
+ mask->bits[MASK_OFS (val)] |= MASK_BIT (val);
+}
+
+/**
+ * \brief get size of #snd_pcm_access_mask_t
+ * \return size in bytes
+ */
+size_t
+snd_pcm_access_mask_sizeof ()
+{
+ return sizeof (snd_pcm_access_mask_t);
+}
+
+/**
+ * \brief Restrict a configuration space to contain only a set of access types
+ * \param pcm PCM handle
+ * \param params Configuration space
+ * \param mask Access mask
+ * \return 0 otherwise a negative error code
+ */
+int
+snd_pcm_hw_params_set_access_mask (snd_pcm_t * pcm,
+ snd_pcm_hw_params_t * params,
+ snd_pcm_access_mask_t * mask)
+{
+ dbg_printf ("snd_pcm_hw_params_set_access_mask()\n");
+ // NOP
+ return 0;
+}
+
+/**
+ * \brief Read interleaved frames from a PCM using direct buffer (mmap)
+ * \param pcm PCM handle
+ * \param buffer frames containing buffer
+ * \param size frames to be written
+ * \return a positive number of frames actually read otherwise a
+ * negative error code
+ * \retval -EBADFD PCM is not in the right state (#SND_PCM_STATE_PREPARED or #SND_PCM_STATE_RUNNING)
+ * \retval -EPIPE an overrun occurred
+ * \retval -ESTRPIPE a suspend event occurred (stream is suspended and waiting for an application recovery)
+ *
+ * If the blocking behaviour was selected, then routine waits until
+ * all requested bytes are filled. The count of bytes can be less only
+ * if a signal or underrun occurred.
+ *
+ * If the non-blocking behaviour is selected, then routine doesn't wait at all.
+ */
+snd_pcm_sframes_t
+snd_pcm_mmap_readi (snd_pcm_t * pcm, void *buffer, snd_pcm_uframes_t size)
+{
+ dbg_printf ("snd_pcm_mmap_readi()\n");
+ return snd_pcm_readi (pcm, buffer, size);
+}
+
+/**
+ * \brief Read non interleaved frames to a PCM using direct buffer (mmap)
+ * \param pcm PCM handle
+ * \param bufs frames containing buffers (one for each channel)
+ * \param size frames to be written
+ * \return a positive number of frames actually read otherwise a
+ * negative error code
+ * \retval -EBADFD PCM is not in the right state (#SND_PCM_STATE_PREPARED or #SND_PCM_STATE_RUNNING)
+ * \retval -EPIPE an overrun occurred
+ * \retval -ESTRPIPE a suspend event occurred (stream is suspended and waiting for an application recovery)
+ *
+ * If the blocking behaviour was selected, then routine waits until
+ * all requested bytes are filled. The count of bytes can be less only
+ * if a signal or underrun occurred.
+ *
+ * If the non-blocking behaviour is selected, then routine doesn't wait at all.
+ */
+snd_pcm_sframes_t
+snd_pcm_mmap_readn (snd_pcm_t * pcm, void **bufs, snd_pcm_uframes_t size)
+{
+ dbg_printf ("snd_pcm_mmap_readn()\n");
+ return snd_pcm_readn (pcm, bufs, size);
+}
+
+/**
+ * \brief Write interleaved frames to a PCM using direct buffer (mmap)
+ * \param pcm PCM handle
+ * \param buffer frames containing buffer
+ * \param size frames to be written
+ * \return a positive number of frames actually written otherwise a
+ * negative error code
+ * \retval -EBADFD PCM is not in the right state (#SND_PCM_STATE_PREPARED or #SND_PCM_STATE_RUNNING)
+ * \retval -EPIPE an underrun occurred
+ * \retval -ESTRPIPE a suspend event occurred (stream is suspended and waiting for an application recovery)
+ *
+ * If the blocking behaviour is selected, then routine waits until
+ * all requested bytes are played or put to the playback ring buffer.
+ * The count of bytes can be less only if a signal or underrun occurred.
+ *
+ * If the non-blocking behaviour is selected, then routine doesn't wait at all.
+ */
+snd_pcm_sframes_t
+snd_pcm_mmap_writei (snd_pcm_t * pcm, const void *buffer,
+ snd_pcm_uframes_t size)
+{
+ dbg_printf ("snd_pcm_mmap_writei()\n");
+
+ return snd_pcm_writei (pcm, buffer, size);
+}
+
+/**
+ * \brief Write non interleaved frames to a PCM using direct buffer (mmap)
+ * \param pcm PCM handle
+ * \param bufs frames containing buffers (one for each channel)
+ * \param size frames to be written
+ * \return a positive number of frames actually written otherwise a
+ * negative error code
+ * \retval -EBADFD PCM is not in the right state (#SND_PCM_STATE_PREPARED or #SND_PCM_STATE_RUNNING)
+ * \retval -EPIPE an underrun occurred
+ * \retval -ESTRPIPE a suspend event occurred (stream is suspended and waiting for an application recovery)
+ *
+ * If the blocking behaviour is selected, then routine waits until
+ * all requested bytes are played or put to the playback ring buffer.
+ * The count of bytes can be less only if a signal or underrun occurred.
+ *
+ * If the non-blocking behaviour is selected, then routine doesn't wait at all.
+ */
+snd_pcm_sframes_t
+snd_pcm_mmap_writen (snd_pcm_t * pcm, void **bufs, snd_pcm_uframes_t size)
+{
+ dbg_printf ("snd_pcm_mmap_writen()\n");
+ return snd_pcm_writen (pcm, bufs, size);
+}
+
+/**
+ * \brief Link two PCMs
+ * \param pcm1 first PCM handle
+ * \param pcm2 first PCM handle
+ * \return 0 on success otherwise a negative error code
+ *
+ * The two PCMs will start/stop/prepare in sync.
+ */
+int
+snd_pcm_link (snd_pcm_t * pcm1, snd_pcm_t * pcm2)
+{
+ dbg_printf ("snd_pcm_link()\n");
+ return -EINVAL;
+}
+
+/**
+ * \brief Set silence size inside a software configuration container
+ * \param pcm PCM handle
+ * \param params Software configuration container
+ * \param val Silence size in frames (0 for disabled)
+ * \return 0 otherwise a negative error code
+ *
+ * A portion of playback buffer is overwritten with silence when playback
+ * underrun is nearer than silence threshold (see
+ * #snd_pcm_sw_params_set_silence_threshold)
+ *
+ * The special case is when silence size value is equal or greater than
+ * boundary. The unused portion of the ring buffer (initial written samples
+ * are untouched) is filled with silence at start. Later, only just processed
+ * sample area is filled with silence. Note: silence_threshold must be set to zero.
+ */
+int
+snd_pcm_sw_params_set_silence_size (snd_pcm_t * pcm,
+ snd_pcm_sw_params_t * params,
+ snd_pcm_uframes_t val)
+{
+ dbg_printf ("snd_pcm_sw_params_set_silence_size()\n");
+
+ return 0;
+}
+
+/**
+ * \brief Set silence threshold inside a software configuration container
+ * \param pcm PCM handle
+ * \param params Software configuration container
+ * \param val Silence threshold in frames
+ * \return 0 otherwise a negative error code
+ *
+ * A portion of playback buffer is overwritten with silence (see
+ * #snd_pcm_sw_params_set_silence_size) when playback underrun is nearer
+ * than silence threshold.
+ */
+int
+snd_pcm_sw_params_set_silence_threshold (snd_pcm_t * pcm, snd_pcm_sw_params_t
+ * params, snd_pcm_uframes_t val)
+{
+ dbg_printf ("snd_pcm_sw_params_set_silence_threshold()\n");
+
+ return 0;
+}
+
+/**
+ * \brief Restrict a configuration space to contain only one period size
+ * \param pcm PCM handle
+ * \param params Configuration space
+ * \param val approximate period size in frames
+ * \param dir Sub unit direction
+ * \return 0 otherwise a negative error code if configuration space would become empty
+ *
+ * Wanted exact value is <,=,> val following dir (-1,0,1)
+ */
+int
+snd_pcm_hw_params_set_period_size (snd_pcm_t * pcm,
+ snd_pcm_hw_params_t * params,
+ snd_pcm_uframes_t val, int dir)
+{
+ dbg_printf
+ ("snd_pcm_hw_params_set_period_size(pcm=%x, params=%x, val=%d, dir=%d)\n",
+ pcm, params, val, dir);
+ pcm->period_size = val;
+ return 0;
+}
+
+/**
+ * \brief Set stop threshold inside a software configuration container
+ * \param pcm PCM handle
+ * \param params Software configuration container
+ * \param val Stop threshold in frames
+ * \return 0 otherwise a negative error code
+ *
+ * PCM is automatically stopped in #SND_PCM_STATE_XRUN state when available
+ * frames is >= threshold. If the stop threshold is equal to boundary (also
+ * software parameter - sw_param) then automatic stop will be disabled
+ * (thus device will do the endless loop in the ring buffer).
+ */
+int
+snd_pcm_sw_params_set_stop_threshold (snd_pcm_t * pcm,
+ snd_pcm_sw_params_t * params,
+ snd_pcm_uframes_t val)
+{
+ dbg_printf ("snd_pcm_sw_params_set_stop_threshold()\n");
+
+ return 0;
+}
+
+/**
+ * \brief Return 16 bit expressing silence for a PCM sample format
+ * \param format Sample format
+ * \return silence 16 bit word
+ */
+u_int16_t
+snd_pcm_format_silence_16 (snd_pcm_format_t format)
+{
+ dbg_printf ("snd_pcm_format_silence_16(%x)\n", format);
+ return 0;
+}
+
+/**
+ * \brief Return 8 bit expressing silence for a PCM sample format
+ * \param format Sample format
+ * \return silence 8 bit word
+ */
+u_int8_t
+snd_pcm_format_silence (snd_pcm_format_t format)
+{
+
+ dbg_printf ("snd_pcm_format_silence(%x)\n", format);
+
+ return 0x80;
+}
+
+
+/**
+ * \brief Return 32 bit expressing silence for a PCM sample format
+ * \param format Sample format
+ * \return silence 32 bit word
+ */
+u_int32_t
+snd_pcm_format_silence_32 (snd_pcm_format_t format)
+{
+ dbg_printf ("snd_pcm_format_silence_32(%x)\n", format);
+ return 0;
+}
+
+
+/**
+ * \brief Get available subdevices count from a PCM info container
+ * \param obj PCM info container
+ * \return available subdevices count of PCM
+ */
+unsigned int
+snd_pcm_info_get_subdevices_avail (const snd_pcm_info_t * obj)
+{
+ dbg_printf ("snd_pcm_info_get_subdevices_avail()\n");
+
+ return 1;
+}
+
+/**
+ * \brief get description of PCM sample format
+ * \param format PCM sample format
+ * \return ascii description of PCM sample format
+ */
+const char *
+snd_pcm_format_description (snd_pcm_format_t format)
+{
+ if (format > SND_PCM_FORMAT_LAST)
+ return NULL;
+ return snd_pcm_format_descriptions[format];
+}
+
+/**
+ * \brief Get subdevices count from a PCM info container
+ * \param obj PCM info container
+ * \return subdevices total count of PCM
+ */
+unsigned int
+snd_pcm_info_get_subdevices_count (const snd_pcm_info_t * obj)
+{
+ dbg_printf ("snd_pcm_info_get_subdevices_count()\n");
+
+ return 1;
+}
+
+/**
+ * \brief Silence a PCM samples buffer
+ * \param format Sample format
+ * \param data Buffer
+ * \return samples Samples count
+ */
+int
+snd_pcm_format_set_silence (snd_pcm_format_t format, void *data,
+ unsigned int samples)
+{
+ dbg_printf ("snd_pcm_format_set_silence()\n");
+
+ return 0;
+}
+
+
+/**
+ * \brief get identifier of PCM handle
+ * \param pcm PCM handle
+ * \return ascii identifier of PCM handle
+ *
+ * Returns the ASCII identifier of given PCM handle. It's the same
+ * identifier specified in snd_pcm_open().
+ */
+const char *
+snd_pcm_name (snd_pcm_t * pcm)
+{
+ return pcm->info.name;
+}
+
+/**
+ * \brief get name of PCM state
+ * \param state PCM state
+ * \return ascii name of PCM state
+ */
+const char *
+snd_pcm_state_name (snd_pcm_state_t state)
+{
+ if (state > SND_PCM_STATE_LAST)
+ return NULL;
+ return snd_pcm_state_names[state];
+
+}
+
+/**
+ * \brief get name of PCM stream type
+ * \param stream PCM stream type
+ * \return ascii name of PCM stream type
+ */
+const char *
+snd_pcm_stream_name (snd_pcm_stream_t stream)
+{
+ assert (stream <= SND_PCM_STREAM_LAST);
+ return snd_pcm_stream_names[stream];
+}
+
+/**
+ * \brief Extract maximum buffer time from a configuration space
+ * \param params Configuration space
+ * \param val approximate maximum buffer duration in us
+ * \param dir Sub unit direction
+ * \return 0 otherwise a negative error code
+ *
+ * Exact value is <,=,> the returned one following dir (-1,0,1)
+ */
+int INTERNAL (snd_pcm_hw_params_get_buffer_time_max) (const
+ snd_pcm_hw_params_t *
+ params,
+ unsigned int *val,
+ int *dir)
+{
+ dbg_printf ("snd_pcm_hw_params_get_buffer_time_max()\n");
+ return 0;
+}
+
+/**
+ * \brief Get subdevice name from a PCM info container
+ * \param obj PCM info container
+ * \return name of used PCM subdevice
+ */
+const char *
+snd_pcm_info_get_subdevice_name (const snd_pcm_info_t * obj)
+{
+ dbg_printf ("snd_pcm_info_get_subdevice_name()\n");
+
+ return "OSS subname";
+}
+
+int
+snd_device_name_hint (int card, const char * iface, void *** hints)
+{
+ dbg_printf ("snd_device_name_hint()\n");
+
+ return -1;
+}
+
+int
+snd_pcm_hw_params_is_monotonic (const snd_pcm_hw_params_t * params)
+{
+ return 0;
+}
+
+/**
+ * \brief get PCM sample format from name
+ * \param name PCM sample format name (case insensitive)
+ * \return PCM sample format
+ */
+snd_pcm_format_t
+snd_pcm_format_value (const char *name)
+{
+ snd_pcm_format_t format;
+ for (format = 0; format <= SND_PCM_FORMAT_LAST; format++)
+ {
+ if (snd_pcm_format_names[format] &&
+ strcasecmp (name, snd_pcm_format_names[format]) == 0)
+ {
+ return format;
+ }
+ }
+ for (format = 0; format <= SND_PCM_FORMAT_LAST; format++)
+ {
+ if (snd_pcm_format_descriptions[format] &&
+ strcasecmp (name, snd_pcm_format_descriptions[format]) == 0)
+ {
+ return format;
+ }
+ }
+ return SND_PCM_FORMAT_UNKNOWN;
+}
+
+
+/**
+ * \brief Get id from a PCM info container
+ * \param obj PCM info container
+ * \return short id of PCM
+ */
+const char *
+snd_pcm_info_get_id (const snd_pcm_info_t * obj)
+{
+ dbg_printf ("snd_pcm_info_get_id()\n");
+
+ return "OSS ID";
+}
+
+/**
+ * \brief Return nominal bits per a PCM sample
+ * \param format Sample format
+ * \return bits per sample, a negative error code if not applicable
+ */
+int
+snd_pcm_format_width (snd_pcm_format_t format)
+{
+ switch (format)
+ {
+ case SNDRV_PCM_FORMAT_S8:
+ case SNDRV_PCM_FORMAT_U8:
+ return 8;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ case SNDRV_PCM_FORMAT_S16_BE:
+ case SNDRV_PCM_FORMAT_U16_LE:
+ case SNDRV_PCM_FORMAT_U16_BE:
+ return 16;
+ case SNDRV_PCM_FORMAT_S18_3LE:
+ case SNDRV_PCM_FORMAT_S18_3BE:
+ case SNDRV_PCM_FORMAT_U18_3LE:
+ case SNDRV_PCM_FORMAT_U18_3BE:
+ return 18;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ case SNDRV_PCM_FORMAT_S20_3BE:
+ case SNDRV_PCM_FORMAT_U20_3LE:
+ case SNDRV_PCM_FORMAT_U20_3BE:
+ return 20;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ case SNDRV_PCM_FORMAT_S24_BE:
+ case SNDRV_PCM_FORMAT_U24_LE:
+ case SNDRV_PCM_FORMAT_U24_BE:
+ case SNDRV_PCM_FORMAT_S24_3LE:
+ case SNDRV_PCM_FORMAT_S24_3BE:
+ case SNDRV_PCM_FORMAT_U24_3LE:
+ case SNDRV_PCM_FORMAT_U24_3BE:
+ return 24;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ case SNDRV_PCM_FORMAT_S32_BE:
+ case SNDRV_PCM_FORMAT_U32_LE:
+ case SNDRV_PCM_FORMAT_U32_BE:
+ case SNDRV_PCM_FORMAT_FLOAT_LE:
+ case SNDRV_PCM_FORMAT_FLOAT_BE:
+ return 32;
+ case SNDRV_PCM_FORMAT_FLOAT64_LE:
+ case SNDRV_PCM_FORMAT_FLOAT64_BE:
+ return 64;
+ case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
+ case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
+ return 32;
+ case SNDRV_PCM_FORMAT_MU_LAW:
+ case SNDRV_PCM_FORMAT_A_LAW:
+ return 8;
+ case SNDRV_PCM_FORMAT_IMA_ADPCM:
+ return 4;
+ default:
+ return -EINVAL;
+ }
+}
+
+
+/**
+ * \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
+ *
+ * The asynchronous callback is called when period boundary elapses.
+ */
+int
+snd_async_add_pcm_handler (snd_async_handler_t ** handler, snd_pcm_t * pcm,
+ snd_async_callback_t callback, void *private_data)
+{
+ dbg_printf ("snd_async_add_pcm_handler()\n");
+
+ return -EINVAL;
+}
+
+void *
+snd_async_handler_get_callback_private (snd_async_handler_t * handler)
+{
+ // What's this?
+ dbg_printf ("snd_async_handler_get_callback_private()\n");
+ return NULL;
+}
+
+/*
+ * What's this?
+ */
+int
+snd_pcm_format_linear (snd_pcm_format_t format)
+{
+ return 1;
+}
+
+/*
+ * What's this?
+ */
+int
+snd_pcm_format_float (snd_pcm_format_t format)
+{
+ return 0;
+}
+
+/*
+ * What's this?
+ */
+int
+snd_pcm_format_signed (snd_pcm_format_t format)
+{
+ return (format != SND_PCM_FORMAT_U8);
+}
+
+/*
+ * What's this?
+ */
+snd_pcm_format_t
+snd_pcm_build_linear_format (int width, int pwidth, int unsignd,
+ int big_endian)
+{
+ printf ("Invalid ALSA call snd_pcm_build_linear_format()\n");
+ return 0;
+}
+
+int
+snd_pcm_format_cpu_endian (snd_pcm_format_t format)
+{
+ return 1;
+}
+
+int
+snd_pcm_format_little_endian (snd_pcm_format_t format)
+{
+ return 1;
+}
+
+/**
+ * \brief get size of #snd_pcm_format_mask_t
+ * \return size in bytes
+ */
+size_t
+snd_pcm_format_mask_sizeof ()
+{
+ return sizeof (snd_pcm_format_mask_t);
+}
+
+/**
+ * \brief test the presence of a format in a #snd_pcm_format_mask_t
+ * \param mask pointer to mask
+ * \param val format
+ */
+int
+snd_pcm_format_mask_test (const snd_pcm_format_mask_t * mask,
+ snd_pcm_format_t val)
+{
+ printf ("snd_pcm_format_mask_test()\n");
+ 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)
+{
+ dbg_printf ("snd_async_handler_get_pcm()\n");
+ return NULL;
+}
+
+/**
+ * \brief Copy one or more areas
+ * \param dst_areas destination areas specification (one for each channel)
+ * \param dst_offset offset in frames inside destination area
+ * \param src_areas source areas specification (one for each channel)
+ * \param src_offset offset in frames inside source area
+ * \param channels channels count
+ * \param frames frames to copy
+ * \param format PCM sample format
+ * \return 0 on success otherwise a negative error code
+ */
+int
+snd_pcm_areas_copy (const snd_pcm_channel_area_t * dst_areas,
+ snd_pcm_uframes_t dst_offset,
+ const snd_pcm_channel_area_t * src_areas,
+ snd_pcm_uframes_t src_offset, unsigned int channels,
+ snd_pcm_uframes_t frames, snd_pcm_format_t format)
+{
+ dbg_printf ("snd_pcm_areas_copy()\n");
+
+ return -EINVAL;
+}
+
+/**
+ * \brief Get format mask from a configuration space
+ * \param params Configuration space
+ * \param mask Returned Format mask
+ */
+void
+snd_pcm_hw_params_get_format_mask (snd_pcm_hw_params_t * params,
+ snd_pcm_format_mask_t * mask)
+{
+ printf ("snd_pcm_hw_params_get_format_mask()\n");
+}
+
+#if 1
+
+#ifdef USE_VERSIONED_SYMBOLS
+
+#define OBSOLETE1(name, what, new) \
+ symbol_version(__old_##name, name, what); \
+ default_symbol_version(__##name, name, new);
+
+#else
+
+#define OBSOLETE1(name, what, new) \
+ use_default_symbol_version(__##name, name, new);
+
+#endif /* USE_VERSIONED_SYMBOLS */
+
+#define __P_OLD_GET(pfx, name, val_type, ret_type) \
+ret_type pfx##name(const snd_pcm_hw_params_t *params) \
+{ \
+ val_type val; \
+ if (INTERNAL(name)(params, &val) < 0) \
+ return 0; \
+ return (ret_type)val; \
+}
+
+#define __P_OLD_GET1(pfx, name, val_type, ret_type) \
+ret_type pfx##name(const snd_pcm_hw_params_t *params, int *dir) \
+{ \
+ val_type val; \
+ if (INTERNAL(name)(params, &val, dir) < 0) \
+ return 0; \
+ return (ret_type)val; \
+}
+
+#define __OLD_GET(name, val_type, ret_type) __P_OLD_GET(__old_, name, val_type, ret_type)
+#define __OLD_GET1(name, val_type, ret_type) __P_OLD_GET1(__old_, name, val_type, ret_type)
+
+#define __P_OLD_NEAR(pfx, name, ret_type) \
+ret_type pfx##name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, ret_type val) \
+{ \
+ if (INTERNAL(name)(pcm, params, &val) < 0) \
+ return 0; \
+ return (ret_type)val; \
+}
+
+#define __P_OLD_NEAR1(pfx, name, ret_type) \
+ret_type pfx##name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, ret_type val, int *dir) \
+{ \
+ if (INTERNAL(name)(pcm, params, &val, dir) < 0) \
+ return 0; \
+ return (ret_type)val; \
+}
+
+#define __OLD_NEAR(name, ret_type) __P_OLD_NEAR(__old_, name, ret_type)
+#define __OLD_NEAR1(name, ret_type) __P_OLD_NEAR1(__old_, name, ret_type)
+
+#define __P_OLD_SET_FL(pfx, name, ret_type) \
+ret_type pfx##name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) \
+{ \
+ ret_type val; \
+ if (INTERNAL(name)(pcm, params, &val) < 0) \
+ return 0; \
+ return (ret_type)val; \
+}
+
+#define __P_OLD_SET_FL1(pfx, name, ret_type) \
+ret_type pfx##name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, int *dir) \
+{ \
+ ret_type val; \
+ if (INTERNAL(name)(pcm, params, &val, dir) < 0) \
+ return 0; \
+ return (ret_type)val; \
+}
+
+#define __OLD_SET_FL(name, ret_type) __P_OLD_SET_FL(__old_, name, ret_type)
+#define __OLD_SET_FL1(name, ret_type) __P_OLD_SET_FL1(__old_, name, ret_type)
+
+#define __P_OLD_GET_SW(pfx, name, ret_type) \
+ret_type pfx##name(snd_pcm_sw_params_t *params) \
+{ \
+ ret_type val; \
+ if (INTERNAL(name)(params, &val) < 0) \
+ return 0; \
+ return (ret_type)val; \
+}
+
+#define __OLD_GET_SW(name, ret_type) __P_OLD_GET_SW(__old_, name, ret_type)
+
+#endif /* DOC_HIDDEN */
+
+__OLD_NEAR1 (snd_pcm_hw_params_set_rate_near, unsigned int);
+OBSOLETE1 (snd_pcm_hw_params_set_rate_near, ALSA_0.9, ALSA_0.9.0rc4);
+
+__OLD_NEAR (snd_pcm_hw_params_set_channels_near, unsigned int);
+OBSOLETE1 (snd_pcm_hw_params_set_channels_near, ALSA_0.9, ALSA_0.9.0rc4);
+
+__OLD_GET1 (snd_pcm_hw_params_get_period_size, snd_pcm_uframes_t,
+ snd_pcm_sframes_t);
+OBSOLETE1 (snd_pcm_hw_params_get_period_size, ALSA_0.9, ALSA_0.9.0rc4);
+
+
+__OLD_NEAR1 (snd_pcm_hw_params_set_buffer_time_near, unsigned int);
+OBSOLETE1 (snd_pcm_hw_params_set_buffer_time_near, ALSA_0.9,
+ ALSA_0.9.0rc4) __OLD_GET (snd_pcm_hw_params_get_buffer_size,
+ snd_pcm_uframes_t, snd_pcm_sframes_t);
+OBSOLETE1 (snd_pcm_hw_params_get_buffer_size, ALSA_0.9, ALSA_0.9.0rc4);
+
+__OLD_NEAR1 (snd_pcm_hw_params_set_period_time_near, unsigned int);
+OBSOLETE1 (snd_pcm_hw_params_set_period_time_near, ALSA_0.9,
+ ALSA_0.9.0rc4);
+
+__OLD_NEAR (snd_pcm_hw_params_set_buffer_size_near, snd_pcm_uframes_t);
+OBSOLETE1 (snd_pcm_hw_params_set_buffer_size_near, ALSA_0.9,
+ ALSA_0.9.0rc4);
+
+__OLD_NEAR1 (snd_pcm_hw_params_set_period_size_near, snd_pcm_uframes_t);
+OBSOLETE1 (snd_pcm_hw_params_set_period_size_near, ALSA_0.9,
+ ALSA_0.9.0rc4);
+
+__OLD_NEAR1 (snd_pcm_hw_params_set_periods_near, unsigned int);
+OBSOLETE1 (snd_pcm_hw_params_set_periods_near, ALSA_0.9, ALSA_0.9.0rc4);
+
+__OLD_GET1 (snd_pcm_hw_params_get_period_time, unsigned int, int);
+OBSOLETE1 (snd_pcm_hw_params_get_period_time, ALSA_0.9, ALSA_0.9.0rc4);
+
+__OLD_GET1 (snd_pcm_hw_params_get_buffer_time, unsigned int, int);
+OBSOLETE1 (snd_pcm_hw_params_get_buffer_time, ALSA_0.9, ALSA_0.9.0rc4);
+
+__OLD_GET_SW (snd_pcm_sw_params_get_xfer_align, snd_pcm_uframes_t);
+OBSOLETE1 (snd_pcm_sw_params_get_xfer_align, ALSA_0.9, ALSA_0.9.0rc4);
+
+__OLD_GET1 (snd_pcm_hw_params_get_periods, unsigned int, int);
+OBSOLETE1 (snd_pcm_hw_params_get_periods, ALSA_0.9, ALSA_0.9.0rc4);
+
+__OLD_GET (snd_pcm_hw_params_get_access, snd_pcm_access_t, int);
+OBSOLETE1 (snd_pcm_hw_params_get_access, ALSA_0.9, ALSA_0.9.0rc4);
+
+__OLD_GET1 (snd_pcm_hw_params_get_buffer_time_max, unsigned int,
+ unsigned int);
+OBSOLETE1 (snd_pcm_hw_params_get_buffer_time_max, ALSA_0.9,
+ ALSA_0.9.0rc4);
+
+__OLD_GET1 (snd_pcm_hw_params_get_tick_time, unsigned int, int);
+OBSOLETE1 (snd_pcm_hw_params_get_tick_time, ALSA_0.9, ALSA_0.9.0rc4);
+
+__OLD_GET (snd_pcm_hw_params_get_channels_max, unsigned int, unsigned int);
+OBSOLETE1 (snd_pcm_hw_params_get_channels_max, ALSA_0.9, ALSA_0.9.0rc4);
+
+__OLD_GET (snd_pcm_hw_params_get_channels_min, unsigned int, unsigned int);
+OBSOLETE1 (snd_pcm_hw_params_get_channels_min, ALSA_0.9, ALSA_0.9.0rc4);
+
+__OLD_GET1 (snd_pcm_hw_params_get_rate_max, unsigned int, unsigned int);
+OBSOLETE1 (snd_pcm_hw_params_get_rate_max, ALSA_0.9, ALSA_0.9.0rc4);
+
+__OLD_GET1 (snd_pcm_hw_params_get_rate_min, unsigned int, unsigned int);
+OBSOLETE1 (snd_pcm_hw_params_get_rate_min, ALSA_0.9, ALSA_0.9.0rc4);
+
+__OLD_GET (snd_pcm_hw_params_get_format, snd_pcm_format_t, int);
+OBSOLETE1 (snd_pcm_hw_params_get_format, ALSA_0.9, ALSA_0.9.0rc4);
+
+__OLD_GET1 (snd_pcm_hw_params_get_rate, unsigned int, int);
+OBSOLETE1 (snd_pcm_hw_params_get_rate, ALSA_0.9, ALSA_0.9.0rc4);