]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Implemented snd_pcm_avail() function.
authorJaroslav Kysela <perex@perex.cz>
Fri, 11 Oct 2002 18:39:24 +0000 (18:39 +0000)
committerJaroslav Kysela <perex@perex.cz>
Fri, 11 Oct 2002 18:39:24 +0000 (18:39 +0000)
More documentation updates for snd_pcm_avail_update() and snd_pcm_delay().
Updated behaviour of read/write functions (wait when buffer is full) to
follow kernel.

src/pcm/pcm.c
src/pcm/pcm_file.c
src/pcm/pcm_hooks.c
src/pcm/pcm_hw.c
src/pcm/pcm_local.h
src/pcm/pcm_meter.c
src/pcm/pcm_multi.c
src/pcm/pcm_null.c
src/pcm/pcm_plugin.c
src/pcm/pcm_share.c
src/pcm/pcm_shm.c

index 9ab753f0c4755986f70aa614bea224c3d09c83a4..137d2b16202fcbd369342d6e81bda4d6cc3d3f8b 100644 (file)
@@ -359,9 +359,9 @@ network I/O etc.). If application wants to manage the ahead samples itself,
 the \link ::snd_pcm_rewind() \endlink function allows to forget the last
 samples in the stream.
 
-\section pcm_status Obtaining device status
+\section pcm_status Obtaining stream status
 
-The device status is stored in \link ::snd_pcm_status_t \endlink structure.
+The stream status is stored in \link ::snd_pcm_status_t \endlink structure.
 These parameters can be obtained: the current stream state -
 \link ::snd_pcm_status_get_state \endlink, timestamp of trigger -
 \link ::snd_pcm_status_get_trigger_tstamp \endlink, timestamp of last
@@ -373,21 +373,33 @@ samples - \link ::snd_pcm_status_get_overrange \endlink. The last two
 parameters - avail_max and overrange are reset to zero after the status
 call.
 
-\subsection pcm_status_fast Obtaining device status fast
+\subsection pcm_status_fast Obtaining stream state fast and update r/w pointer
 
 The function \link ::snd_pcm_avail_update \endlink updates the current
 available count of samples for writing (playback) or filled samples for
-reading (capture). It is a light version of
-\link ::snd_pcm_status_get_avail \endlink, because it does not require
-the user <-> kernel context switch, but the value is less accurate,
-because ring buffer pointers are updated in kernel drivers only when
-an interrupt occurs.
+reading (capture). This call is mandatory for updating actual r/w pointer.
+Using standalone, it is a light method to obtain current stream position,
+because it does not require the user <-> kernel context switch, but the value
+is less accurate, because ring buffer pointers are updated in kernel drivers
+only when an interrupt occurs. If you want to get accurate stream state,
+use functions \link ::snd_pcm_avail \endlink or \link ::snd_pcm_delay \endlink.
+Note that both of these functions do not update the current r/w pointer
+for applications, so the function \link ::snd_pcm_avail_update \endlink must
+be called afterwards before any read/write begin+commit operations.
+<p>
+The function \link ::snd_pcm_avail \endlink returns current available space
+in the ring buffer. Note that this function does not update the current r/w
+pointer for applications, so the function \link ::snd_pcm_avail_update \endlink
+must be called afterwards before any read/write/begin+commit operations.
 <p>
 The function \link ::snd_pcm_delay \endlink returns the delay in samples.
 For playback, it means count of samples in the ring buffer before
 the next sample will be sent to DAC. For capture, it means count of samples
 in the ring buffer before the next sample will be captured from ADC. It works
-only when the stream is in the running or draining state.
+only when the stream is in the running or draining (playback only) state.
+Note that this function does not update the current r/w pointer for applications,
+so the function \link ::snd_pcm_avail_update \endlink must be called afterwards
+before any read/write begin+commit operations.
 
 \section pcm_action Managing the stream state
 
@@ -811,6 +823,30 @@ snd_pcm_state_t snd_pcm_state(snd_pcm_t *pcm)
        return pcm->fast_ops->state(pcm->fast_op_arg);
 }
 
+/**
+ * \brief Obtain available frames for a running PCM handle
+ * \param pcm PCM handle
+ * \param availp Returned available frames
+ * \return 0 on success otherwise a negative error code
+ *
+ * Returns available frames to be filled inside ring buffer.
+ * This value might be greater than buffer size when
+ * underrun (playback) or overrun (capture) occurs.
+ *
+ * This function returns accurate value, because it updates
+ * stream position from hardware.
+ *
+ * Note this function does not update the actual r/w pointer
+ * for applications. The function \link ::snd_pcm_avail_update \endlink
+ * have to be called before any read/write/begin+commit operation.
+ */
+int snd_pcm_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
+{
+       assert(pcm);
+       assert(pcm->setup);
+       return pcm->fast_ops->avail(pcm->fast_op_arg, availp);
+}
+
 /**
  * \brief Obtain delay for a running PCM handle
  * \param pcm PCM handle
@@ -822,6 +858,10 @@ snd_pcm_state_t snd_pcm_state(snd_pcm_t *pcm)
  * It's positive and less than buffer size in normal situation,
  * negative on playback underrun and greater than buffer size on
  * capture overrun.
+ *
+ * Note this function does not update the actual r/w pointer
+ * for applications. The function \link ::snd_pcm_avail_update \endlink
+ * have to be called before any read/write/begin+commit operation.
  */
 int snd_pcm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 {
@@ -5728,6 +5768,8 @@ snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_
                break;
        case SND_PCM_STATE_XRUN:
                return -EPIPE;
+       case SND_PCM_STATE_SUSPENDED:
+               return -ESTRPIPE;
        default:
                return -EBADFD;
        }
@@ -5736,19 +5778,21 @@ snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_
                snd_pcm_uframes_t frames;
                snd_pcm_sframes_t avail;
        _again:
+               if (pcm->sleep_min == 0 && state == SND_PCM_STATE_RUNNING) {
+                       snd_pcm_sframes_t delay;
+                       /* update hw_ptr */
+                       err = snd_pcm_delay(pcm, &delay);
+                       if (err < 0)
+                               goto _end;
+               }
                avail = snd_pcm_avail_update(pcm);
                if (avail < 0) {
                        err = avail;
                        goto _end;
                }
-               if ((state == SND_PCM_STATE_PAUSED) ||
-                   (state == SND_PCM_STATE_DRAINING)) {
-                       if ((snd_pcm_uframes_t)avail < pcm->xfer_align) {
-                               err = -EPIPE;
-                               goto _end;
-                       }
-               } else if (((snd_pcm_uframes_t)avail < pcm->avail_min && size > (snd_pcm_uframes_t)avail) ||
-                          (size >= pcm->xfer_align && (snd_pcm_uframes_t)avail < pcm->xfer_align)) {
+               if (((snd_pcm_uframes_t)avail < pcm->avail_min && size > (snd_pcm_uframes_t)avail) ||
+                   (size >= pcm->xfer_align && (snd_pcm_uframes_t)avail < pcm->xfer_align)) {
+
                        if (pcm->mode & SND_PCM_NONBLOCK) {
                                err = -EAGAIN;
                                goto _end;
@@ -5774,13 +5818,6 @@ snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_
                offset += frames;
                size -= frames;
                xfer += frames;
-#if 0
-               state = snd_pcm_state(pcm);
-               if (state == SND_PCM_STATE_XRUN) {
-                       err = -EPIPE;
-                       goto _end;
-               }
-#endif
        }
  _end:
        return xfer > 0 ? (snd_pcm_sframes_t) xfer : err;
@@ -5805,6 +5842,8 @@ snd_pcm_sframes_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area
                break;
        case SND_PCM_STATE_XRUN:
                return -EPIPE;
+       case SND_PCM_STATE_SUSPENDED:
+               return -ESTRPIPE;
        default:
                return -EBADFD;
        }
@@ -5824,15 +5863,9 @@ snd_pcm_sframes_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area
                if (avail < 0) {
                        err = avail;
                        goto _end;
-               }
-               if (state == SND_PCM_STATE_PAUSED ||
-                   state == SND_PCM_STATE_PREPARED) {
-                       if ((snd_pcm_uframes_t)avail < pcm->xfer_align) {
-                               err = -EPIPE;
-                               goto _end;
-                       }
                } else if (((snd_pcm_uframes_t)avail < pcm->avail_min && size > (snd_pcm_uframes_t)avail) ||
                           (size >= pcm->xfer_align && (snd_pcm_uframes_t)avail < pcm->xfer_align)) {
+
                        if (pcm->mode & SND_PCM_NONBLOCK) {
                                err = -EAGAIN;
                                goto _end;
@@ -5858,13 +5891,6 @@ snd_pcm_sframes_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area
                offset += frames;
                size -= frames;
                xfer += frames;
-#if 0
-               state = snd_pcm_state(pcm);
-               if (state == SND_PCM_STATE_XRUN) {
-                       err = -EPIPE;
-                       goto _end;
-               }
-#endif
                if (state == SND_PCM_STATE_PREPARED) {
                        snd_pcm_sframes_t hw_avail = pcm->buffer_size - avail;
                        hw_avail += frames;
index 30536ba3d8994cf42e6d5af900da93e4e38cadd2..d8ed59d8e99974cfef25d0b6ab6f73bd1d961693 100644 (file)
@@ -162,6 +162,12 @@ static snd_pcm_state_t snd_pcm_file_state(snd_pcm_t *pcm)
        return snd_pcm_state(file->slave);
 }
 
+static int snd_pcm_file_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
+{
+       snd_pcm_file_t *file = pcm->private_data;
+       return snd_pcm_avail(file->slave, availp);
+}
+
 static int snd_pcm_file_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 {
        snd_pcm_file_t *file = pcm->private_data;
@@ -406,6 +412,7 @@ static snd_pcm_ops_t snd_pcm_file_ops = {
 static snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
        status: snd_pcm_file_status,
        state: snd_pcm_file_state,
+       avail: snd_pcm_file_avail,
        delay: snd_pcm_file_delay,
        prepare: snd_pcm_file_prepare,
        reset: snd_pcm_file_reset,
index 946835deaf766726cf5c28306ae33763b753ca3c..0cd74de01f3328ca013e9be79255dc07e71da5dd 100644 (file)
@@ -116,6 +116,12 @@ static snd_pcm_state_t snd_pcm_hooks_state(snd_pcm_t *pcm)
        return snd_pcm_state(h->slave);
 }
 
+static int snd_pcm_hooks_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
+{
+       snd_pcm_hooks_t *h = pcm->private_data;
+       return snd_pcm_avail(h->slave, availp);
+}
+
 static int snd_pcm_hooks_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 {
        snd_pcm_hooks_t *h = pcm->private_data;
@@ -292,6 +298,7 @@ static snd_pcm_ops_t snd_pcm_hooks_ops = {
 static snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = {
        status: snd_pcm_hooks_status,
        state: snd_pcm_hooks_state,
+       avail: snd_pcm_hooks_avail,
        delay: snd_pcm_hooks_delay,
        prepare: snd_pcm_hooks_prepare,
        reset: snd_pcm_hooks_reset,
index 4f59aeb4db0450201fd008c40b2e6f9fb7bafa91..b2c872b6eb5240f996c0f7119d003e6e58db2ad9 100644 (file)
@@ -77,9 +77,11 @@ struct sndrv_pcm_hw_params_old {
 #define SND_PCM_IOCTL_HW_REFINE_OLD _IOWR('A', 0x10, struct sndrv_pcm_hw_params_old)
 #define SND_PCM_IOCTL_HW_PARAMS_OLD _IOWR('A', 0x11, struct sndrv_pcm_hw_params_old)
 
-#define SND_PCM_IOCTL_XRUN _IO('A', 0x48)
+#define SND_PCM_IOCTL_AVAIL _IOR('A', 0x22, sndrv_pcm_uframes_t)
+#define SND_PCM_IOCTL_XRUN  _IO ('A', 0x48)
 
 static int use_old_hw_params_ioctl(int fd, unsigned int cmd, snd_pcm_hw_params_t *params);
+static snd_pcm_sframes_t snd_pcm_hw_avail_update(snd_pcm_t *pcm);
 
 /*
  *
@@ -101,7 +103,7 @@ typedef struct {
 
 #define SNDRV_FILE_PCM_STREAM_PLAYBACK         "/dev/snd/pcmC%iD%ip"
 #define SNDRV_FILE_PCM_STREAM_CAPTURE          "/dev/snd/pcmC%iD%ic"
-#define SNDRV_PCM_VERSION_MAX                  SNDRV_PROTOCOL_VERSION(2, 0, 2)
+#define SNDRV_PCM_VERSION_MAX                  SNDRV_PROTOCOL_VERSION(2, 0, 3)
 
 /* update appl_ptr with driver */
 #define UPDATE_SHADOW_PTR(hw) \
@@ -393,6 +395,33 @@ static int snd_pcm_hw_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
        return 0;
 }
 
+static int snd_pcm_hw_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
+{
+       snd_pcm_hw_t *hw = pcm->private_data;
+       int fd = hw->fd;
+       if (SNDRV_PROTOCOL_VERSION(2, 0, 3) <= hw->version) {
+               if (ioctl(fd, SND_PCM_IOCTL_AVAIL, availp) < 0) {
+                       // SYSERR("SND_PCM_IOCTL_AVAIL failed");
+                       return -errno;
+               }
+       } else {
+               snd_pcm_sframes_t delay;
+               int err = snd_pcm_hw_delay(pcm, &delay);
+               if (err < 0) {
+                       delay = snd_pcm_hw_avail_update(pcm);
+                       if (delay < 0)
+                               return delay;
+                       *availp = delay;
+               } else {
+                       delay = pcm->stream == SND_PCM_STREAM_PLAYBACK ? pcm->buffer_size - delay : delay;
+                       if (delay < 0)
+                               delay = 0;
+                       *availp = delay;
+               }
+       }
+       return 0;
+}
+
 static int snd_pcm_hw_prepare(snd_pcm_t *pcm)
 {
        snd_pcm_hw_t *hw = pcm->private_data;
@@ -757,6 +786,7 @@ static snd_pcm_ops_t snd_pcm_hw_ops = {
 static snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
        status: snd_pcm_hw_status,
        state: snd_pcm_hw_state,
+       avail: snd_pcm_hw_avail,
        delay: snd_pcm_hw_delay,
        prepare: snd_pcm_hw_prepare,
        reset: snd_pcm_hw_reset,
index 2d8ab61f093526acb9be61a10f532f1b766118c5..b8a91ae74583585b5c174f8e1e839bcb11e80bac 100644 (file)
@@ -144,6 +144,7 @@ typedef struct {
        int (*drain)(snd_pcm_t *pcm);
        int (*pause)(snd_pcm_t *pcm, int enable);
        snd_pcm_state_t (*state)(snd_pcm_t *pcm);
+       int (*avail)(snd_pcm_t *pcm, snd_pcm_uframes_t *availp);
        int (*delay)(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
        int (*resume)(snd_pcm_t *pcm);
        snd_pcm_sframes_t (*rewind)(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
@@ -323,31 +324,12 @@ static inline snd_pcm_uframes_t snd_pcm_mmap_hw_offset(snd_pcm_t *pcm)
 
 static inline snd_pcm_uframes_t snd_pcm_mmap_playback_delay(snd_pcm_t *pcm)
 {
-       snd_pcm_state_t state = snd_pcm_state(pcm);
-       
-       switch (state) {
-       case SND_PCM_STATE_RUNNING:
-       case SND_PCM_STATE_DRAINING:
-               return snd_pcm_mmap_playback_hw_avail(pcm);
-       case SND_PCM_STATE_XRUN:
-               return -EPIPE;
-       default:
-               return -EBADFD;
-       }
+       return snd_pcm_mmap_playback_hw_avail(pcm);
 }
 
 static inline snd_pcm_uframes_t snd_pcm_mmap_capture_delay(snd_pcm_t *pcm)
 {
-       snd_pcm_state_t state = snd_pcm_state(pcm);
-       
-       switch (state) {
-       case SND_PCM_STATE_RUNNING:
-               return snd_pcm_mmap_capture_hw_avail(pcm);
-       case SND_PCM_STATE_XRUN:
-               return -EPIPE;
-       default:
-               return -EBADFD;
-       }
+       return snd_pcm_mmap_capture_hw_avail(pcm);
 }
 
 static inline snd_pcm_sframes_t snd_pcm_mmap_delay(snd_pcm_t *pcm)
index c3e414302c07a9831eff57dc1e87547f4f5c1d13..820f733f031a0d596dc7ec892dfcde3c1ef352fe 100644 (file)
@@ -319,6 +319,12 @@ static snd_pcm_state_t snd_pcm_meter_state(snd_pcm_t *pcm)
        return snd_pcm_state(meter->slave);
 }
 
+static int snd_pcm_meter_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
+{
+       snd_pcm_meter_t *meter = pcm->private_data;
+       return snd_pcm_avail(meter->slave, availp);
+}
+
 static int snd_pcm_meter_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 {
        snd_pcm_meter_t *meter = pcm->private_data;
@@ -593,6 +599,7 @@ static snd_pcm_ops_t snd_pcm_meter_ops = {
 static snd_pcm_fast_ops_t snd_pcm_meter_fast_ops = {
        status: snd_pcm_meter_status,
        state: snd_pcm_meter_state,
+       avail: snd_pcm_meter_avail,
        delay: snd_pcm_meter_delay,
        prepare: snd_pcm_meter_prepare,
        reset: snd_pcm_meter_reset,
index 7f5caac6108a771800d843976a9ed46e77e7fd93..57aca7d15c7819907a80e9f8f7eb0f223968168e 100644 (file)
@@ -351,6 +351,13 @@ static snd_pcm_state_t snd_pcm_multi_state(snd_pcm_t *pcm)
        return snd_pcm_state(slave);
 }
 
+static int snd_pcm_multi_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
+{
+       snd_pcm_multi_t *multi = pcm->private_data;
+       snd_pcm_t *slave = multi->slaves[0].pcm;
+       return snd_pcm_avail(slave, availp);
+}
+
 static int snd_pcm_multi_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 {
        snd_pcm_multi_t *multi = pcm->private_data;
@@ -594,6 +601,7 @@ static snd_pcm_ops_t snd_pcm_multi_ops = {
 static snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = {
        status: snd_pcm_multi_status,
        state: snd_pcm_multi_state,
+       avail: snd_pcm_multi_avail,
        delay: snd_pcm_multi_delay,
        prepare: snd_pcm_multi_prepare,
        reset: snd_pcm_multi_reset,
index 338b58ae5d3c35a26e2ec88a1428d1ab822e38cf..3edd58dfc45c2248dacea0e7af05588a9fbf777d 100644 (file)
@@ -102,6 +102,12 @@ static snd_pcm_state_t snd_pcm_null_state(snd_pcm_t *pcm)
        return null->state;
 }
 
+static int snd_pcm_null_avail(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_uframes_t *availp)
+{
+       *availp = pcm->buffer_size;
+       return 0;
+}
+
 static int snd_pcm_null_delay(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sframes_t *delayp)
 {
        *delayp = 0;
@@ -320,6 +326,7 @@ static snd_pcm_ops_t snd_pcm_null_ops = {
 static snd_pcm_fast_ops_t snd_pcm_null_fast_ops = {
        status: snd_pcm_null_status,
        state: snd_pcm_null_state,
+       avail: snd_pcm_null_avail,
        delay: snd_pcm_null_delay,
        prepare: snd_pcm_null_prepare,
        reset: snd_pcm_null_reset,
index 9cf4f0480d8f650a3a0d6cf9bb8f9248d537ef6a..656e41e99100c0aebdb9fa0fa74ac8f179bfcc35 100644 (file)
@@ -188,6 +188,19 @@ snd_pcm_state_t snd_pcm_plugin_state(snd_pcm_t *pcm)
        return snd_pcm_state(plugin->slave);
 }
 
+int snd_pcm_plugin_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
+{
+       snd_pcm_plugin_t *plugin = pcm->private_data;
+       snd_pcm_uframes_t sd;
+       int err = snd_pcm_avail(plugin->slave, &sd);
+       if (err < 0)
+               return err;
+       if (plugin->client_frames)
+               sd = plugin->client_frames(pcm, sd);
+       *availp = sd;
+       return 0;
+}
+
 int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 {
        snd_pcm_plugin_t *plugin = pcm->private_data;
@@ -197,7 +210,7 @@ int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
                return err;
        if (plugin->client_frames)
                sd = plugin->client_frames(pcm, sd);
-       *delayp = sd + snd_pcm_mmap_delay(pcm);
+       *delayp = sd;
        return 0;
 }
 
@@ -627,6 +640,7 @@ int snd_pcm_plugin_hw_params_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
 snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
        status: snd_pcm_plugin_status,
        state: snd_pcm_plugin_state,
+       avail: snd_pcm_plugin_avail,
        delay: snd_pcm_plugin_delay,
        prepare: snd_pcm_plugin_prepare,
        reset: snd_pcm_plugin_reset,
index 89a1c4f4235e6cb35cbf7558d00abdbe31e5d711..2195f1758b3432701ffe48ab10fb0e6a56f31110 100644 (file)
@@ -713,12 +713,34 @@ static snd_pcm_state_t snd_pcm_share_state(snd_pcm_t *pcm)
        return share->state;
 }
 
+static int _snd_pcm_share_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
+{
+       snd_pcm_share_t *share = pcm->private_data;
+       snd_pcm_share_slave_t *slave = share->slave;
+       switch (share->state) {
+       case SND_PCM_STATE_XRUN:
+               return -EPIPE;
+       default:
+               break;
+       }
+       return snd_pcm_avail(slave->pcm, availp);
+}
+
+static int snd_pcm_share_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
+{
+       snd_pcm_share_t *share = pcm->private_data;
+       snd_pcm_share_slave_t *slave = share->slave;
+       int err;
+       Pthread_mutex_lock(&slave->mutex);
+       err = _snd_pcm_share_avail(pcm, availp);
+       Pthread_mutex_unlock(&slave->mutex);
+       return err;
+}
+
 static int _snd_pcm_share_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 {
        snd_pcm_share_t *share = pcm->private_data;
        snd_pcm_share_slave_t *slave = share->slave;
-       int err = 0;
-       snd_pcm_sframes_t sd;
        switch (share->state) {
        case SND_PCM_STATE_XRUN:
                return -EPIPE;
@@ -731,11 +753,7 @@ static int _snd_pcm_share_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
        default:
                return -EBADFD;
        }
-       err = snd_pcm_delay(slave->pcm, &sd);
-       if (err < 0)
-               return err;
-       *delayp = sd + snd_pcm_mmap_delay(pcm);
-       return 0;
+       return snd_pcm_delay(slave->pcm, delayp);
 }
 
 static int snd_pcm_share_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
@@ -1215,6 +1233,7 @@ static snd_pcm_ops_t snd_pcm_share_ops = {
 static snd_pcm_fast_ops_t snd_pcm_share_fast_ops = {
        status: snd_pcm_share_status,
        state: snd_pcm_share_state,
+       avail: snd_pcm_share_avail,
        delay: snd_pcm_share_delay,
        prepare: snd_pcm_share_prepare,
        reset: snd_pcm_share_reset,
index 824bb8b92521b5daed80fa11dbd701c1762f8342..cf126fbbfd699c4cb0bb82f3333d2519289d55e6 100644 (file)
@@ -443,6 +443,19 @@ static snd_pcm_state_t snd_pcm_shm_state(snd_pcm_t *pcm)
        return snd_pcm_shm_action(pcm);
 }
 
+static int snd_pcm_shm_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
+{
+       snd_pcm_shm_t *shm = pcm->private_data;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       int err;
+       ctrl->cmd = SND_PCM_IOCTL_AVAIL;
+       err = snd_pcm_shm_action(pcm);
+       if (err < 0)
+               return err;
+       *availp = ctrl->u.avail.frames;
+       return err;
+}
+
 static int snd_pcm_shm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 {
        snd_pcm_shm_t *shm = pcm->private_data;