OSDN Git Service

Added simple_mixer and simple_pcm subdirs with some 'empty' code
authorJaroslav Kysela <perex@perex.cz>
Sun, 22 Jun 2003 18:09:03 +0000 (18:09 +0000)
committerJaroslav Kysela <perex@perex.cz>
Sun, 22 Jun 2003 18:09:03 +0000 (18:09 +0000)
configure.in
include/Makefile.am
include/asoundlib.h
include/mixer_simple.h
include/pcm_simple.h
src/Makefile.am
src/simple_mixer/Makefile.am [new file with mode: 0644]
src/simple_mixer/simple_mixer.c [new file with mode: 0644]
src/simple_pcm/Makefile.am [new file with mode: 0644]
src/simple_pcm/simple_pcm.c [new file with mode: 0644]

index 1489794..34d72fb 100644 (file)
@@ -161,8 +161,8 @@ esac
 
 AC_OUTPUT(Makefile doc/Makefile doc/pictures/Makefile include/Makefile
          include/sound/Makefile src/Makefile \
-          src/control/Makefile src/mixer/Makefile
-         src/pcm/Makefile src/pcm/ext/Makefile src/pcm/scopes/Makefile \
+          src/control/Makefile src/mixer/Makefile src/simple_mixer/Makefile \
+         src/pcm/Makefile src/pcm/ext/Makefile src/pcm/scopes/Makefile src/simple_pcm/Makefile \
          src/rawmidi/Makefile src/timer/Makefile \
           src/hwdep/Makefile src/seq/Makefile src/instr/Makefile \
           src/compat/Makefile src/conf/Makefile \
index 1683841..df336bc 100644 (file)
@@ -8,7 +8,8 @@ alsainclude_HEADERS = asoundlib.h asoundef.h \
                      conf.h pcm.h pcm_plugin.h rawmidi.h timer.h \
                      hwdep.h control.h mixer.h \
                      seq_event.h seq.h seqmid.h seq_midi_event.h \
-                     conv.h instr.h iatomic.h
+                     conv.h instr.h iatomic.h \
+                     pcm_simple.h mixer_simple.h
 
 noinst_HEADERS = sys.h search.h list.h aserver.h local.h alsa-symbols.h
 
index 9331a69..a96507b 100644 (file)
@@ -4,7 +4,7 @@
  * \author Jaroslav Kysela <perex@suse.cz>
  * \author Abramo Bagnara <abramo@alsa-project.org>
  * \author Takashi Iwai <tiwai@suse.de>
- * \date 1998-2001
+ * \date 1998-2003
  *
  * Application interface library for the ALSA driver
  *
index e2db7f3..732943c 100644 (file)
 #ifndef __ALSA_MIXER_SIMPLE_H
 #define __ALSA_MIXER_SIMPLE_H
 
+#include <alsa/asoundlib.h>
+
 /** Simple Mixer latency type */
 enum snds_mixer_io_type {
 
+       /*
+        *  playback section
+        */
+
        /** master volume - left (0-1000) */
        SNDS_MIO_MASTER_LVOL = 0,
        /** master volume - right (0-1000) */
@@ -66,6 +72,9 @@ enum snds_mixer_io_type {
        /** CD volume - right mute (0 = off, 1 = on) */
        SNDS_MIO_AUX_RMUTE,
 
+       /*
+        *  capture section
+        */
 
        /** capture gain - left (0-1000) */
        SNDS_MIO_CGAIN_LVOL = 0x1000,
@@ -85,6 +94,8 @@ enum snds_mixer_io_type {
        SNDS_MIO_CSOURCE_MIX
 };
 
+typedef struct snds_mixer snds_mixer_t;
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -95,14 +106,13 @@ extern "C" {
  *  \{
  */
 
-int snds_mixer_open(snds_mixer_t **pcm, const char *playback_name, const char *capture_name);
-int snds_mixer_open_lconf(snds_mixer_t **pcm, const char *plaback_name, const char *capture_name, snd_config_t *lconf);
-int snds_mixer_close(snds_mixer_t *pcm);
-int snds_mixer_poll_descriptors_count(snds_mixer_t *pcm);
-int snds_mixer_poll_descriptors(snds_mixer_t *pcm, struct pollfd *pfds, unsigned int space);
-int snds_mixer_poll_descriptors_revents(snds_mixer_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
-int snds_mixer_io_get(snds_mixer_t *pcm, enum snds_mixer_io_type type, int *val);
-int snds_mixer_io_set(snds_mixer_t *pcm, enum snds_mixer_io_type type, int val);
+int snds_mixer_open(snds_mixer_t **pmixer, const char *playback_name, const char *capture_name, snd_config_t *lconf);
+int snds_mixer_close(snds_mixer_t *mixer);
+int snds_mixer_poll_descriptors_count(snds_mixer_t *mixer);
+int snds_mixer_poll_descriptors(snds_mixer_t *mixer, struct pollfd *pfds, unsigned int space);
+int snds_mixer_poll_descriptors_revents(snds_mixer_t *mixer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
+int snds_mixer_io_get(snds_mixer_t *mixer, enum snds_mixer_io_type type, int *val);
+int snds_mixer_io_set(snds_mixer_t *mixer, enum snds_mixer_io_type type, int val);
 int snds_mixer_io_change(snds_mixer_t *mixer, enum snds_mixer_io_type *changed, int changed_array_size);
 
 /** \} */
index 6d432c5..b431cff 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef __ALSA_PCM_SIMPLE_H
 #define __ALSA_PCM_SIMPLE_H
 
-#include <alsa/pcm.h>
+#include <alsa/asoundlib.h>
 
 /** Simple PCM latency type */
 enum snds_pcm_latency_type {
@@ -58,6 +58,8 @@ enum snds_pcm_xrun_type {
        SNDS_PCM_XRUN_STOP
 };
 
+typedef struct snds_pcm snds_pcm_t;
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -77,7 +79,7 @@ int snds_pcm_start(snds_pcm_t *pcm);
 int snds_pcm_drop(snds_pcm_t *pcm);
 int snds_pcm_drain(snds_pcm_t *pcm);
 int snds_pcm_delay(snds_pcm_t *pcm, snd_pcm_sframes_t *delayp);
-int snds_pcm_resume(snd_pcm_t *pcm);
+int snds_pcm_resume(snds_pcm_t *pcm);
 int snds_pcm_wait(snds_pcm_t *pcm, int timeout);
 snd_pcm_t *snds_pcm_raw_playback(snds_pcm_t *pcm);
 snd_pcm_t *snds_pcm_raw_capture(snds_pcm_t *pcm);
index feeec57..afe55bf 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS=control mixer pcm rawmidi timer hwdep seq instr compat conf
+SUBDIRS=control mixer simple_mixer pcm simple_pcm rawmidi timer hwdep seq instr compat conf
 EXTRA_DIST=Versions
 COMPATNUM=@LIBTOOL_VERSION_INFO@
 
@@ -10,7 +10,9 @@ endif
 
 lib_LTLIBRARIES = libasound.la
 libasound_la_SOURCES = conf.c confmisc.c input.c output.c async.c error.c dlmisc.c socket.c shmarea.c
-libasound_la_LIBADD = control/libcontrol.la mixer/libmixer.la pcm/libpcm.la \
+libasound_la_LIBADD = control/libcontrol.la
+                     mixer/libmixer.la simple_mixer/libsimplemixer.la \
+                     pcm/libpcm.la simple_pcm/libsimplepcm.la \
                       rawmidi/librawmidi.la timer/libtimer.la \
                      hwdep/libhwdep.la seq/libseq.la instr/libinstr.la \
                      compat/libcompat.la -lm -ldl -lpthread
@@ -24,9 +26,15 @@ control/libcontrol.la:
 mixer/libmixer.la:
        $(MAKE) -C mixer libmixer.la
 
+simple_mixer/libsimplemixer.la:
+       $(MAKE) -C simple_mixer libsimplemixer.la
+
 pcm/libpcm.la:
        $(MAKE) -C pcm libpcm.la
 
+simple_pcm/libsimplepcm.la:
+       $(MAKE) -C simple_pcm libsimplepcm.la
+
 rawmidi/librawmidi.la:
        $(MAKE) -C rawmidi librawmidi.la
 
diff --git a/src/simple_mixer/Makefile.am b/src/simple_mixer/Makefile.am
new file mode 100644 (file)
index 0000000..e1bfd67
--- /dev/null
@@ -0,0 +1,13 @@
+SUBDIRS =
+DIST_SUBDIRS =
+
+EXTRA_LTLIBRARIES = libsimplemixer.la
+
+libsimplemixer_la_SOURCES = simple_mixer.c
+noinst_HEADERS =
+
+alsadir = $(datadir)/alsa
+
+all: libsimplemixer.la
+
+INCLUDES=-I$(top_srcdir)/include
diff --git a/src/simple_mixer/simple_mixer.c b/src/simple_mixer/simple_mixer.c
new file mode 100644 (file)
index 0000000..10e68a6
--- /dev/null
@@ -0,0 +1,161 @@
+/**
+ * \file simple_mixer/simple_mixer.c
+ * \ingroup Mixer_simple
+ * \brief Simple mixer interface
+ * \author Jaroslav Kysela <perex@suse.cz>
+ * \date 2003
+ *
+ * Simple mixer interface is a high level abtraction for soundcard's
+ * mixing.
+ *
+ * See the \ref Mixer_simple page for more details.
+ */
+/*
+ *  Simple 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_simple Simple mixer interface
+
+<P>Write something here</P>
+
+\section Mixer_simple_overview
+
+Write something here
+
+*/
+/**
+ * \example ../test/simple_mixer.c
+ * \anchor example_simple_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 "mixer_simple.h"
+
+struct snds_mixer {
+       snd_mixer_t *mixer;
+};
+
+/**
+ * \brief Opens a simple mixer instance
+ * \param pmixer Returned simple mixer handle
+ * \param playback_name ASCII identifier of the simple mixer handle (playback controls)
+ * \param capture_name ASCII identifier of the simple mixer handle (capture controls)
+ * \param lconf Local configuration (might be NULL - use global configuration)
+ * \return 0 on success otherwise a negative error code
+ */
+int snds_mixer_open(snds_mixer_t **pmixer,
+                   const char *playback_name,
+                   const char *capture_name,
+                   snd_config_t *lconf)
+{
+       *pmixer = NULL;
+       return -ENODEV;
+}
+
+/**
+ * \brief Closes a simple mixer instance
+ * \param mixer Simple mixer handle to close
+ * \return 0 on success otherwise a negative error code
+ */
+int snds_mixer_close(snds_mixer_t *mixer)
+{
+       return -ENODEV;
+}
+
+/**
+ * \brief get count of poll descriptors for simple mixer handle
+ * \param mixer simple mixer handle
+ * \return count of poll descriptors
+ */
+int snds_mixer_poll_descriptors_count(snds_mixer_t *mixer)
+{
+       return snd_mixer_poll_descriptors_count(mixer->mixer);
+}
+
+/**
+ * \brief get poll descriptors
+ * \param mixer simple mixer handle
+ * \param pfds array of poll descriptors
+ * \param space space in the poll descriptor array
+ * \return count of filled descriptors
+ */     
+int snds_mixer_poll_descriptors(snds_mixer_t *mixer, struct pollfd *pfds, unsigned int space)
+{
+       return snd_mixer_poll_descriptors(mixer->mixer, pfds, space);
+}
+
+/**
+ * \brief get returned events from poll descriptors
+ * \param mixer simple 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 snds_mixer_poll_descriptors_revents(snds_mixer_t *mixer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
+{
+       return snd_mixer_poll_descriptors_revents(mixer->mixer, pfds, nfds, revents);
+}
+
+/**
+ * \brief get simple mixer io control value
+ * \param mixer simple mixer handle
+ * \param type io type
+ * \param val returned value
+ * \return zero if success, otherwise a negative error code
+ */ 
+int snds_mixer_io_get(snds_mixer_t *mixer, enum snds_mixer_io_type type, int *val)
+{
+       return -ENODEV;
+}
+
+/**
+ * \brief set simple mixer io control value
+ * \param mixer simple mixer handle
+ * \param type io type
+ * \param val desired value
+ * \return zero if success, otherwise a negative error code
+ */ 
+int snds_mixer_io_set(snds_mixer_t *mixer, enum snds_mixer_io_type type, int val)
+{
+       return -ENODEV;
+}
+
+/**
+ * \brief get simple mixer io control change notification
+ * \param mixer simple 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 snds_mixer_io_change(snds_mixer_t *mixer, enum snds_mixer_io_type *changed, int changed_array_size)
+{
+       return -ENODEV;
+}
diff --git a/src/simple_pcm/Makefile.am b/src/simple_pcm/Makefile.am
new file mode 100644 (file)
index 0000000..ae19eae
--- /dev/null
@@ -0,0 +1,13 @@
+SUBDIRS =
+DIST_SUBDIRS =
+
+EXTRA_LTLIBRARIES = libsimplepcm.la
+
+libsimplepcm_la_SOURCES = simple_pcm.c
+noinst_HEADERS =
+
+alsadir = $(datadir)/alsa
+
+all: libsimplepcm.la
+
+INCLUDES=-I$(top_srcdir)/include
diff --git a/src/simple_pcm/simple_pcm.c b/src/simple_pcm/simple_pcm.c
new file mode 100644 (file)
index 0000000..e588e51
--- /dev/null
@@ -0,0 +1,384 @@
+/**
+ * \file simple_pcm/simple_pcm.c
+ * \ingroup PCM_simple
+ * \brief Simple PCM interface
+ * \author Jaroslav Kysela <perex@suse.cz>
+ * \date 2003
+ *
+ * Simple PCM interface is a high level abtraction for
+ * digital audio streaming.
+ *
+ * See the \ref PCM_simple page for more details.
+ */
+/*
+ *  Simple 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_simple Simple PCM interface
+
+<P>Write something here</P>
+
+\section PCM_simple_overview
+
+Write something here
+
+*/
+/**
+ * \example ../test/simple_pcm.c
+ * \anchor example_simple_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 "local.h"
+#include "pcm_simple.h"
+
+struct snds_pcm {
+       snd_pcm_t *playback;
+       snd_pcm_t *capture;
+       snd_pcm_t *master;
+};
+
+/**
+ * \brief Opens a simple pcm instance
+ * \param ppcm Returned simple pcm handle
+ * \param playback_name ASCII identifier of the simple pcm handle (playback)
+ * \param capture_name ASCII identifier of the simple pcm handle (capture)
+ * \param lconf Local configuration (might be NULL - use global configuration)
+ * \return 0 on success otherwise a negative error code
+ */
+int snds_pcm_open(snds_pcm_t **ppcm,
+                   const char *playback_name,
+                   const char *capture_name,
+                   snd_config_t *lconf)
+{
+       *ppcm = NULL;
+       return -ENODEV;
+}
+
+/**
+ * \brief Closes a simple pcm instance
+ * \param pcm Simple pcm handle to close
+ * \return 0 on success otherwise a negative error code
+ */
+int snds_pcm_close(snds_pcm_t *pcm)
+{
+       return -ENODEV;
+}
+
+/**
+ * \brief get count of poll descriptors for simple pcm handle
+ * \param pcm simple pcm handle
+ * \return count of poll descriptors
+ */
+int snds_pcm_poll_descriptors_count(snds_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 simple pcm handle
+ * \param pfds array of poll descriptors
+ * \param space space in the poll descriptor array
+ * \return count of filled descriptors
+ */     
+int snds_pcm_poll_descriptors(snds_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 simple 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 snds_pcm_poll_descriptors_revents(snds_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 simple PCM handle
+ * \return 0 on success otherwise a negative error code
+ */
+int snds_pcm_start(snds_pcm_t *pcm)
+{
+       /* the streams are linked, so use only one stream */
+       return snd_pcm_start(pcm->master);
+}
+
+/**
+ * \brief Stop a PCM dropping pending frames
+ * \param pcm simple PCM handle
+ * \return 0 on success otherwise a negative error code
+ */
+int snds_pcm_drop(snds_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 snds_pcm_drain(snds_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 simple 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 snds_pcm_delay(snds_pcm_t *pcm, snd_pcm_sframes_t *delayp)
+{
+       int err = 0;
+       snd_pcm_sframes_t pdelay, cdelay;
+
+       assert(pcm);
+       assert(delayp);
+       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 Resume from suspend, no samples are lost
+ * \param pcm simple 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 snds_pcm_resume(snds_pcm_t *pcm)
+{
+       return snd_pcm_resume(pcm->master);
+}
+
+/**
+ * \brief Wait for a PCM to become ready
+ * \param pcm simple 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 snds_pcm_wait(snds_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 simple PCM handle
+ * \return raw (lowlevel) capture PCM handle or NULL
+ */
+snd_pcm_t *snds_pcm_raw_playback(snds_pcm_t *pcm)
+{
+       return pcm->playback;
+}
+
+/**
+ * \brief Get raw (lowlevel) capture PCM handle
+ * \param pcm simple PCM handle
+ * \return raw (lowlevel) capture PCM handle or NULL
+ */
+snd_pcm_t *snds_pcm_raw_capture(snds_pcm_t *pcm)
+{
+       return pcm->capture;
+}
+
+int snds_pcm_param_rate(snds_pcm_t *pcm, unsigned int rate, unsigned int *used_rate)
+{
+       return -EIO;
+}
+
+int snds_pcm_param_channels(snds_pcm_t *pcm, unsigned int channels, unsigned int *used_channels)
+{
+       return -EIO;
+}
+
+int snds_pcm_param_format(snds_pcm_t *pcm, snd_pcm_format_t format, snd_pcm_subformat_t subformat)
+{
+       return -EIO;
+}
+
+int snds_pcm_param_latency(snds_pcm_t *pcm, enum snds_pcm_latency_type latency)
+{
+       return -EIO;
+}
+
+int snds_pcm_param_access(snds_pcm_t *pcm, enum snds_pcm_access_type access)
+{
+       return -EIO;
+}
+
+int snds_pcm_param_xrun(snds_pcm_t *pcm, enum snds_pcm_xrun_type xrun)
+{
+       return -EIO;
+}
+
+int snds_pcm_pio_ibegin(snds_pcm_t *pcm, void *ring_buffer, snd_pcm_uframes_t *frames)
+{
+       return -EIO;
+}
+
+int snds_pcm_pio_iend(snds_pcm_t *pcm, snd_pcm_uframes_t frames)
+{
+       return -EIO;
+}
+
+int snds_pcm_pio_nbegin(snds_pcm_t *pcm, void **ring_buffer, snd_pcm_uframes_t *frames)
+{
+       return -EIO;
+}
+
+int snds_pcm_pio_nend(snds_pcm_t *pcm, snd_pcm_uframes_t frames)
+{
+       return -EIO;
+}
+
+int snds_pcm_cio_ibegin(snds_pcm_t *pcm, void *ring_buffer, snd_pcm_uframes_t *frames)
+{
+       return -EIO;
+}
+
+int snds_pcm_cio_iend(snds_pcm_t *pcm, snd_pcm_uframes_t frames)
+{
+       return -EIO;
+}
+
+int snds_pcm_cio_nbegin(snds_pcm_t *pcm, void **ring_buffer, snd_pcm_uframes_t *frames)
+{
+       return -EIO;
+}
+
+int snds_pcm_cio_nend(snds_pcm_t *pcm, snd_pcm_uframes_t frames)
+{
+       return -EIO;
+}