+++ /dev/null
-/**
- * \file include/mixer_ordinary.h
- * \brief Application interface library for the ALSA driver
- * \author Jaroslav Kysela <perex@suse.cz>
- * \date 2003
- *
- * Application interface library for the ALSA driver.
- * See the \ref mixer_ordinary page for more details.
- */
-/*
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * 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
- *
- */
-
-#ifndef __ALSA_MIXER_SIMPLE_H
-#define __ALSA_MIXER_SIMPLE_H
-
-#include <alsa/asoundlib.h>
-
-/*
- * Abbreviations:
- *
- * FLVOL - Front Left Volume (0-1000)
- * FCLVOL - Front Center Left Volume (0-1000)
- * FCVOL - Front Center Volume (0-1000)
- * FCRVOL - Front Center Right Volume (0-1000)
- * FRVOL - Front Right Volume (0-1000)
- * FSLVOL - Front Side Left Volume (0-1000)
- * FSRVOL - Front Side Right Volume (0-1000)
- * RSLVOL - Rear Side Left Volume (0-1000)
- * RSRVOL - Rear Side Right Volume (0-1000)
- * RLVOL - Rear Left Volume (0-1000)
- * RCVOL - Rear Center Volume (0-1000)
- * RRVOL - Rear Right Volume (0-1000)
- * LFEVOL - Low Frequency Effects (Subwoofer) Volume (0-1000)
- * OVRVOL - Overhead Volume (0-1000)
- */
-
-/** Ordinary Mixer I/O type */
-enum sndo_mixer_io_type {
-
- /*
- * playback section
- */
-
- /* Master */
- SNDO_MIO_MASTER_FLVOL = 0 * 0x40,
- SNDO_MIO_MASTER_FCLVOL,
- SNDO_MIO_MASTER_FCVOL,
- SNDO_MIO_MASTER_FCRVOL,
- SNDO_MIO_MASTER_FRVOL,
- SNDO_MIO_MASTER_FSLVOL,
- SNDO_MIO_MASTER_FSRVOL,
- SNDO_MIO_MASTER_RSLVOL,
- SNDO_MIO_MASTER_RSRVOL,
- SNDO_MIO_MASTER_RLVOL,
- SNDO_MIO_MASTER_RCVOL,
- SNDO_MIO_MASTER_RRVOL,
- SNDO_MIO_MASTER_LFEVOL,
- SNDO_MIO_MASTER_OVRVOL,
-
- /* PCM */
- SNDO_MIO_PCM_FLVOL = 1 * 0x40,
- SNDO_MIO_PCM_FCLVOL,
- SNDO_MIO_PCM_FCVOL,
- SNDO_MIO_PCM_FCRVOL,
- SNDO_MIO_PCM_FRVOL,
- SNDO_MIO_PCM_FSLVOL,
- SNDO_MIO_PCM_FSRVOL,
- SNDO_MIO_PCM_RSLVOL,
- SNDO_MIO_PCM_RSRVOL,
- SNDO_MIO_PCM_RLVOL,
- SNDO_MIO_PCM_RCVOL,
- SNDO_MIO_PCM_RRVOL,
- SNDO_MIO_PCM_LFEVOL,
- SNDO_MIO_PCM_OVRVOL,
-
- /* LINE */
- SNDO_MIO_LINE_FLVOL = 2 * 0x40,
- SNDO_MIO_LINE_FCLVOL,
- SNDO_MIO_LINE_FCVOL,
- SNDO_MIO_LINE_FCRVOL,
- SNDO_MIO_LINE_FRVOL,
- SNDO_MIO_LINE_FSLVOL,
- SNDO_MIO_LINE_FSRVOL,
- SNDO_MIO_LINE_RSLVOL,
- SNDO_MIO_LINE_RSRVOL,
- SNDO_MIO_LINE_RLVOL,
- SNDO_MIO_LINE_RCVOL,
- SNDO_MIO_LINE_RRVOL,
- SNDO_MIO_LINE_LFEVOL,
- SNDO_MIO_LINE_OVRVOL,
-
- /* MIC */
- SNDO_MIO_MIC_FLVOL = 3 * 0x40,
- SNDO_MIO_MIC_FCLVOL,
- SNDO_MIO_MIC_FCVOL,
- SNDO_MIO_MIC_FCRVOL,
- SNDO_MIO_MIC_FRVOL,
- SNDO_MIO_MIC_FSLVOL,
- SNDO_MIO_MIC_FSRVOL,
- SNDO_MIO_MIC_RSLVOL,
- SNDO_MIO_MIC_RSRVOL,
- SNDO_MIO_MIC_RLVOL,
- SNDO_MIO_MIC_RCVOL,
- SNDO_MIO_MIC_RRVOL,
- SNDO_MIO_MIC_LFEVOL,
- SNDO_MIO_MIC_OVRVOL,
-
- /* CD */
- SNDO_MIO_CD_FLVOL = 4 * 0x40,
- SNDO_MIO_CD_FCLVOL,
- SNDO_MIO_CD_FCVOL,
- SNDO_MIO_CD_FCRVOL,
- SNDO_MIO_CD_FRVOL,
- SNDO_MIO_CD_FSLVOL,
- SNDO_MIO_CD_FSRVOL,
- SNDO_MIO_CD_RSLVOL,
- SNDO_MIO_CD_RSRVOL,
- SNDO_MIO_CD_RLVOL,
- SNDO_MIO_CD_RCVOL,
- SNDO_MIO_CD_RRVOL,
- SNDO_MIO_CD_LFEVOL,
- SNDO_MIO_CD_OVRVOL,
-
- /* AUX */
- SNDO_MIO_AUX_FLVOL = 5 * 0x40,
- SNDO_MIO_AUX_FCLVOL,
- SNDO_MIO_AUX_FCVOL,
- SNDO_MIO_AUX_FCRVOL,
- SNDO_MIO_AUX_FRVOL,
- SNDO_MIO_AUX_FSLVOL,
- SNDO_MIO_AUX_FSRVOL,
- SNDO_MIO_AUX_RSLVOL,
- SNDO_MIO_AUX_RSRVOL,
- SNDO_MIO_AUX_RLVOL,
- SNDO_MIO_AUX_RCVOL,
- SNDO_MIO_AUX_RRVOL,
- SNDO_MIO_AUX_LFEVOL,
- SNDO_MIO_AUX_OVRVOL,
-
- /*
- * capture section
- */
-
- /* capture gain */
- SNDO_MIO_CGAIN_FL = 0x8000,
- SNDO_MIO_CGAIN_FCL,
- SNDO_MIO_CGAIN_FC,
- SNDO_MIO_CGAIN_FCR,
- SNDO_MIO_CGAIN_FR,
- SNDO_MIO_CGAIN_FSL,
- SNDO_MIO_CGAIN_FSR,
- SNDO_MIO_CGAIN_RSL,
- SNDO_MIO_CGAIN_RSR,
- SNDO_MIO_CGAIN_RL,
- SNDO_MIO_CGAIN_RC,
- SNDO_MIO_CGAIN_RR,
- SNDO_MIO_CGAIN_LFE,
- SNDO_MIO_CGAIN_OVR,
-
- /* capture source (0 = off, 1 = on) */
- SNDO_MIO_CSOURCE_MIC = 0x8100,
- SNDO_MIO_CSOURCE_LINE,
- SNDO_MIO_CSOURCE_CD,
- SNDO_MIO_CSOURCE_AUX,
- SNDO_MIO_CSOURCE_MIX,
-
- /* misc */
- SNDO_MIO_STEREO = 0x8200, /* (0 = off, 1 = on) standard stereo source, might be converted to use all outputs */
-};
-
-typedef struct sndo_mixer sndo_mixer_t;
-struct alisp_cfg;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \defgroup Mixer_ordinary Mixer Ordinary Interface
- * See the \ref mixer_ordinary page for more details.
- * \{
- */
-
-int sndo_mixer_open(sndo_mixer_t **pmixer, const char *playback_name, const char *capture_name, struct alisp_cfg *lconf);
-int sndo_mixer_open_pcm(sndo_mixer_t **pmixer, snd_pcm_t *playback_pcm, snd_pcm_t *capture_pcm, struct alisp_cfg *lconf);
-int sndo_mixer_close(sndo_mixer_t *mixer);
-int sndo_mixer_poll_descriptors_count(sndo_mixer_t *mixer);
-int sndo_mixer_poll_descriptors(sndo_mixer_t *mixer, struct pollfd *pfds, unsigned int space);
-int sndo_mixer_poll_descriptors_revents(sndo_mixer_t *mixer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
-int sndo_mixer_io_get_name(enum sndo_mixer_io_type type, char **name);
-int sndo_mixer_io_get(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val);
-int sndo_mixer_io_set(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val);
-int sndo_mixer_io_try_set(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val);
-int sndo_mixer_io_get_dB(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val);
-int sndo_mixer_io_set_dB(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val);
-int sndo_mixer_io_try_set_dB(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val);
-int sndo_mixer_io_change(sndo_mixer_t *mixer, enum sndo_mixer_io_type *changed, int changed_array_size);
-
-/** \} */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __ALSA_MIXER_SIMPLE_H */
+++ /dev/null
-/**
- * \file include/pcm_ordinary.h
- * \brief Application interface library for the ALSA driver
- * \author Jaroslav Kysela <perex@suse.cz>
- * \date 2003
- *
- * Application interface library for the ALSA driver.
- * See the \ref pcm_ordinary page for more details.
- */
-/*
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * 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
- *
- */
-
-#ifndef __ALSA_PCM_ORDINARY_H
-#define __ALSA_PCM_ORDINARY_H
-
-#include <alsa/asoundlib.h>
-
-/** Ordinary PCM latency type */
-enum sndo_pcm_latency_type {
- /** normal latency - for standard playback or capture
- (estimated latency in one direction 350ms) (default) */
- SNDO_PCM_LATENCY_NORMAL = 0,
- /** medium latency - software phones etc.
- (estimated latency in one direction maximally 50ms) */
- SNDO_PCM_LATENCY_MEDIUM,
- /** realtime latency - realtime applications (effect processors etc.)
- (estimated latency in one direction 5ms) */
- SNDO_PCM_LATENCY_REALTIME
-};
-
-/** Ordinary PCM access type */
-enum sndo_pcm_access_type {
- /** interleaved access - channels are interleaved without any gaps among samples (default) */
- SNDO_PCM_ACCESS_INTERLEAVED = 0,
- /** noninterleaved access - channels are separate without any gaps among samples */
- SNDO_PCM_ACCESS_NONINTERLEAVED
-};
-
-/** Ordinary PCM xrun type */
-enum sndo_pcm_xrun_type {
- /** driver / library will ignore all xruns, the stream runs forever (default) */
- SNDO_PCM_XRUN_IGNORE = 0,
- /** driver / library stops the stream when an xrun occurs */
- SNDO_PCM_XRUN_STOP
-};
-
-typedef struct sndo_pcm sndo_pcm_t;
-
-typedef int (sndo_pcm_engine_callback_t)(sndo_pcm_t *pcm);
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \defgroup PCM_ordinary PCM Ordinary Interface
- * See the \ref pcm_ordinary page for more details.
- * \{
- */
-
-int sndo_pcm_open(sndo_pcm_t **pcm, const char *playback_name, const char *capture_name, struct alisp_cfg *lconf);
-int sndo_pcm_close(sndo_pcm_t *pcm);
-int sndo_pcm_poll_descriptors_count(sndo_pcm_t *pcm);
-int sndo_pcm_poll_descriptors(sndo_pcm_t *pcm, struct pollfd *pfds, unsigned int space);
-int sndo_pcm_start(sndo_pcm_t *pcm);
-int sndo_pcm_drop(sndo_pcm_t *pcm);
-int sndo_pcm_drain(sndo_pcm_t *pcm);
-int sndo_pcm_delay(sndo_pcm_t *pcm, snd_pcm_sframes_t *delayp);
-int sndo_pcm_transfer_block(sndo_pcm_t *pcm, snd_pcm_uframes_t *tblock);
-int sndo_pcm_resume(sndo_pcm_t *pcm);
-int sndo_pcm_wait(sndo_pcm_t *pcm, int timeout);
-snd_pcm_t *sndo_pcm_raw_playback(sndo_pcm_t *pcm);
-snd_pcm_t *sndo_pcm_raw_capture(sndo_pcm_t *pcm);
-
-/**
- * \defgroup PCM_ordinary_params Parameters Functions
- * \ingroup PCM_ordinary
- * See the \ref pcm_ordinary page for more details.
- * \{
- */
-
-int sndo_pcm_param_reset(sndo_pcm_t *pcm);
-int sndo_pcm_param_access(sndo_pcm_t *pcm, enum sndo_pcm_access_type access);
-int sndo_pcm_param_rate(sndo_pcm_t *pcm, unsigned int rate, unsigned int *used_rate);
-int sndo_pcm_param_channels(sndo_pcm_t *pcm, unsigned int channels);
-int sndo_pcm_param_format(sndo_pcm_t *pcm, snd_pcm_format_t format, snd_pcm_subformat_t subformat);
-int sndo_pcm_param_latency(sndo_pcm_t *pcm, enum sndo_pcm_latency_type latency, snd_pcm_uframes_t *used_latency);
-int sndo_pcm_param_xrun(sndo_pcm_t *pcm, enum sndo_pcm_xrun_type xrun);
-
-/** \} */
-
-/**
- * \defgroup PCM_ordinary_access Ring Buffer I/O Functions
- * \ingroup PCM_ordinary
- * See the \ref pcm_ordinary page for more details.
- * \{
- */
-
-/* playback */
-int sndo_pcm_pio_ibegin(sndo_pcm_t *pcm, void **ring_buffer, snd_pcm_uframes_t *frames);
-snd_pcm_sframes_t sndo_pcm_pio_iend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames);
-int sndo_pcm_pio_nbegin(sndo_pcm_t *pcm, void ***ring_buffer, snd_pcm_uframes_t *frames);
-snd_pcm_sframes_t sndo_pcm_pio_nend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames);
-/* capture */
-int sndo_pcm_cio_ibegin(sndo_pcm_t *pcm, void **ring_buffer, snd_pcm_uframes_t *frames);
-snd_pcm_sframes_t sndo_pcm_cio_iend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames);
-int sndo_pcm_cio_nbegin(sndo_pcm_t *pcm, void ***ring_buffer, snd_pcm_uframes_t *frames);
-snd_pcm_sframes_t sndo_pcm_cio_nend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames);
-
-/** \} */
-
-/**
- * \defgroup PCM_ordinary_engine Callback like engine
- * \ingroup PCM_ordinary
- * See the \ref pcm_ordinary page for more details.
- * \{
- */
-
-int sndo_pcm_set_private_data(sndo_pcm_t *pcm, void *private_data);
-int sndo_pcm_get_private_data(sndo_pcm_t *pcm, void **private_data);
-int sndo_pcm_engine(sndo_pcm_t *pcm,
- sndo_pcm_engine_callback_t *playback,
- sndo_pcm_engine_callback_t *capture);
-
-/** \} */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __ALSA_PCM_ORDINARY_H */
-SUBDIRS=control mixer ordinary_mixer pcm ordinary_pcm rawmidi timer hwdep seq instr compat conf alisp
+SUBDIRS=control mixer pcm rawmidi timer hwdep seq instr compat conf alisp
EXTRA_DIST=Versions
COMPATNUM=@LIBTOOL_VERSION_INFO@
+++ /dev/null
-#SUBDIRS =
-#DIST_SUBDIRS =
-
-EXTRA_LTLIBRARIES = libordinarymixer.la
-
-libordinarymixer_la_SOURCES = ordinary_mixer.c
-#noinst_HEADERS =
-
-alsadir = $(datadir)/alsa
-
-all: libordinarymixer.la
-
-INCLUDES=-I$(top_srcdir)/include
+++ /dev/null
-/**
- * \file ordinary_mixer/ordinary_mixer.c
- * \ingroup Mixer_ordinary
- * \brief Ordinary mixer interface
- * \author Jaroslav Kysela <perex@suse.cz>
- * \date 2003,2004
- *
- * Ordinary mixer interface is a high level abtraction for soundcard's
- * mixing.
- *
- * See the \ref Mixer_ordinary page for more details.
- */
-/*
- * Ordinary Mixer Interface - main file
- * Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * 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
- *
- */
-
-/*! \page Mixer_ordinary Ordinary mixer interface
-
-<P>Write something here</P>
-
-\section Mixer_ordinary_overview
-
-Write something here
-
-*/
-/**
- * \example ../test/ordinary_mixer.c
- * \anchor example_ordinary_mixer
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <malloc.h>
-#include <stdarg.h>
-#include <signal.h>
-#include <dlfcn.h>
-#include <sys/ioctl.h>
-#include <sys/poll.h>
-#include <sys/shm.h>
-#include <sys/mman.h>
-#include <limits.h>
-#include "local.h"
-#include "alisp.h"
-#include "mixer_ordinary.h"
-
-struct sndo_mixer {
- struct alisp_cfg *cfg;
- struct alisp_instance *alisp;
- int hctl_count;
- snd_hctl_t **hctl;
- int _free_cfg;
-};
-
-int sndo_mixer_open1(sndo_mixer_t **pmixer,
- const char *lisp_fcn,
- const char *lisp_fmt,
- const void *parg,
- const void *carg,
- struct alisp_cfg *lconf)
-{
- struct alisp_cfg *cfg = lconf;
- struct alisp_instance *alisp;
- struct alisp_seq_iterator *iterator;
- sndo_mixer_t *mixer;
- int err, count;
- long val;
-
- *pmixer = NULL;
- if (cfg == NULL) {
- char *file;
- snd_input_t *input;
- file = getenv("ALSA_ORDINARY_MIXER");
- if (!file)
- file = DATADIR "/alsa/sndo-mixer.alisp";
- if ((err = snd_input_stdio_open(&input, file, "r")) < 0) {
- SNDERR("unable to open alisp file '%s'", file);
- return err;
- }
- cfg = alsa_lisp_default_cfg(input);
- if (cfg == NULL)
- return -ENOMEM;
- cfg->warning = 1;
-#if 0
- cfg->debug = 1;
- cfg->verbose = 1;
-#endif
- }
- err = alsa_lisp(cfg, &alisp);
- if (err < 0)
- goto __error;
- err = alsa_lisp_function(alisp, &iterator, lisp_fcn, lisp_fmt, parg, carg);
- if (err < 0) {
- alsa_lisp_free(alisp);
- goto __error;
- }
- err = alsa_lisp_seq_integer(iterator, &val);
- if (err == 0 && val < 0)
- err = val;
- alsa_lisp_result_free(alisp, iterator);
- if (err < 0) {
- alsa_lisp_free(alisp);
- goto __error;
- }
- count = 0;
- if (alsa_lisp_seq_first(alisp, "hctls", &iterator) == 0) {
- count = alsa_lisp_seq_count(iterator);
- if (count < 0)
- count = 0;
- }
- mixer = malloc(sizeof(sndo_mixer_t) + count * sizeof(snd_hctl_t *));
- if (mixer == NULL) {
- alsa_lisp_free(alisp);
- err = -ENOMEM;
- goto __error;
- }
- memset(mixer, 0, sizeof(sndo_mixer_t));
- if (count > 0) {
- mixer->hctl = (snd_hctl_t **)(mixer + 1);
- do {
- if (alsa_lisp_seq_pointer(iterator, "hctl", (void **)&mixer->hctl[mixer->hctl_count++]))
- break;
- } while (mixer->hctl_count < count && alsa_lisp_seq_next(&iterator) == 0);
- if (mixer->hctl_count < count) {
- mixer->hctl = NULL;
- mixer->hctl_count = 0;
- }
- }
- mixer->alisp = alisp;
- mixer->cfg = cfg;
- mixer->_free_cfg = cfg != lconf;
- *pmixer = mixer;
- return 0;
- __error:
- if (cfg != lconf)
- alsa_lisp_default_cfg_free(cfg);
- return err;
-}
-
-/**
- * \brief Opens a ordinary mixer instance
- * \param pmixer Returned ordinary mixer handle
- * \param playback_name name for playback HCTL communication
- * \param capture_name name for capture HCTL communication
- * \param lconf Local configuration (might be NULL - use global configuration)
- * \return 0 on success otherwise a negative error code
- */
-int sndo_mixer_open(sndo_mixer_t **pmixer,
- const char *playback_name,
- const char *capture_name,
- struct alisp_cfg *lconf)
-{
- return sndo_mixer_open1(pmixer, "sndo_mixer_open", "%s%s", playback_name, capture_name, lconf);
-}
-
-
-/**
- * \brief Opens a ordinary mixer instance
- * \param pmixer Returned ordinary mixer handle
- * \param playback_pcm handle of the playback PCM
- * \param capture_pcm handle of the capture PCM
- * \param lconf Local configuration (might be NULL - use global configuration)
- * \return 0 on success otherwise a negative error code
- */
-int sndo_mixer_open_pcm(sndo_mixer_t **pmixer,
- snd_pcm_t *playback_pcm,
- snd_pcm_t *capture_pcm,
- struct alisp_cfg *lconf)
-{
- return sndo_mixer_open1(pmixer, "sndo_mixer_open_pcm", "%ppcm%ppcm", playback_pcm, capture_pcm, lconf);
-}
-
-/**
- * \brief Closes a ordinary mixer instance
- * \param mixer Ordinary mixer handle to close
- * \return 0 on success otherwise a negative error code
- */
-int sndo_mixer_close(sndo_mixer_t *mixer)
-{
- int res;
-
- res = alsa_lisp_function(mixer->alisp, NULL, "sndo_mixer_close", "n");
- alsa_lisp_free(mixer->alisp);
- if (mixer->_free_cfg)
- alsa_lisp_default_cfg_free(mixer->cfg);
- free(mixer);
- return res;
-}
-
-/**
- * \brief get count of poll descriptors for ordinary mixer handle
- * \param mixer ordinary mixer handle
- * \return count of poll descriptors
- */
-int sndo_mixer_poll_descriptors_count(sndo_mixer_t *mixer)
-{
- int idx, err, res = -EIO;
-
- if (mixer->hctl_count > 0) {
- for (idx = 0; idx < mixer->hctl_count; idx++) {
- err = snd_hctl_poll_descriptors_count(mixer->hctl[idx]);
- if (err < 0)
- return err;
- res += err;
- }
- } else {
- struct alisp_seq_iterator *result;
- long val;
- err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_poll_descriptors_count", "n");
- if (err < 0)
- return err;
- err = alsa_lisp_seq_integer(result, &val);
- return err < 0 ? err : val;
- }
- return res;
-}
-
-/**
- * \brief get poll descriptors
- * \param mixer ordinary mixer handle
- * \param pfds array of poll descriptors
- * \param space space in the poll descriptor array
- * \return count of filled descriptors
- */
-int sndo_mixer_poll_descriptors(sndo_mixer_t *mixer, struct pollfd *pfds, unsigned int space)
-{
- int err, idx, res;
-
- if (mixer->hctl_count > 0) {
- for (idx = res = 0; idx < mixer->hctl_count && space > 0; idx++) {
- err = snd_hctl_poll_descriptors(mixer->hctl[idx], pfds, space);
- if (err < 0)
- return err;
- res += err;
- space -= err;
- }
- return res;
- } else {
- struct alisp_seq_iterator *result;
- long val;
- err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_poll_descriptors", "%i", space);
- if (err < 0)
- return err;
- assert(0); /* FIXME: pass pfds to application */
- err = alsa_lisp_seq_integer(result, &val);
- return err < 0 ? err : val;
- }
-}
-
-/**
- * \brief get returned events from poll descriptors
- * \param mixer ordinary mixer 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
- */
-int sndo_mixer_poll_descriptors_revents(sndo_mixer_t *mixer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
-{
- int err, idx, count, res;
-
- if (mixer->hctl_count > 0) {
- for (idx = res = 0; idx < mixer->hctl_count && nfds > 0; idx++) {
- err = snd_hctl_poll_descriptors_count(mixer->hctl[idx]);
- if (err < 0)
- return err;
- count = err;
- if (nfds < (unsigned int)err)
- return -EINVAL;
- err = snd_hctl_poll_descriptors_revents(mixer->hctl[idx], pfds, count, revents);
- if (err < 0)
- return err;
- if (err != count)
- return -EINVAL;
- pfds += count;
- nfds -= err;
- revents += count;
- res += count;
- }
- return res;
- } else {
- struct alisp_seq_iterator *result;
- long val, tmp;
-
- assert(0); /* FIXME: pass pfds to alisp too */
- err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_poll_descriptors_revents", "%i", nfds);
- if (err < 0)
- return err;
- err = alsa_lisp_seq_integer(result, &val);
- if (err >= 0 && alsa_lisp_seq_count(result) > 1) {
- alsa_lisp_seq_next(&result);
- err = alsa_lisp_seq_integer(result, &tmp);
- *revents = tmp;
- } else {
- *revents = 0;
- }
- return err < 0 ? err : val;
- }
-}
-
-#define IOLINES 6
-
-static const char *name_table1[] = {
- "Master",
- "PCM",
- "Line",
- "Mic"
- "CD",
- "AUX"
-};
-
-#define SPEAKERS 14
-
-static const char *name_table2[] = {
- "Front Left",
- "Front Center Left",
- "Front Center",
- "Front Center Right",
- "Front Right",
- "Front Side Left",
- "Front Side Right",
- "Rear Side Left",
- "Rear Side Right",
- "Rear Left",
- "Rear Center",
- "Rear Right",
- "LFE (Subwoofer)",
- "Overhead"
-};
-
-#define CSOURCES 5
-
-static const char *name_table3[] = {
- "Mic",
- "Line",
- "CD",
- "AUX",
- "Mix",
-};
-
-static int compose_string(char **result, const char *s1, const char *s2, const char *s3, const char *s4)
-{
- int len = strlen(s1) + strlen(s2) + strlen(s3) + strlen(s4);
- *result = malloc(len + 1);
- if (*result == NULL)
- return -ENOMEM;
- strcpy(*result, s1);
- strcat(*result, s2);
- strcat(*result, s3);
- strcat(*result, s4);
- return 0;
-}
-
-/**
- * \brief get ordinary mixer io control value
- * \param mixer ordinary mixer handle
- * \param type io type
- * \param val returned value
- * \return zero if success, otherwise a negative error code
- */
-int sndo_mixer_io_get_name(enum sndo_mixer_io_type type, char **name)
-{
- if (type < IOLINES * 0x40) {
- int tmp = type / 0x40;
- type %= 0x40;
- if (type < SPEAKERS)
- return compose_string(name, name_table1[tmp], " ", name_table2[type], " Volume");
- } else if (type >= SNDO_MIO_CGAIN_FL && type < SNDO_MIO_CGAIN_FL + SPEAKERS) {
- return compose_string(name, "Capture Gain ", name_table2[type - SNDO_MIO_CGAIN_FL], "", "");
- } else if (type >= SNDO_MIO_CSOURCE_MIC && type < SNDO_MIO_CSOURCE_MIC + CSOURCES) {
- return compose_string(name, "Capture Source ", name_table3[type - SNDO_MIO_CSOURCE_MIC], "", "");
- }
- return -ENOENT;
-}
-
-/**
- * \brief get ordinary mixer io control value
- * \param mixer ordinary mixer handle
- * \param type io type
- * \param val returned value
- * \return zero if success, otherwise a negative error code
- */
-int sndo_mixer_io_get(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val)
-{
- struct alisp_seq_iterator *result;
- long val1;
- int err;
-
- err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_io_set", "%i", type);
- if (err < 0)
- return err;
- err = alsa_lisp_seq_integer(result, &val1);
- if (err < 0)
- return err;
- *val = val1;
- return 0;
-}
-
-/**
- * \brief set ordinary mixer io control value
- * \param mixer ordinary mixer handle
- * \param type io type
- * \param val desired value
- * \return zero if success, otherwise a negative error code
- */
-int sndo_mixer_io_set(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val)
-{
- struct alisp_seq_iterator *result;
- long val1;
- int err;
-
- err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_io_set", "%i%i", type, *val);
- if (err < 0)
- return err;
- err = alsa_lisp_seq_integer(result, &val1);
- if (err < 0)
- return err;
- *val = val1;
- return 0;
-}
-
-/**
- * \brief try to set ordinary mixer io control value
- * \param mixer ordinary mixer handle
- * \param type io type
- * \param val desired value
- * \return zero if success, otherwise a negative error code
- *
- * This function does not update the value.
- * It only returns the real value which will be set.
- */
-int sndo_mixer_io_try_set(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val)
-{
- struct alisp_seq_iterator *result;
- long val1;
- int err;
-
- err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_io_try_set", "%i%i", type, *val);
- if (err < 0)
- return err;
- err = alsa_lisp_seq_integer(result, &val1);
- if (err < 0)
- return err;
- *val = val1;
- return 0;
-}
-
-/**
- * \brief get ordinary mixer io control value in dB (decibel units)
- * \param mixer ordinary mixer handle
- * \param type io type
- * \param val returned value in dB
- * \return zero if success, otherwise a negative error code
- */
-int sndo_mixer_io_get_dB(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val)
-{
- struct alisp_seq_iterator *result;
- long val1;
- int err;
-
- err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_io_set_dB", "%i", type);
- if (err < 0)
- return err;
- err = alsa_lisp_seq_integer(result, &val1);
- if (err < 0)
- return err;
- *val = val1;
- return 0;
-}
-
-/**
- * \brief set ordinary mixer io control value in dB (decibel units)
- * \param mixer ordinary mixer handle
- * \param type io type
- * \param val desired value in dB
- * \return zero if success, otherwise a negative error code
- */
-int sndo_mixer_io_set_dB(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val)
-{
- struct alisp_seq_iterator *result;
- long val1;
- int err;
-
- err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_io_set", "%i%i", type, *val);
- if (err < 0)
- return err;
- err = alsa_lisp_seq_integer(result, &val1);
- if (err < 0)
- return err;
- *val = val1;
- return 0;
-}
-
-/**
- * \brief try to set ordinary mixer io control value in dB (decibel units)
- * \param mixer ordinary mixer handle
- * \param type io type
- * \param val desired and returned value in dB
- * \return zero if success, otherwise a negative error code
- *
- * This function does not update the value.
- * It only returns the real value which will be set.
- */
-int sndo_mixer_io_try_set_dB(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val)
-{
- struct alisp_seq_iterator *result;
- long val1;
- int err;
-
- err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_io_try_set", "%i%i", type, *val);
- if (err < 0)
- return err;
- err = alsa_lisp_seq_integer(result, &val1);
- if (err < 0)
- return err;
- *val = val1;
- return 0;
-}
-
-/**
- * \brief get ordinary mixer io control change notification
- * \param mixer ordinary mixer handle
- * \param changed list of changed io types
- * \param changed_array_size size of list of changed io types
- * \return zero if success, otherwise a negative error code
- */
-int sndo_mixer_io_change(sndo_mixer_t *mixer, enum sndo_mixer_io_type *changed, int changed_array_size)
-{
- struct alisp_seq_iterator *result;
- long val1;
- int err;
-
- err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_io_change", "%i", changed_array_size);
- if (err < 0)
- return err;
- err = alsa_lisp_seq_integer(result, &val1);
- if (err < 0)
- return err;
- if (val1 < 0)
- return val1;
- while (changed_array_size-- > 0) {
- *changed = val1;
- if (!alsa_lisp_seq_next(&result))
- break;
- err = alsa_lisp_seq_integer(result, &val1);
- if (err < 0)
- return err;
- }
- return 0;
-}
+++ /dev/null
-#SUBDIRS =
-#DIST_SUBDIRS =
-
-EXTRA_LTLIBRARIES = libordinarypcm.la
-
-libordinarypcm_la_SOURCES = ordinary_pcm.c
-#noinst_HEADERS =
-
-alsadir = $(datadir)/alsa
-
-all: libordinarypcm.la
-
-INCLUDES=-I$(top_srcdir)/include
+++ /dev/null
-/**
- * \file ordinary_pcm/ordinary_pcm.c
- * \ingroup PCM_ordinary
- * \brief Ordinary PCM interface
- * \author Jaroslav Kysela <perex@suse.cz>
- * \date 2003,2004
- *
- * Ordinary PCM interface is a high level abtraction for
- * digital audio streaming.
- *
- * See the \ref PCM_ordinary page for more details.
- */
-/*
- * Ordinary PCM Interface - main file
- * Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * 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
- *
- */
-
-/*! \page PCM_ordinary Ordinary PCM interface
-
-<P>Write something here</P>
-
-\section PCM_ordinary_overview
-
-Write something here
-
-*/
-/**
- * \example ../test/ordinary_pcm.c
- * \anchor example_ordinary_pcm
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <malloc.h>
-#include <stdarg.h>
-#include <signal.h>
-#include <dlfcn.h>
-#include <sys/ioctl.h>
-#include <sys/poll.h>
-#include <sys/shm.h>
-#include <sys/mman.h>
-#include <limits.h>
-#include "asoundlib.h"
-#include "alisp.h"
-#include "pcm_ordinary.h"
-
-struct sndo_pcm {
- snd_pcm_t *playback;
- snd_pcm_t *capture;
- snd_pcm_hw_params_t *p_hw_params;
- snd_pcm_hw_params_t *c_hw_params;
- snd_pcm_sw_params_t *p_sw_params;
- snd_pcm_sw_params_t *c_sw_params;
- snd_pcm_t *master;
- unsigned int channels;
- unsigned int samplebytes;
- snd_pcm_uframes_t p_offset;
- snd_pcm_uframes_t c_offset;
- snd_pcm_uframes_t p_period_size;
- snd_pcm_uframes_t c_period_size;
- snd_pcm_uframes_t transfer_block;
- snd_pcm_uframes_t ring_size;
- enum sndo_pcm_latency_type latency;
- enum sndo_pcm_xrun_type xrun;
- int setting_up;
- int initialized;
-};
-
-static int sndo_pcm_setup(sndo_pcm_t *pcm);
-static int sndo_pcm_initialize(sndo_pcm_t *pcm);
-
-static inline int sndo_pcm_check_setup(sndo_pcm_t *pcm)
-{
- if (!pcm->initialized)
- return sndo_pcm_initialize(pcm);
- return 0;
-}
-
-/**
- * \brief Opens a ordinary pcm instance
- * \param ppcm Returned ordinary pcm handle
- * \param playback_name ASCII identifier of the ordinary pcm handle (playback)
- * \param capture_name ASCII identifier of the ordinary pcm handle (capture)
- * \param lconf Local configuration (might be NULL - use global configuration)
- * \return 0 on success otherwise a negative error code
- */
-int sndo_pcm_open(sndo_pcm_t **ppcm,
- const char *playback_name,
- const char *capture_name,
- struct alisp_cfg *lconf)
-{
- int err = 0;
- sndo_pcm_t *pcm;
-
- assert(ppcm);
- assert(playback_name || capture_name);
- *ppcm = NULL;
- pcm = calloc(1, sizeof(sndo_pcm_t));
- if (pcm == NULL)
- return -ENOMEM;
- if (playback_name) {
- err = snd_pcm_hw_params_malloc(&pcm->p_hw_params);
- if (err < 0)
- goto __end;
- err = snd_pcm_sw_params_malloc(&pcm->p_sw_params);
- }
- if (capture_name) {
- err = snd_pcm_hw_params_malloc(&pcm->c_hw_params);
- if (err < 0)
- goto __end;
- err = snd_pcm_sw_params_malloc(&pcm->p_sw_params);
- }
- if (err < 0)
- goto __end;
- if (lconf) {
- if (playback_name) {
- err = snd_pcm_open_lconf(&pcm->playback, playback_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK, NULL);
- if (err < 0)
- goto __end;
- }
- if (capture_name) {
- err = snd_pcm_open_lconf(&pcm->capture, playback_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK, NULL);
- if (err < 0)
- goto __end;
- }
- } else {
- if (playback_name) {
- err = snd_pcm_open(&pcm->playback, playback_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
- if (err < 0)
- goto __end;
- }
- if (capture_name) {
- err = snd_pcm_open(&pcm->capture, playback_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
- if (err < 0)
- goto __end;
- }
- }
- if (pcm->playback && pcm->capture) {
- err = snd_pcm_link(pcm->playback, pcm->capture);
- if (err < 0)
- goto __end;
- pcm->master = pcm->playback;
- }
- __end:
- if (err < 0)
- sndo_pcm_close(pcm);
- return err;
-}
-
-/**
- * \brief Closes a ordinary pcm instance
- * \param pcm Ordinary pcm handle to close
- * \return 0 on success otherwise a negative error code
- */
-int sndo_pcm_close(sndo_pcm_t *pcm)
-{
- int err;
-
- if (pcm->playback)
- err = snd_pcm_close(pcm->playback);
- if (pcm->capture)
- err = snd_pcm_close(pcm->capture);
- if (pcm->p_hw_params)
- snd_pcm_hw_params_free(pcm->p_hw_params);
- if (pcm->p_sw_params)
- snd_pcm_sw_params_free(pcm->p_sw_params);
- if (pcm->c_hw_params)
- snd_pcm_hw_params_free(pcm->c_hw_params);
- if (pcm->c_sw_params)
- snd_pcm_sw_params_free(pcm->c_sw_params);
- free(pcm);
- return 0;
-}
-
-/**
- * \brief get count of poll descriptors for ordinary pcm handle
- * \param pcm ordinary pcm handle
- * \return count of poll descriptors
- */
-int sndo_pcm_poll_descriptors_count(sndo_pcm_t *pcm)
-{
- int err, res = 0;
-
- err = snd_pcm_poll_descriptors_count(pcm->playback);
- if (err > 0)
- res += err;
- err = snd_pcm_poll_descriptors_count(pcm->capture);
- if (err > 0)
- res += err;
- return err < 0 ? err : res;
-}
-
-/**
- * \brief get poll descriptors
- * \param pcm ordinary pcm handle
- * \param pfds array of poll descriptors
- * \param space space in the poll descriptor array
- * \return count of filled descriptors
- */
-int sndo_pcm_poll_descriptors(sndo_pcm_t *pcm, struct pollfd *pfds, unsigned int space)
-{
- int playback, err, res = 0;
-
- playback = snd_pcm_poll_descriptors_count(pcm->playback);
- if (playback < 0)
- return playback;
- err = snd_pcm_poll_descriptors(pcm->playback, pfds, (unsigned)playback < space ? (unsigned)playback : space);
- if (err < 0)
- return err;
- res += err;
- if ((unsigned)res < space) {
- err = snd_pcm_poll_descriptors(pcm->capture, pfds + res, space - res);
- if (err < 0)
- return err;
- res += err;
- }
- return res;
-}
-
-/**
- * \brief get returned events from poll descriptors
- * \param pcm ordinary 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
- */
-int sndo_pcm_poll_descriptors_revents(sndo_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
-{
- int playback, err;
- unsigned short _revents;
-
- playback = snd_pcm_poll_descriptors_count(pcm->playback);
- if (playback < 0)
- return playback;
- err = snd_pcm_poll_descriptors_revents(pcm->playback, pfds, nfds < (unsigned)playback ? nfds : (unsigned)playback, revents);
- if (err < 0)
- return err;
- if (nfds > (unsigned)playback) {
- err = snd_pcm_poll_descriptors_revents(pcm->capture, pfds + playback, nfds - playback, &_revents);
- if (err < 0)
- return err;
- *revents |= _revents;
- }
- return 0;
-}
-
-/**
- * \brief Start a PCM
- * \param pcm ordinary PCM handle
- * \return 0 on success otherwise a negative error code
- */
-int sndo_pcm_start(sndo_pcm_t *pcm)
-{
- int err;
-
- err = sndo_pcm_check_setup(pcm);
- if (err < 0)
- return err;
- /* the streams are linked, so use only one stream */
- return snd_pcm_start(pcm->master);
-}
-
-/**
- * \brief Stop a PCM dropping pending frames
- * \param pcm ordinary PCM handle
- * \return 0 on success otherwise a negative error code
- */
-int sndo_pcm_drop(sndo_pcm_t *pcm)
-{
- /* the streams are linked, so use only one stream */
- return snd_pcm_drop(pcm->master);
-}
-
-/**
- * \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.
- */
-int sndo_pcm_drain(sndo_pcm_t *pcm)
-{
- /* the streams are linked, so use only one stream */
- return snd_pcm_drain(pcm->master);
-}
-
-/**
- * \brief Obtain delay for a running PCM handle
- * \param pcm ordinary 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.
- */
-int sndo_pcm_delay(sndo_pcm_t *pcm, snd_pcm_sframes_t *delayp)
-{
- int err;
- snd_pcm_sframes_t pdelay, cdelay;
-
- assert(pcm);
- assert(delayp);
- err = sndo_pcm_check_setup(pcm);
- if (err < 0)
- return err;
- if (pcm->playback)
- err = snd_pcm_avail_update(pcm->playback);
- if (err >= 0 && pcm->capture)
- err = snd_pcm_avail_update(pcm->capture);
- if (err >= 0 && pcm->playback)
- err = snd_pcm_delay(pcm->playback, &pdelay);
- if (err >= 0 && pcm->capture)
- err = snd_pcm_delay(pcm->capture, &cdelay);
- if (pdelay > cdelay)
- pdelay = cdelay;
- *delayp = pdelay;
- return err;
-}
-
-/**
- * \brief Obtain transfer block size (aka period size)
- * \param pcm ordinary PCM handle
- * \param tblock Returned transfer block size in frames
- * \return 0 on success otherwise a negative error code
- *
- * All read/write operations must use this transfer block.
- */
-int sndo_pcm_transfer_block(sndo_pcm_t *pcm, snd_pcm_uframes_t *tblock)
-{
- int err;
-
- assert(pcm);
- assert(tblock);
- err = sndo_pcm_check_setup(pcm);
- if (err < 0)
- return err;
- *tblock = pcm->transfer_block;
- return 0;
-}
-
-/**
- * \brief Resume from suspend, no samples are lost
- * \param pcm ordinary PCM handle
- * \return 0 on success otherwise a negative error code
- * \retval -EAGAIN resume can't be proceed immediately (audio hardware is probably 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 snd_pcm_prepare
- * function to recovery.
- */
-int sndo_pcm_resume(sndo_pcm_t *pcm)
-{
- return snd_pcm_resume(pcm->master);
-}
-
-/**
- * \brief Wait for a PCM to become ready
- * \param pcm ordinary PCM handle
- * \param timeout maximum time in milliseconds to wait
- * \return a positive value on success otherwise a negative error code
- * \retval 0 timeout occurred
- * \retval 1 PCM stream is ready for I/O
- */
-int sndo_pcm_wait(sndo_pcm_t *pcm, int timeout)
-{
- struct pollfd pfd[2];
- unsigned short p_revents, c_revents;
- int err;
- err = snd_pcm_poll_descriptors(pcm->playback, &pfd[0], 1);
- assert(err == 1);
- err = snd_pcm_poll_descriptors(pcm->capture, &pfd[1], 1);
- assert(err == 1);
- err = poll(pfd, 2, timeout);
- if (err < 0)
- return -errno;
- if (err == 0)
- return 0;
- do {
- err = snd_pcm_poll_descriptors_revents(pcm->playback, &pfd[0], 1, &p_revents);
- if (err < 0)
- return err;
- if (p_revents & (POLLERR | POLLNVAL))
- return -EIO;
- err = snd_pcm_poll_descriptors_revents(pcm->capture, &pfd[1], 1, &c_revents);
- if (err < 0)
- return err;
- if (c_revents & (POLLERR | POLLNVAL))
- return -EIO;
- if ((p_revents & POLLOUT) && (c_revents & POLLIN))
- return 1;
- err = poll(&pfd[(p_revents & POLLOUT) ? 1 : 0], 1, 1);
- if (err < 0)
- return err;
- } while (1);
-}
-
-/**
- * \brief Get raw (lowlevel) playback PCM handle
- * \param pcm ordinary PCM handle
- * \return raw (lowlevel) capture PCM handle or NULL
- */
-snd_pcm_t *sndo_pcm_raw_playback(sndo_pcm_t *pcm)
-{
- return pcm->playback;
-}
-
-/**
- * \brief Get raw (lowlevel) capture PCM handle
- * \param pcm ordinary PCM handle
- * \return raw (lowlevel) capture PCM handle or NULL
- */
-snd_pcm_t *sndo_pcm_raw_capture(sndo_pcm_t *pcm)
-{
- return pcm->capture;
-}
-
-/**
- * \brief Reset all parameters
- * \param pcm ordinary PCM handle
- * \return 0 on success otherwise a negative error code
- */
-int sndo_pcm_param_reset(sndo_pcm_t *pcm)
-{
- int err;
-
- err = sndo_pcm_drain(pcm);
- if (err < 0)
- return err;
- pcm->initialized = 0;
- if (pcm->playback) {
- err = snd_pcm_hw_params_any(pcm->playback, pcm->p_hw_params);
- if (err < 0)
- return err;
- err = snd_pcm_sw_params_current(pcm->playback, pcm->p_sw_params);
- if (err < 0)
- return err;
- }
- if (pcm->capture) {
- err = snd_pcm_hw_params_any(pcm->capture, pcm->c_hw_params);
- if (err < 0)
- return err;
- err = snd_pcm_sw_params_current(pcm->capture, pcm->c_sw_params);
- if (err < 0)
- return err;
- }
- return 0;
-}
-
-/**
- * \brief Set sample access type
- * \param pcm ordinary PCM handle
- * \param access access type (interleaved or noninterleaved)
- * \return 0 on success otherwise a negative error code
- */
-int sndo_pcm_param_access(sndo_pcm_t *pcm, enum sndo_pcm_access_type access)
-{
- int err;
- snd_pcm_access_t native_access = SND_PCM_ACCESS_MMAP_INTERLEAVED;
-
- switch (access) {
- case SNDO_PCM_ACCESS_INTERLEAVED: native_access = SND_PCM_ACCESS_MMAP_INTERLEAVED; break;
- case SNDO_PCM_ACCESS_NONINTERLEAVED: native_access = SND_PCM_ACCESS_MMAP_NONINTERLEAVED; break;
- default:
- return -EINVAL;
- }
- err = sndo_pcm_setup(pcm);
- if (err < 0)
- return err;
- if (pcm->playback) {
- err = snd_pcm_hw_params_set_access(pcm->playback, pcm->p_hw_params, native_access);
- if (err < 0) {
- SNDERR("cannot set requested access for the playback direction");
- return err;
- }
- }
- if (pcm->capture) {
- err = snd_pcm_hw_params_set_access(pcm->capture, pcm->c_hw_params, native_access);
- if (err < 0) {
- SNDERR("cannot set requested access for the capture direction");
- return err;
- }
- }
- return 0;
-}
-
-/**
- * \brief Set stream rate
- * \param pcm ordinary PCM handle
- * \param rate requested rate
- * \param used_rate returned real rate
- * \return 0 on success otherwise a negative error code
- */
-int sndo_pcm_param_rate(sndo_pcm_t *pcm, unsigned int rate, unsigned int *used_rate)
-{
- int err;
- unsigned int prate = rate, crate = rate;
-
- err = sndo_pcm_setup(pcm);
- if (err < 0)
- return err;
- if (pcm->playback) {
- err = snd_pcm_hw_params_set_rate_near(pcm->playback, pcm->p_hw_params, &prate, 0);
- if (err < 0) {
- SNDERR("cannot set requested rate for the playback direction");
- return err;
- }
- }
- if (pcm->capture) {
- err = snd_pcm_hw_params_set_rate_near(pcm->capture, pcm->c_hw_params, &crate, 0);
- if (err < 0) {
- SNDERR("cannot set requested rate for the capture direction");
- return err;
- }
- }
- if (used_rate)
- *used_rate = pcm->capture ? crate : prate;
- return 0;
-}
-
-/**
- * \brief Set channels in stream
- * \param pcm ordinary PCM handle
- * \param channels requested channels
- * \return 0 on success otherwise a negative error code
- */
-int sndo_pcm_param_channels(sndo_pcm_t *pcm, unsigned int channels)
-{
- int err;
-
- err = sndo_pcm_setup(pcm);
- if (err < 0)
- return err;
- if (pcm->playback) {
- err = snd_pcm_hw_params_set_channels(pcm->capture, pcm->p_hw_params, channels);
- if (err < 0) {
- SNDERR("cannot set requested channels for the playback direction");
- return err;
- }
- }
- if (pcm->capture) {
- err = snd_pcm_hw_params_set_channels(pcm->capture, pcm->c_hw_params, channels);
- if (err < 0) {
- SNDERR("cannot set requested channels for the capture direction");
- return err;
- }
- }
- return 0;
-}
-
-/**
- * \brief Set stream format
- * \param pcm ordinary PCM handle
- * \param rate requested channels
- * \param used_rate returned real channels
- * \return 0 on success otherwise a negative error code
- */
-int sndo_pcm_param_format(sndo_pcm_t *pcm, snd_pcm_format_t format, snd_pcm_subformat_t subformat)
-{
- int err;
-
- if (subformat != SND_PCM_SUBFORMAT_STD)
- return -EINVAL;
- err = snd_pcm_format_physical_width(format);
- if (err < 0)
- return err;
- if (err % 8)
- return -EINVAL;
- err = sndo_pcm_setup(pcm);
- if (err < 0)
- return err;
- if (pcm->playback) {
- err = snd_pcm_hw_params_set_format(pcm->capture, pcm->p_hw_params, format);
- if (err < 0) {
- SNDERR("cannot set requested format for the playback direction");
- return err;
- }
- }
- if (pcm->capture) {
- err = snd_pcm_hw_params_set_format(pcm->capture, pcm->c_hw_params, format);
- if (err < 0) {
- SNDERR("cannot set requested format for the capture direction");
- return err;
- }
- }
- return 0;
-}
-
-/**
- * \brief Set stream latency
- * \param pcm ordinary PCM handle
- * \param latency requested latency
- * \param used_latency returned real latency in frames
- * \return 0 on success otherwise a negative error code
- *
- * Note that the result value is only approximate and for one direction.
- * For example, hardware FIFOs are not counted etc.
- */
-int sndo_pcm_param_latency(sndo_pcm_t *pcm, enum sndo_pcm_latency_type latency, snd_pcm_uframes_t *used_latency)
-{
- int err;
-
- err = sndo_pcm_setup(pcm);
- if (err < 0)
- return err;
- pcm->latency = latency;
- err = sndo_pcm_check_setup(pcm);
- if (err < 0)
- return err;
- if (used_latency)
- *used_latency = pcm->ring_size;
- return 0;
-}
-
-/**
- * \brief Set xrun behaviour
- * \param pcm ordinary PCM handle
- * \param xrun requested behaviour
- * \return 0 on success otherwise a negative error code
- */
-int sndo_pcm_param_xrun(sndo_pcm_t *pcm, enum sndo_pcm_xrun_type xrun)
-{
- int err;
-
- err = sndo_pcm_setup(pcm);
- if (err < 0)
- return err;
- pcm->xrun = xrun;
- return 0;
-}
-
-/**
- * \brief Begin the playback interleaved frame update
- * \param pcm ordinary PCM handle
- * \param ring_buffer returned pointer to actual destination area
- * \param frames returned maximum count of updated frames
- * \return 0 on success otherwise a negative error code
- */
-int sndo_pcm_pio_ibegin(sndo_pcm_t *pcm, void **ring_buffer, snd_pcm_uframes_t *frames)
-{
- int err;
- const snd_pcm_channel_area_t *areas;
-
- err = sndo_pcm_check_setup(pcm);
- if (err < 0)
- return err;
- err = snd_pcm_mmap_begin(pcm->playback, &areas, &pcm->p_offset, frames);
- if (err < 0)
- return err;
- if (*frames < pcm->transfer_block) {
- frames = 0;
- } else {
- *frames -= *frames % pcm->transfer_block;
- *ring_buffer = (char *)areas->addr + (areas->first / 8) + pcm->p_offset * pcm->samplebytes;
- }
- return 0;
-}
-
-/**
- * \brief Finish the playback interleave frame update (commit data to hardware)
- * \param pcm ordinary PCM handle
- * \param frames count of updated frames
- * \return count of transferred frames on success otherwise a negative error code
- */
-snd_pcm_sframes_t sndo_pcm_pio_iend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames)
-{
- if (frames <= 0)
- return -EINVAL;
- if (frames % pcm->transfer_block)
- return -EINVAL;
- return snd_pcm_mmap_commit(pcm->playback, pcm->p_offset, frames);
-}
-
-/**
- * \brief Begin the playback noninterleaved frame update
- * \param pcm ordinary PCM handle
- * \param ring_buffer returned pointer to actual destination area
- * \param frames returned maximum count of updated frames
- * \return 0 on success otherwise a negative error code
- */
-int sndo_pcm_pio_nbegin(sndo_pcm_t *pcm, void ***ring_buffer, snd_pcm_uframes_t *frames)
-{
- int err;
- unsigned ch;
- const snd_pcm_channel_area_t *areas;
-
- err = sndo_pcm_check_setup(pcm);
- if (err < 0)
- return err;
- err = snd_pcm_mmap_begin(pcm->playback, &areas, &pcm->p_offset, frames);
- if (err < 0)
- return err;
- if (*frames < pcm->transfer_block) {
- frames = 0;
- } else {
- *frames -= *frames % pcm->transfer_block;
- for (ch = 0; ch < pcm->channels; ch++)
- ring_buffer[ch] = areas->addr + (areas->first / 8) + pcm->p_offset * pcm->samplebytes;
- }
- return 0;
-}
-
-/**
- * \brief Finish the playback noninterleave frame update (commit data to hardware)
- * \param pcm ordinary PCM handle
- * \param frames count of updated frames
- * \return count of transferred frames on success otherwise a negative error code
- */
-snd_pcm_sframes_t sndo_pcm_pio_nend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames)
-{
- if (frames <= 0)
- return -EINVAL;
- if (frames % pcm->transfer_block)
- return -EINVAL;
- return snd_pcm_mmap_commit(pcm->playback, pcm->p_offset, frames);
-}
-
-/**
- * \brief Begin the capture interleaved frame update
- * \param pcm ordinary PCM handle
- * \param ring_buffer returned pointer to actual destination area
- * \param frames returned maximum count of updated frames
- * \return 0 on success otherwise a negative error code
- */
-int sndo_pcm_cio_ibegin(sndo_pcm_t *pcm, void **ring_buffer, snd_pcm_uframes_t *frames)
-{
- int err;
- const snd_pcm_channel_area_t *areas;
-
- err = sndo_pcm_check_setup(pcm);
- if (err < 0)
- return err;
- err = snd_pcm_mmap_begin(pcm->capture, &areas, &pcm->c_offset, frames);
- if (err < 0)
- return err;
- if (*frames < pcm->transfer_block) {
- frames = 0;
- } else {
- *frames -= *frames % pcm->transfer_block;
- *ring_buffer = (char *)areas->addr + (areas->first / 8) + pcm->c_offset * pcm->samplebytes;
- }
- return 0;
-}
-
-/**
- * \brief Finish the capture interleave frame update (commit data to hardware)
- * \param pcm ordinary PCM handle
- * \param frames count of updated frames
- * \return count of transferred frames on success otherwise a negative error code
- */
-snd_pcm_sframes_t sndo_pcm_cio_iend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames)
-{
- if (frames <= 0)
- return -EINVAL;
- if (frames % pcm->transfer_block)
- return -EINVAL;
- return snd_pcm_mmap_commit(pcm->capture, pcm->p_offset, frames);
-}
-
-/**
- * \brief Begin the capture noninterleaved frame update
- * \param pcm ordinary PCM handle
- * \param ring_buffer returned pointer to actual destination area
- * \param frames returned maximum count of updated frames
- * \return 0 on success otherwise a negative error code
- */
-int sndo_pcm_cio_nbegin(sndo_pcm_t *pcm, void ***ring_buffer, snd_pcm_uframes_t *frames)
-{
- int err;
- unsigned ch;
- const snd_pcm_channel_area_t *areas;
-
- err = sndo_pcm_check_setup(pcm);
- if (err < 0)
- return err;
- err = snd_pcm_mmap_begin(pcm->capture, &areas, &pcm->c_offset, frames);
- if (err < 0)
- return err;
- if (*frames < pcm->transfer_block) {
- frames = 0;
- } else {
- *frames -= *frames % pcm->transfer_block;
- for (ch = 0; ch < pcm->channels; ch++)
- ring_buffer[ch] = areas->addr + (areas->first / 8) + pcm->c_offset * pcm->samplebytes;
- }
- return 0;
-}
-
-/**
- * \brief Finish the capture noninterleave frame update (commit data to hardware)
- * \param pcm ordinary PCM handle
- * \param frames count of updated frames
- * \return count of transferred frames on success otherwise a negative error code
- */
-snd_pcm_sframes_t sndo_pcm_cio_nend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames)
-{
- if (frames <= 0)
- return -EINVAL;
- if (frames % pcm->transfer_block)
- return -EINVAL;
- return snd_pcm_mmap_commit(pcm->capture, pcm->c_offset, frames);
-}
-
-/*
- * helpers
- */
-
-static int sndo_pcm_setup(sndo_pcm_t *pcm)
-{
- int err;
-
- err = sndo_pcm_drain(pcm);
- if (err < 0)
- return err;
- if (!pcm->setting_up) {
- int err = sndo_pcm_param_reset(pcm);
- if (err < 0)
- return err;
- pcm->setting_up = 1;
- }
- return 0;
-}
-
-static int sndo_pcm_initialize(sndo_pcm_t *pcm)
-{
- int err;
- snd_pcm_uframes_t boundary;
- snd_pcm_uframes_t p_period_size = ~0UL, c_period_size = ~0UL;
- snd_pcm_uframes_t p_buffer_size = ~0UL, c_buffer_size = ~0UL;
-
- if (pcm->playback) {
- err = snd_pcm_hw_params(pcm->playback, pcm->p_hw_params);
- if (err < 0)
- return err;
- err = snd_pcm_hw_params_get_period_size(pcm->p_hw_params, &p_period_size, NULL);
- if (err < 0)
- return err;
- err = snd_pcm_hw_params_get_buffer_size(pcm->p_hw_params, &p_buffer_size);
- if (err < 0)
- return err;
- }
- if (pcm->capture) {
- err = snd_pcm_hw_params(pcm->capture, pcm->c_hw_params);
- if (err < 0)
- return err;
- err = snd_pcm_hw_params_get_period_size(pcm->c_hw_params, &c_period_size, NULL);
- if (err < 0)
- return err;
- err = snd_pcm_hw_params_get_buffer_size(pcm->c_hw_params, &c_buffer_size);
- if (err < 0)
- return err;
- }
- if (p_period_size < c_period_size)
- pcm->transfer_block = p_period_size;
- else
- pcm->transfer_block = c_period_size;
- if (p_buffer_size < c_buffer_size)
- pcm->ring_size = p_buffer_size;
- else
- pcm->ring_size = c_buffer_size;
- if (pcm->playback) {
- err = snd_pcm_sw_params_get_boundary(pcm->p_sw_params, &boundary);
- if (err < 0)
- return err;
- err = snd_pcm_sw_params_set_start_threshold(pcm->playback, pcm->p_sw_params, boundary);
- if (err < 0)
- return err;
- err = snd_pcm_sw_params_set_stop_threshold(pcm->playback, pcm->p_sw_params, pcm->xrun == SNDO_PCM_XRUN_IGNORE ? boundary : pcm->ring_size);
- if (err < 0)
- return err;
- err = snd_pcm_sw_params_set_xfer_align(pcm->playback, pcm->p_sw_params, 1);
- if (err < 0)
- return err;
- err = snd_pcm_sw_params_set_avail_min(pcm->playback, pcm->p_sw_params, pcm->transfer_block);
- if (err < 0)
- return err;
- err = snd_pcm_sw_params(pcm->playback, pcm->p_sw_params);
- if (err < 0)
- return err;
- }
- if (pcm->capture) {
- err = snd_pcm_sw_params_get_boundary(pcm->c_sw_params, &boundary);
- if (err < 0)
- return err;
- err = snd_pcm_sw_params_set_start_threshold(pcm->capture, pcm->c_sw_params, boundary);
- if (err < 0)
- return err;
- err = snd_pcm_sw_params_set_stop_threshold(pcm->capture, pcm->c_sw_params, pcm->xrun == SNDO_PCM_XRUN_IGNORE ? boundary : pcm->ring_size);
- if (err < 0)
- return err;
- err = snd_pcm_sw_params_set_xfer_align(pcm->capture, pcm->c_sw_params, 1);
- if (err < 0)
- return err;
- err = snd_pcm_sw_params_set_avail_min(pcm->capture, pcm->c_sw_params, pcm->transfer_block);
- if (err < 0)
- return err;
- err = snd_pcm_sw_params(pcm->capture, pcm->c_sw_params);
- if (err < 0)
- return err;
- }
- pcm->initialized = 1;
- return 0;
-}