summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/pcm/pcm_rate.c50
1 files changed, 44 insertions, 6 deletions
diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
index 6184defb..1f830dd7 100644
--- a/src/pcm/pcm_rate.c
+++ b/src/pcm/pcm_rate.c
@@ -559,10 +559,9 @@ snd_pcm_rate_read_areas1(snd_pcm_t *pcm,
pcm->channels, rate);
}
-static inline void snd_pcm_rate_sync_hwptr(snd_pcm_t *pcm)
+static inline void snd_pcm_rate_sync_hwptr0(snd_pcm_t *pcm, snd_pcm_uframes_t slave_hw_ptr)
{
snd_pcm_rate_t *rate = pcm->private_data;
- snd_pcm_uframes_t slave_hw_ptr = *rate->gen.slave->hw.ptr;
if (pcm->stream != SND_PCM_STREAM_PLAYBACK)
return;
@@ -576,6 +575,12 @@ static inline void snd_pcm_rate_sync_hwptr(snd_pcm_t *pcm)
rate->hw_ptr %= pcm->boundary;
}
+static inline void snd_pcm_rate_sync_hwptr(snd_pcm_t *pcm)
+{
+ snd_pcm_rate_t *rate = pcm->private_data;
+ snd_pcm_rate_sync_hwptr0(pcm, *rate->gen.slave->hw.ptr);
+}
+
static int snd_pcm_rate_hwsync(snd_pcm_t *pcm)
{
snd_pcm_rate_t *rate = pcm->private_data;
@@ -586,10 +591,37 @@ static int snd_pcm_rate_hwsync(snd_pcm_t *pcm)
return 0;
}
+static snd_pcm_uframes_t snd_pcm_rate_playback_internal_delay(snd_pcm_t *pcm)
+{
+ snd_pcm_rate_t *rate = pcm->private_data;
+
+ if (rate->appl_ptr < rate->last_commit_ptr) {
+ return rate->appl_ptr - rate->last_commit_ptr + pcm->boundary;
+ } else {
+ return rate->appl_ptr - rate->last_commit_ptr;
+ }
+}
+
static int snd_pcm_rate_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
{
+ snd_pcm_rate_t *rate = pcm->private_data;
+ snd_pcm_sframes_t slave_delay;
+ int err;
+
snd_pcm_rate_hwsync(pcm);
- *delayp = snd_pcm_mmap_hw_avail(pcm);
+
+ err = snd_pcm_delay(rate->gen.slave, &slave_delay);
+ if (err < 0) {
+ return err;
+ }
+
+ if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
+ *delayp = rate->ops.input_frames(rate->obj, slave_delay)
+ + snd_pcm_rate_playback_internal_delay(pcm);
+ } else {
+ *delayp = rate->ops.output_frames(rate->obj, slave_delay)
+ + snd_pcm_mmap_capture_hw_avail(pcm);
+ }
return 0;
}
@@ -1083,15 +1115,21 @@ static int snd_pcm_rate_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
status->state = SND_PCM_STATE_RUNNING;
status->trigger_tstamp = rate->trigger_tstamp;
}
- snd_pcm_rate_sync_hwptr(pcm);
+ snd_pcm_rate_sync_hwptr0(pcm, status->hw_ptr);
status->appl_ptr = *pcm->appl.ptr;
status->hw_ptr = *pcm->hw.ptr;
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
- status->delay = snd_pcm_mmap_playback_hw_avail(pcm);
+ status->delay = rate->ops.input_frames(rate->obj, status->delay)
+ + snd_pcm_rate_playback_internal_delay(pcm);
status->avail = snd_pcm_mmap_playback_avail(pcm);
status->avail_max = rate->ops.input_frames(rate->obj, status->avail_max);
} else {
- status->delay = snd_pcm_mmap_capture_hw_avail(pcm);
+ /* FIXME: Maybe possible to somthing similar to
+ * snd_pcm_rate_playback_internal_delay()
+ * for the capture case.
+ */
+ status->delay = rate->ops.output_frames(rate->obj, status->delay)
+ + snd_pcm_mmap_capture_hw_avail(pcm);
status->avail = snd_pcm_mmap_capture_avail(pcm);
status->avail_max = rate->ops.output_frames(rate->obj, status->avail_max);
}