implemented snd_pcm_rewindable() and snd_pcm_forwardable(), removed can_rewind and...
authorJaroslav Kysela <perex@perex.cz>
Mon, 21 Apr 2008 10:46:50 +0000 (12:46 +0200)
committerJaroslav Kysela <perex@perex.cz>
Mon, 21 Apr 2008 10:46:50 +0000 (12:46 +0200)
17 files changed:
include/pcm.h
src/pcm/pcm.c
src/pcm/pcm_dmix.c
src/pcm/pcm_dshare.c
src/pcm/pcm_dsnoop.c
src/pcm/pcm_file.c
src/pcm/pcm_generic.c
src/pcm/pcm_generic.h
src/pcm/pcm_hooks.c
src/pcm/pcm_hw.c
src/pcm/pcm_ioplug.c
src/pcm/pcm_local.h
src/pcm/pcm_meter.c
src/pcm/pcm_mmap_emul.c
src/pcm/pcm_plugin.c
src/pcm/pcm_share.c
src/pcm/pcm_shm.c

index 9a592e3..4eb5035 100644 (file)
@@ -441,7 +441,9 @@ int snd_pcm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
 int snd_pcm_resume(snd_pcm_t *pcm);
 int snd_pcm_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail, snd_htimestamp_t *tstamp);
 snd_pcm_sframes_t snd_pcm_avail_update(snd_pcm_t *pcm);
+snd_pcm_sframes_t snd_pcm_rewindable(snd_pcm_t *pcm);
 snd_pcm_sframes_t snd_pcm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
+snd_pcm_sframes_t snd_pcm_forwardable(snd_pcm_t *pcm);
 snd_pcm_sframes_t snd_pcm_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
 snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);
 snd_pcm_sframes_t snd_pcm_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size);
index e0f808c..88d1515 100644 (file)
@@ -1112,6 +1112,25 @@ int snd_pcm_pause(snd_pcm_t *pcm, int enable)
 }
 
 /**
+ * \brief Get safe count of frames which can be rewinded
+ * \param pcm PCM handle
+ * \return a positive number of frames or negative error code
+ *
+ * Note: The snd_pcm_rewind() can accept bigger value than returned
+ * by this function. But it is not guaranteed that output stream
+ * will be consistent with bigger value.
+ */
+snd_pcm_sframes_t snd_pcm_rewindable(snd_pcm_t *pcm)
+{
+       assert(pcm);
+       if (CHECK_SANITY(! pcm->setup)) {
+               SNDMSG("PCM not set up");
+               return -EIO;
+       }
+       return pcm->fast_ops->rewindable(pcm->fast_op_arg);
+}
+
+/**
  * \brief Move application frame position backward
  * \param pcm PCM handle
  * \param frames wanted displacement in frames
@@ -1131,6 +1150,25 @@ snd_pcm_sframes_t snd_pcm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 }
 
 /**
+ * \brief Get safe count of frames which can be forwarded
+ * \param pcm PCM handle
+ * \return a positive number of frames or negative error code
+ *
+ * Note: The snd_pcm_forward() can accept bigger value than returned
+ * by this function. But it is not guaranteed that output stream
+ * will be consistent with bigger value.
+ */
+snd_pcm_sframes_t snd_pcm_forwardable(snd_pcm_t *pcm)
+{
+       assert(pcm);
+       if (CHECK_SANITY(! pcm->setup)) {
+               SNDMSG("PCM not set up");
+               return -EIO;
+       }
+       return pcm->fast_ops->forwardable(pcm->fast_op_arg);
+}
+
+/**
  * \brief Move application frame position forward
  * \param pcm PCM handle
  * \param frames wanted skip in frames
@@ -2854,48 +2892,6 @@ int snd_pcm_hw_params_can_overrange(const snd_pcm_hw_params_t *params)
 }
 
 /**
- * \brief Check, if device supports forward
- * \param params Configuration space
- * \return Boolean value
- * \retval 0 Device doesn't support forward
- * \retval 1 Device supports forward
- *
- * It is not allowed to call this function when given configuration is not exactly one.
- * Usually, #snd_pcm_hw_params() function chooses one configuration
- * from the configuration space.
- */
-int snd_pcm_hw_params_can_forward(const snd_pcm_hw_params_t *params)
-{
-       assert(params);
-       if (CHECK_SANITY(params->info == ~0U)) {
-               SNDMSG("invalid PCM info field");
-               return 0; /* FIXME: should be a negative error? */
-       }
-       return !!(params->info & SND_PCM_INFO_FORWARD);
-}
-
-/**
- * \brief Check, if device supports rewind
- * \param params Configuration space
- * \return Boolean value
- * \retval 0 Device doesn't support rewind
- * \retval 1 Device supports rewind
- *
- * It is not allowed to call this function when given configuration is not exactly one.
- * Usually, #snd_pcm_hw_params() function chooses one configuration
- * from the configuration space.
- */
-int snd_pcm_hw_params_can_rewind(const snd_pcm_hw_params_t *params)
-{
-       assert(params);
-       if (CHECK_SANITY(params->info == ~0U)) {
-               SNDMSG("invalid PCM info field");
-               return 0; /* FIXME: should be a negative error? */
-       }
-       return !!(params->info & SND_PCM_INFO_REWIND);
-}
-
-/**
  * \brief Check, if hardware supports pause
  * \param params Configuration space
  * \return Boolean value
index 9a6887d..bb79ec6 100644 (file)
@@ -649,6 +649,11 @@ static int snd_pcm_dmix_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTRIB
        return -EIO;
 }
 
+static snd_pcm_sframes_t snd_pcm_dmix_rewindable(snd_pcm_t *pcm)
+{
+       return snd_pcm_mmap_hw_avail(pcm);
+}
+
 static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
        snd_pcm_direct_t *dmix = pcm->private_data;
@@ -723,6 +728,11 @@ static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
        return result + frames;
 }
 
+static snd_pcm_sframes_t snd_pcm_dmix_forwardable(snd_pcm_t *pcm)
+{
+       return snd_pcm_mmap_avail(pcm);
+}
+
 static snd_pcm_sframes_t snd_pcm_dmix_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
        snd_pcm_sframes_t avail;
@@ -885,7 +895,9 @@ static snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = {
        .drop = snd_pcm_dmix_drop,
        .drain = snd_pcm_dmix_drain,
        .pause = snd_pcm_dmix_pause,
+       .rewindable = snd_pcm_dmix_rewindable,
        .rewind = snd_pcm_dmix_rewind,
+       .forwardable = snd_pcm_dmix_forwardable,
        .forward = snd_pcm_dmix_forward,
        .resume = snd_pcm_direct_resume,
        .link = NULL,
index 8d40354..bfe66a8 100644 (file)
@@ -410,15 +410,27 @@ static int snd_pcm_dshare_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTR
        return -EIO;
 }
 
-static snd_pcm_sframes_t snd_pcm_dshare_rewind(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_uframes_t frames ATTRIBUTE_UNUSED)
+static snd_pcm_sframes_t snd_pcm_dshare_rewindable(snd_pcm_t *pcm)
 {
-#if 0
-       /* FIXME: substract samples from the mix ring buffer, too? */
+       return snd_pcm_mmap_playback_hw_avail(pcm);
+}
+
+static snd_pcm_sframes_t snd_pcm_dshare_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
+{
+       snd_pcm_sframes_t avail;
+
+       avail = snd_pcm_mmap_playback_hw_avail(pcm);
+       if (avail < 0)
+               return 0;
+       if (frames > (snd_pcm_uframes_t)avail)
+               frames = avail;
        snd_pcm_mmap_appl_backward(pcm, frames);
        return frames;
-#else
-       return -EIO;
-#endif
+}
+
+static snd_pcm_sframes_t snd_pcm_dshare_forwardable(snd_pcm_t *pcm)
+{
+       return snd_pcm_mmap_playback_avail(pcm);
 }
 
 static snd_pcm_sframes_t snd_pcm_dshare_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
@@ -574,7 +586,9 @@ static snd_pcm_fast_ops_t snd_pcm_dshare_fast_ops = {
        .drop = snd_pcm_dshare_drop,
        .drain = snd_pcm_dshare_drain,
        .pause = snd_pcm_dshare_pause,
+       .rewindable = snd_pcm_dshare_rewindable,
        .rewind = snd_pcm_dshare_rewind,
+       .forwardable = snd_pcm_dshare_forwardable,
        .forward = snd_pcm_dshare_forward,
        .resume = snd_pcm_direct_resume,
        .link = NULL,
index e9ea81b..1f602c3 100644 (file)
@@ -313,12 +313,29 @@ static int snd_pcm_dsnoop_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTR
        return -EIO;
 }
 
+static snd_pcm_sframes_t snd_pcm_dsnoop_rewindable(snd_pcm_t *pcm)
+{
+       return snd_pcm_mmap_capture_avail(pcm);
+}
+
 static snd_pcm_sframes_t snd_pcm_dsnoop_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
+       snd_pcm_sframes_t avail;
+
+       avail = snd_pcm_mmap_capture_avail(pcm);
+       if (avail < 0)
+               return 0;
+       if (frames > (snd_pcm_uframes_t)avail)
+               frames = avail;
        snd_pcm_mmap_appl_backward(pcm, frames);
        return frames;
 }
 
+static snd_pcm_sframes_t snd_pcm_dsnoop_forwardable(snd_pcm_t *pcm)
+{
+       return snd_pcm_mmap_capture_hw_avail(pcm);
+}
+
 static snd_pcm_sframes_t snd_pcm_dsnoop_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
        snd_pcm_sframes_t avail;
@@ -464,7 +481,9 @@ static snd_pcm_fast_ops_t snd_pcm_dsnoop_fast_ops = {
        .drop = snd_pcm_dsnoop_drop,
        .drain = snd_pcm_dsnoop_drain,
        .pause = snd_pcm_dsnoop_pause,
+       .rewindable = snd_pcm_dsnoop_rewindable,
        .rewind = snd_pcm_dsnoop_rewind,
+       .forwardable = snd_pcm_dsnoop_forwardable,
        .forward = snd_pcm_dsnoop_forward,
        .resume = snd_pcm_direct_resume,
        .link = NULL,
index 289a434..e3216da 100644 (file)
@@ -265,6 +265,16 @@ static int snd_pcm_file_drain(snd_pcm_t *pcm)
        return err;
 }
 
+static snd_pcm_sframes_t snd_pcm_file_rewindable(snd_pcm_t *pcm)
+{
+       snd_pcm_file_t *file = pcm->private_data;
+       snd_pcm_sframes_t res = snd_pcm_rewindable(pcm);
+       snd_pcm_sframes_t n = snd_pcm_bytes_to_frames(pcm, file->wbuf_used_bytes);
+       if (res > n)
+               res = n;
+       return res;
+}
+
 static snd_pcm_sframes_t snd_pcm_file_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
        snd_pcm_file_t *file = pcm->private_data;
@@ -283,6 +293,16 @@ static snd_pcm_sframes_t snd_pcm_file_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
        return err;
 }
 
+static snd_pcm_sframes_t snd_pcm_file_forwardable(snd_pcm_t *pcm)
+{
+       snd_pcm_file_t *file = pcm->private_data;
+       snd_pcm_sframes_t res = snd_pcm_forwardable(pcm);
+       snd_pcm_sframes_t n = snd_pcm_bytes_to_frames(pcm, file->wbuf_size_bytes - file->wbuf_used_bytes);
+       if (res > n)
+               res = n;
+       return res;
+}
+
 static snd_pcm_sframes_t snd_pcm_file_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
        snd_pcm_file_t *file = pcm->private_data;
@@ -466,7 +486,9 @@ static snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
        .drop = snd_pcm_file_drop,
        .drain = snd_pcm_file_drain,
        .pause = snd_pcm_generic_pause,
+       .rewindable = snd_pcm_file_rewindable,
        .rewind = snd_pcm_file_rewind,
+       .forwardable = snd_pcm_file_forwardable,
        .forward = snd_pcm_file_forward,
        .resume = snd_pcm_generic_resume,
        .link = snd_pcm_generic_link,
index 85b8d4f..84ea85f 100644 (file)
@@ -185,12 +185,24 @@ int snd_pcm_generic_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
        return snd_pcm_delay(generic->slave, delayp);
 }
 
+snd_pcm_sframes_t snd_pcm_generic_forwardable(snd_pcm_t *pcm)
+{
+       snd_pcm_generic_t *generic = pcm->private_data;
+       return snd_pcm_forwardable(generic->slave);
+}
+
 snd_pcm_sframes_t snd_pcm_generic_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
        snd_pcm_generic_t *generic = pcm->private_data;
        return INTERNAL(snd_pcm_forward)(generic->slave, frames);
 }
 
+snd_pcm_sframes_t snd_pcm_generic_rewindable(snd_pcm_t *pcm)
+{
+       snd_pcm_generic_t *generic = pcm->private_data;
+       return snd_pcm_rewindable(generic->slave);
+}
+
 snd_pcm_sframes_t snd_pcm_generic_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
        snd_pcm_generic_t *generic = pcm->private_data;
index 9874c1b..430b8cf 100644 (file)
@@ -73,8 +73,12 @@ typedef struct {
        snd1_pcm_generic_resume
 #define snd_pcm_generic_delay \
        snd1_pcm_generic_delay
+#define snd_pcm_generic_forwardable \
+       snd1_pcm_generic_forwardable
 #define snd_pcm_generic_forward \
        snd1_pcm_generic_forward
+#define snd_pcm_generic_rewindable \
+       snd1_pcm_generic_rewindable
 #define snd_pcm_generic_rewind \
        snd1_pcm_generic_rewind
 #define snd_pcm_generic_link \
@@ -124,7 +128,9 @@ int snd_pcm_generic_drain(snd_pcm_t *pcm);
 int snd_pcm_generic_pause(snd_pcm_t *pcm, int enable);
 int snd_pcm_generic_resume(snd_pcm_t *pcm);
 int snd_pcm_generic_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
+snd_pcm_sframes_t snd_pcm_generic_forwardable(snd_pcm_t *pcm);
 snd_pcm_sframes_t snd_pcm_generic_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
+snd_pcm_sframes_t snd_pcm_generic_rewindable(snd_pcm_t *pcm);
 snd_pcm_sframes_t snd_pcm_generic_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
 int snd_pcm_generic_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2);
 int snd_pcm_generic_link_slaves(snd_pcm_t *pcm, snd_pcm_t *master);
index 5f9b662..0abe819 100644 (file)
@@ -147,7 +147,9 @@ static snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = {
        .drop = snd_pcm_generic_drop,
        .drain = snd_pcm_generic_drain,
        .pause = snd_pcm_generic_pause,
+       .rewindable = snd_pcm_generic_rewindable,
        .rewind = snd_pcm_generic_rewind,
+       .forwardable = snd_pcm_generic_forwardable,
        .forward = snd_pcm_generic_forward,
        .resume = snd_pcm_generic_resume,
        .link = snd_pcm_generic_link,
index ebead2f..5acad3d 100644 (file)
@@ -248,9 +248,7 @@ static int snd_pcm_hw_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
 
        if (params->info != ~0UL) {
                params->info &= ~0xf0000000;
-               params->info |= (pcm->monotonic ? SND_PCM_INFO_MONOTONIC : 0) |
-                                SND_PCM_INFO_REWIND |
-                                SND_PCM_INFO_FORWARD;
+               params->info |= (pcm->monotonic ? SND_PCM_INFO_MONOTONIC : 0);
        }
        
        return 0;
@@ -510,6 +508,11 @@ static int snd_pcm_hw_pause(snd_pcm_t *pcm, int enable)
        return 0;
 }
 
+static snd_pcm_sframes_t snd_pcm_hw_rewindable(snd_pcm_t *pcm)
+{
+       return snd_pcm_mmap_hw_avail(pcm);
+}
+
 static snd_pcm_sframes_t snd_pcm_hw_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
        snd_pcm_hw_t *hw = pcm->private_data;
@@ -525,6 +528,11 @@ static snd_pcm_sframes_t snd_pcm_hw_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t fra
        return frames;
 }
 
+static snd_pcm_sframes_t snd_pcm_hw_forwardable(snd_pcm_t *pcm)
+{
+       return snd_pcm_mmap_avail(pcm);
+}
+
 static snd_pcm_sframes_t snd_pcm_hw_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
        snd_pcm_hw_t *hw = pcm->private_data;
@@ -917,7 +925,9 @@ static snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
        .drop = snd_pcm_hw_drop,
        .drain = snd_pcm_hw_drain,
        .pause = snd_pcm_hw_pause,
+       .rewindable = snd_pcm_hw_rewindable,
        .rewind = snd_pcm_hw_rewind,
+       .forwardable = snd_pcm_hw_forwardable,
        .forward = snd_pcm_hw_forward,
        .resume = snd_pcm_hw_resume,
        .link = snd_pcm_hw_link,
index 642a905..a30efeb 100644 (file)
@@ -501,12 +501,22 @@ static int snd_pcm_ioplug_pause(snd_pcm_t *pcm, int enable)
        return 0;
 }
 
+static snd_pcm_sframes_t snd_pcm_ioplug_rewindable(snd_pcm_t *pcm)
+{
+       return snd_pcm_mmap_hw_avail(pcm);
+}
+
 static snd_pcm_sframes_t snd_pcm_ioplug_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
        snd_pcm_mmap_appl_backward(pcm, frames);
        return frames;
 }
 
+static snd_pcm_sframes_t snd_pcm_ioplug_forwardable(snd_pcm_t *pcm)
+{
+       return snd_pcm_mmap_avail(pcm);
+}
+
 static snd_pcm_sframes_t snd_pcm_ioplug_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
        snd_pcm_mmap_appl_forward(pcm, frames);
@@ -767,7 +777,9 @@ static snd_pcm_fast_ops_t snd_pcm_ioplug_fast_ops = {
        .link = NULL,
        .link_slaves = NULL,
        .unlink = NULL,
+       .rewindable = snd_pcm_ioplug_rewindable,
        .rewind = snd_pcm_ioplug_rewind,
+       .forwardable = snd_pcm_ioplug_forwardable,
        .forward = snd_pcm_ioplug_forward,
        .writei = snd_pcm_ioplug_writei,
        .writen = snd_pcm_ioplug_writen,
index f0dae7c..0f1dcad 100644 (file)
@@ -95,8 +95,6 @@ typedef enum sndrv_pcm_hw_param snd_pcm_hw_param_t;
 #define SND_PCM_HW_PARAMS_NORESAMPLE SNDRV_PCM_HW_PARAMS_NORESAMPLE
 #define SND_PCM_HW_PARAMS_EXPORT_BUFFER SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER
 
-#define SND_PCM_INFO_FORWARD   0x10000000
-#define SND_PCM_INFO_REWIND    0x20000000
 #define SND_PCM_INFO_MONOTONIC 0x80000000
 
 typedef struct _snd_pcm_rbptr {
@@ -159,7 +157,9 @@ typedef struct {
        int (*link)(snd_pcm_t *pcm1, snd_pcm_t *pcm2);
        int (*link_slaves)(snd_pcm_t *pcm, snd_pcm_t *master);
        int (*unlink)(snd_pcm_t *pcm);
+       snd_pcm_sframes_t (*rewindable)(snd_pcm_t *pcm);
        snd_pcm_sframes_t (*rewind)(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
+       snd_pcm_sframes_t (*forwardable)(snd_pcm_t *pcm);
        snd_pcm_sframes_t (*forward)(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
        snd_pcm_sframes_t (*writei)(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);
        snd_pcm_sframes_t (*writen)(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
index 079de1e..0dedb42 100644 (file)
@@ -527,7 +527,9 @@ static snd_pcm_fast_ops_t snd_pcm_meter_fast_ops = {
        .drop = snd_pcm_generic_drop,
        .drain = snd_pcm_generic_drain,
        .pause = snd_pcm_generic_pause,
+       .rewindable = snd_pcm_generic_rewindable,
        .rewind = snd_pcm_meter_rewind,
+       .forwardable = snd_pcm_generic_forwardable,
        .forward = snd_pcm_meter_forward,
        .resume = snd_pcm_generic_resume,
        .writei = snd_pcm_mmap_writei,
index a00ddb1..896e632 100644 (file)
@@ -358,7 +358,9 @@ static snd_pcm_fast_ops_t snd_pcm_mmap_emul_fast_ops = {
        .drop = snd_pcm_generic_drop,
        .drain = snd_pcm_generic_drain,
        .pause = snd_pcm_generic_pause,
+       .rewindable = snd_pcm_generic_rewindable,
        .rewind = snd_pcm_mmap_emul_rewind,
+       .forwardable = snd_pcm_generic_forwardable,
        .forward = snd_pcm_mmap_emul_forward,
        .resume = snd_pcm_generic_resume,
        .link = snd_pcm_generic_link,
index d5fc5d7..c73a02b 100644 (file)
@@ -192,6 +192,11 @@ static int snd_pcm_plugin_reset(snd_pcm_t *pcm)
        return 0;
 }
 
+static snd_pcm_sframes_t snd_pcm_plugin_rewindable(snd_pcm_t *pcm)
+{
+       return snd_pcm_mmap_hw_avail(pcm);
+}
+
 static snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
        snd_pcm_plugin_t *plugin = pcm->private_data;
@@ -203,7 +208,6 @@ static snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t
        if (frames == 0)
                return 0;
        
-       /* FIXME: rate plugin */
        if (plugin->slave_frames)
                sframes = plugin->slave_frames(pcm, (snd_pcm_sframes_t) frames);
        else
@@ -221,6 +225,11 @@ static snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t
        return n;
 }
 
+static snd_pcm_sframes_t snd_pcm_plugin_forwardable(snd_pcm_t *pcm)
+{
+       return snd_pcm_mmap_avail(pcm);
+}
+
 static snd_pcm_sframes_t snd_pcm_plugin_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
        snd_pcm_plugin_t *plugin = pcm->private_data;
@@ -232,7 +241,6 @@ static snd_pcm_sframes_t snd_pcm_plugin_forward(snd_pcm_t *pcm, snd_pcm_uframes_
        if (frames == 0)
                return 0;
        
-       /* FIXME: rate plugin */
        if (plugin->slave_frames)
                sframes = plugin->slave_frames(pcm, (snd_pcm_sframes_t) frames);
        else
@@ -563,7 +571,9 @@ snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
        .drop = snd_pcm_generic_drop,
        .drain = snd_pcm_generic_drain,
        .pause = snd_pcm_generic_pause,
+       .rewindable = snd_pcm_plugin_rewindable,
        .rewind = snd_pcm_plugin_rewind,
+       .forwardable = snd_pcm_plugin_forwardable,
        .forward = snd_pcm_plugin_forward,
        .resume = snd_pcm_generic_resume,
        .link = snd_pcm_generic_link,
index a01e759..3294c71 100644 (file)
@@ -1039,6 +1039,17 @@ static snd_pcm_sframes_t _snd_pcm_share_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t
        return n;
 }
 
+static snd_pcm_sframes_t snd_pcm_share_rewindable(snd_pcm_t *pcm)
+{
+       snd_pcm_share_t *share = pcm->private_data;
+       snd_pcm_share_slave_t *slave = share->slave;
+       snd_pcm_sframes_t ret;
+       Pthread_mutex_lock(&slave->mutex);
+       ret = snd_pcm_rewindable(slave->pcm);
+       Pthread_mutex_unlock(&slave->mutex);
+       return ret;
+}
+
 static snd_pcm_sframes_t snd_pcm_share_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
        snd_pcm_share_t *share = pcm->private_data;
@@ -1085,6 +1096,17 @@ static snd_pcm_sframes_t _snd_pcm_share_forward(snd_pcm_t *pcm, snd_pcm_uframes_
        return n;
 }
 
+static snd_pcm_sframes_t snd_pcm_share_forwardable(snd_pcm_t *pcm)
+{
+       snd_pcm_share_t *share = pcm->private_data;
+       snd_pcm_share_slave_t *slave = share->slave;
+       snd_pcm_sframes_t ret;
+       Pthread_mutex_lock(&slave->mutex);
+       ret = snd_pcm_forwardable(slave->pcm);
+       Pthread_mutex_unlock(&slave->mutex);
+       return ret;
+}
+
 static snd_pcm_sframes_t snd_pcm_share_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
        snd_pcm_share_t *share = pcm->private_data;
@@ -1316,7 +1338,9 @@ static snd_pcm_fast_ops_t snd_pcm_share_fast_ops = {
        .writen = snd_pcm_mmap_writen,
        .readi = snd_pcm_mmap_readi,
        .readn = snd_pcm_mmap_readn,
+       .rewindable = snd_pcm_share_rewindable,
        .rewind = snd_pcm_share_rewind,
+       .forwardable = snd_pcm_share_forwardable,
        .forward = snd_pcm_share_forward,
        .resume = snd_pcm_share_resume,
        .avail_update = snd_pcm_share_avail_update,
index 29f9d23..b0c0bb9 100644 (file)
@@ -508,6 +508,11 @@ static int snd_pcm_shm_pause(snd_pcm_t *pcm, int enable)
        return snd_pcm_shm_action(pcm);
 }
 
+static snd_pcm_sframes_t snd_pcm_shm_rewindable(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
+{
+       return 0;       /* FIX ME */
+}
+
 static snd_pcm_sframes_t snd_pcm_shm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
        snd_pcm_shm_t *shm = pcm->private_data;
@@ -517,6 +522,11 @@ static snd_pcm_sframes_t snd_pcm_shm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t fr
        return snd_pcm_shm_action(pcm);
 }
 
+static snd_pcm_sframes_t snd_pcm_shm_forwardable(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
+{
+       return 0;       /* FIX ME */
+}
+
 static snd_pcm_sframes_t snd_pcm_shm_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
        snd_pcm_shm_t *shm = pcm->private_data;
@@ -607,7 +617,9 @@ static snd_pcm_fast_ops_t snd_pcm_shm_fast_ops = {
        .drop = snd_pcm_shm_drop,
        .drain = snd_pcm_shm_drain,
        .pause = snd_pcm_shm_pause,
+       .rewindable = snd_pcm_shm_rewindable,
        .rewind = snd_pcm_shm_rewind,
+       .forwardable = snd_pcm_shm_forwardable,
        .forward = snd_pcm_shm_forward,
        .resume = snd_pcm_shm_resume,
        .writei = snd_pcm_mmap_writei,