aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/tinyalsa/pcm.h2
-rw-r--r--src/pcm.c28
2 files changed, 30 insertions, 0 deletions
diff --git a/include/tinyalsa/pcm.h b/include/tinyalsa/pcm.h
index 99ca786..cdc31a5 100644
--- a/include/tinyalsa/pcm.h
+++ b/include/tinyalsa/pcm.h
@@ -343,6 +343,8 @@ int pcm_mmap_commit(struct pcm *pcm, unsigned int offset, unsigned int frames);
int pcm_mmap_avail(struct pcm *pcm);
+int pcm_mmap_get_hw_ptr(struct pcm* pcm, unsigned int *hw_ptr, struct timespec *tstamp);
+
int pcm_get_poll_fd(struct pcm *pcm);
int pcm_link(struct pcm *pcm1, struct pcm *pcm2);
diff --git a/src/pcm.c b/src/pcm.c
index eb16ed3..3b54ec7 100644
--- a/src/pcm.c
+++ b/src/pcm.c
@@ -1560,6 +1560,34 @@ int pcm_mmap_read(struct pcm *pcm, void *data, unsigned int count)
return pcm_mmap_transfer(pcm, data, pcm_bytes_to_frames(pcm, count));
}
+/* Returns current read/write position in the mmap buffer with associated time stamp. */
+int pcm_mmap_get_hw_ptr(struct pcm* pcm, unsigned int *hw_ptr, struct timespec *tstamp)
+{
+ int rc;
+
+ if (pcm == NULL || hw_ptr == NULL || tstamp == NULL)
+ return oops(pcm, EINVAL, "pcm %p, hw_ptr %p, tstamp %p", pcm, hw_ptr, tstamp);
+
+ if (!pcm_is_ready(pcm))
+ return oops(pcm, errno, "pcm_is_ready failed");
+
+ rc = pcm_sync_ptr(pcm, SNDRV_PCM_SYNC_PTR_HWSYNC);
+ if (rc < 0)
+ return oops(pcm, errno, "pcm_sync_ptr failed");
+
+ if ((pcm->mmap_status->state != PCM_STATE_RUNNING) &&
+ (pcm->mmap_status->state != PCM_STATE_DRAINING))
+ return oops(pcm, ENOSYS, "invalid stream state %d", pcm->mmap_status->state);
+
+ *tstamp = pcm->mmap_status->tstamp;
+ if (tstamp->tv_sec == 0 && tstamp->tv_nsec == 0)
+ return oops(pcm, errno, "invalid time stamp");
+
+ *hw_ptr = pcm->mmap_status->hw_ptr;
+
+ return 0;
+}
+
static int pcm_rw_transfer(struct pcm *pcm, void *data, unsigned int frames)
{
int is_playback;