@@ -234,6 +234,9 @@ int snd_pcm_ioplug_set_param_list(snd_pcm_ioplug_t *io, int type, unsigned int n
/* change PCM status */
int snd_pcm_ioplug_set_state(snd_pcm_ioplug_t *ioplug, snd_pcm_state_t state);
+/* calucalte the available frames */
+snd_pcm_uframes_t snd_pcm_ioplug_hw_avail(const snd_pcm_ioplug_t* const ioplug, const snd_pcm_uframes_t hw_ptr, const snd_pcm_uframes_t appl_ptr);
+
/** \} */
#endif /* __ALSA_PCM_IOPLUG_H */
@@ -1148,3 +1148,27 @@ int snd_pcm_ioplug_set_state(snd_pcm_ioplug_t *ioplug, snd_pcm_state_t state)
ioplug->state = state;
return 0;
}
+
+/**
+ * \brief Get the available frames. This function can be used to calculate the
+ * the available frames before calling #snd_pcm_avail_update()
+ * \param ioplug the ioplug handle
+ * \param hw_ptr hardware pointer in frames
+ * \param appl_ptr application pointer in frames
+ * \return available frames for the hardware
+ */
+snd_pcm_uframes_t snd_pcm_ioplug_hw_avail(const snd_pcm_ioplug_t* const ioplug,
+ const snd_pcm_uframes_t hw_ptr,
+ const snd_pcm_uframes_t appl_ptr)
+{
+ /* available data/space which can be transfered by the user application */
+ const snd_pcm_uframes_t user_avail = __snd_pcm_avail(ioplug->pcm, hw_ptr,
+ appl_ptr);
+
+ if (user_avail > ioplug->pcm->buffer_size) {
+ /* there was an Xrun */
+ return 0;
+ }
+ /* available data/space which can be transfered by the DMA */
+ return ioplug->pcm->buffer_size - user_avail;
+}
@@ -467,10 +467,12 @@ static inline int snd_pcm_check_error(snd_pcm_t *pcm, int err)
return err;
}
-static inline snd_pcm_uframes_t snd_pcm_mmap_playback_avail(snd_pcm_t *pcm)
+static inline snd_pcm_uframes_t __snd_pcm_playback_avail(snd_pcm_t *pcm,
+ const snd_pcm_uframes_t hw_ptr,
+ const snd_pcm_uframes_t appl_ptr)
{
snd_pcm_sframes_t avail;
- avail = *pcm->hw.ptr + pcm->buffer_size - *pcm->appl.ptr;
+ avail = hw_ptr + pcm->buffer_size - appl_ptr;
if (avail < 0)
avail += pcm->boundary;
else if ((snd_pcm_uframes_t) avail >= pcm->boundary)
@@ -478,21 +480,40 @@ static inline snd_pcm_uframes_t snd_pcm_mmap_playback_avail(snd_pcm_t *pcm)
return avail;
}
-static inline snd_pcm_uframes_t snd_pcm_mmap_capture_avail(snd_pcm_t *pcm)
+static inline snd_pcm_uframes_t snd_pcm_mmap_playback_avail(snd_pcm_t *pcm)
+{
+ return __snd_pcm_playback_avail(pcm, *pcm->hw.ptr, *pcm->appl.ptr);
+}
+
+static inline snd_pcm_uframes_t __snd_pcm_capture_avail(snd_pcm_t *pcm,
+ const snd_pcm_uframes_t hw_ptr,
+ const snd_pcm_uframes_t appl_ptr)
{
snd_pcm_sframes_t avail;
- avail = *pcm->hw.ptr - *pcm->appl.ptr;
+ avail = hw_ptr - appl_ptr;
if (avail < 0)
avail += pcm->boundary;
return avail;
}
-static inline snd_pcm_uframes_t snd_pcm_mmap_avail(snd_pcm_t *pcm)
+static inline snd_pcm_uframes_t snd_pcm_mmap_playback_avail(snd_pcm_t *pcm)
+{
+ return __snd_pcm_capture_avail(pcm, *pcm->hw.ptr, *pcm->appl.ptr);
+}
+
+static inline snd_pcm_uframes_t __snd_pcm_avail(snd_pcm_t *pcm,
+ const snd_pcm_uframes_t hw_ptr,
+ const snd_pcm_uframes_t appl_ptr)
{
if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
- return snd_pcm_mmap_playback_avail(pcm);
+ return snd_pcm_playback_avail(pcm, hw_ptr, appl_ptr);
else
- return snd_pcm_mmap_capture_avail(pcm);
+ return snd_pcm_capture_avail(pcm, hw_ptr, appl_ptr);
+}
+
+static inline snd_pcm_uframes_t snd_pcm_mmap_avail(snd_pcm_t *pcm)
+{
+ return __snd_pcm_avail(pcm, *pcm->hw.ptr, *pcm->appl.ptr);
}
static inline snd_pcm_sframes_t snd_pcm_mmap_playback_hw_avail(snd_pcm_t *pcm)