Impemented snd_pcm_htimestamp() function.

This commit is contained in:
Jaroslav Kysela 2008-01-09 13:50:45 +01:00
parent 309a274454
commit 2c1318803f
19 changed files with 182 additions and 14 deletions

View file

@ -427,6 +427,7 @@ snd_pcm_state_t snd_pcm_state(snd_pcm_t *pcm);
int snd_pcm_hwsync(snd_pcm_t *pcm);
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_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
snd_pcm_sframes_t snd_pcm_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames);

View file

@ -343,7 +343,8 @@ is equal or greater than this value, then application will be activated.
The timestamp mode specifies, if timestamps are activated. Currently, only
#SND_PCM_TSTAMP_NONE and #SND_PCM_TSTAMP_MMAP
modes are known. The mmap mode means that timestamp is taken
on every period time boundary.
on every period time boundary. Corresponding position in the ring buffer
assigned to timestamp can be obtained using #snd_pcm_htimestamp() function.
\par Transfer align
@ -383,7 +384,7 @@ The stream status is stored in #snd_pcm_status_t structure.
These parameters can be obtained: the current stream state -
#snd_pcm_status_get_state(), timestamp of trigger -
#snd_pcm_status_get_trigger_tstamp(), timestamp of last
update #snd_pcm_status_get_tstamp(), delay in samples -
pointer update #snd_pcm_status_get_tstamp(), delay in samples -
#snd_pcm_status_get_delay(), available count in samples -
#snd_pcm_status_get_avail(), maximum available samples -
#snd_pcm_status_get_avail_max(), ADC over-range count in
@ -979,6 +980,26 @@ int snd_pcm_resume(snd_pcm_t *pcm)
return pcm->fast_ops->resume(pcm->fast_op_arg);
}
/**
* \brief Obtain last position update hi-res timestamp
* \param pcm PCM handle
* \param avail Number of available frames when timestamp was grabbed
* \param tstamp Hi-res timestamp
* \return 0 on success otherwise a negative error code
*
* Note this function does not update the actual r/w pointer
* for applications.
*/
int snd_pcm_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail, snd_htimestamp_t *tstamp)
{
assert(pcm);
if (CHECK_SANITY(! pcm->setup)) {
SNDMSG("PCM not set up");
return -EIO;
}
return pcm->fast_ops->htimestamp(pcm->fast_op_arg, avail, tstamp);
}
/**
* \brief Prepare PCM for use
* \param pcm PCM handle

View file

@ -382,10 +382,7 @@ static int snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
memset(status, 0, sizeof(*status));
status->state = snd_pcm_dmix_state(pcm);
status->trigger_tstamp = dmix->trigger_tstamp;
if (pcm->tstamp_mode == SND_PCM_TSTAMP_MMAP)
status->tstamp = snd_pcm_hw_fast_tstamp(dmix->spcm);
else
gettimestamp(&status->tstamp, pcm->monotonic);
gettimestamp(&status->tstamp, pcm->monotonic);
status->avail = snd_pcm_mmap_playback_avail(pcm);
status->avail_max = status->avail > dmix->avail_max ? status->avail : dmix->avail_max;
dmix->avail_max = 0;
@ -671,6 +668,27 @@ static snd_pcm_sframes_t snd_pcm_dmix_avail_update(snd_pcm_t *pcm)
return snd_pcm_mmap_playback_avail(pcm);
}
static int snd_pcm_dmix_htimestamp(snd_pcm_t *pcm,
snd_pcm_uframes_t *avail,
snd_htimestamp_t *tstamp)
{
snd_pcm_direct_t *dmix = pcm->private_data;
snd_pcm_uframes_t avail1;
int ok = 0;
while (1) {
if (dmix->state == SND_PCM_STATE_RUNNING ||
dmix->state == SND_PCM_STATE_DRAINING)
snd_pcm_dmix_sync_ptr(pcm);
avail1 = snd_pcm_mmap_playback_avail(pcm);
if (ok && *avail == avail1)
break;
*avail = avail1;
*tstamp = snd_pcm_hw_fast_tstamp(pcm);
}
return 0;
}
static int snd_pcm_dmix_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
{
snd_pcm_direct_t *dmix = pcm->private_data;
@ -731,6 +749,7 @@ static snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = {
.readn = snd_pcm_dmix_readn,
.avail_update = snd_pcm_dmix_avail_update,
.mmap_commit = snd_pcm_dmix_mmap_commit,
.htimestamp = snd_pcm_dmix_htimestamp,
.poll_descriptors = NULL,
.poll_descriptors_count = NULL,
.poll_revents = snd_pcm_dmix_poll_revents,

View file

@ -226,10 +226,7 @@ static int snd_pcm_dshare_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
memset(status, 0, sizeof(*status));
status->state = snd_pcm_state(dshare->spcm);
status->trigger_tstamp = dshare->trigger_tstamp;
if (pcm->tstamp_mode == SND_PCM_TSTAMP_MMAP)
status->tstamp = snd_pcm_hw_fast_tstamp(dshare->spcm);
else
gettimestamp(&status->tstamp, pcm->monotonic);
gettimestamp(&status->tstamp, pcm->monotonic);
status->avail = snd_pcm_mmap_playback_avail(pcm);
status->avail_max = status->avail > dshare->avail_max ? status->avail : dshare->avail_max;
dshare->avail_max = 0;
@ -517,6 +514,27 @@ static snd_pcm_sframes_t snd_pcm_dshare_avail_update(snd_pcm_t *pcm)
return snd_pcm_mmap_playback_avail(pcm);
}
static int snd_pcm_dshare_htimestamp(snd_pcm_t *pcm,
snd_pcm_uframes_t *avail,
snd_htimestamp_t *tstamp)
{
snd_pcm_direct_t *dshare = pcm->private_data;
snd_pcm_uframes_t avail1;
int ok = 0;
while (1) {
if (dshare->state == SND_PCM_STATE_RUNNING ||
dshare->state == SND_PCM_STATE_DRAINING)
snd_pcm_dshare_sync_ptr(pcm);
avail1 = snd_pcm_mmap_playback_avail(pcm);
if (ok && *avail == avail1)
break;
*avail = avail1;
*tstamp = snd_pcm_hw_fast_tstamp(pcm);
}
return 0;
}
static void snd_pcm_dshare_dump(snd_pcm_t *pcm, snd_output_t *out)
{
snd_pcm_direct_t *dshare = pcm->private_data;
@ -568,6 +586,7 @@ static snd_pcm_fast_ops_t snd_pcm_dshare_fast_ops = {
.readn = snd_pcm_dshare_readn,
.avail_update = snd_pcm_dshare_avail_update,
.mmap_commit = snd_pcm_dshare_mmap_commit,
.htimestamp = snd_pcm_dshare_htimestamp,
.poll_descriptors = NULL,
.poll_descriptors_count = NULL,
.poll_revents = snd_pcm_direct_poll_revents,

View file

@ -172,10 +172,7 @@ static int snd_pcm_dsnoop_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
state = snd_pcm_state(dsnoop->spcm);
status->state = state == SND_PCM_STATE_RUNNING ? dsnoop->state : state;
status->trigger_tstamp = dsnoop->trigger_tstamp;
if (pcm->tstamp_mode == SND_PCM_TSTAMP_MMAP)
status->tstamp = snd_pcm_hw_fast_tstamp(dsnoop->spcm);
else
gettimestamp(&status->tstamp, pcm->monotonic);
gettimestamp(&status->tstamp, pcm->monotonic);
status->avail = snd_pcm_mmap_capture_avail(pcm);
status->avail_max = status->avail > dsnoop->avail_max ? status->avail : dsnoop->avail_max;
dsnoop->avail_max = 0;
@ -407,6 +404,27 @@ static snd_pcm_sframes_t snd_pcm_dsnoop_avail_update(snd_pcm_t *pcm)
return snd_pcm_mmap_capture_avail(pcm);
}
static int snd_pcm_dsnoop_htimestamp(snd_pcm_t *pcm,
snd_pcm_uframes_t *avail,
snd_htimestamp_t *tstamp)
{
snd_pcm_direct_t *dsnoop = pcm->private_data;
snd_pcm_uframes_t avail1;
int ok = 0;
while (1) {
if (dsnoop->state == SND_PCM_STATE_RUNNING ||
dsnoop->state == SND_PCM_STATE_DRAINING)
snd_pcm_dsnoop_sync_ptr(pcm);
avail1 = snd_pcm_mmap_capture_avail(pcm);
if (ok && *avail == avail1)
break;
*avail = avail1;
*tstamp = snd_pcm_hw_fast_tstamp(pcm);
}
return 0;
}
static void snd_pcm_dsnoop_dump(snd_pcm_t *pcm, snd_output_t *out)
{
snd_pcm_direct_t *dsnoop = pcm->private_data;
@ -458,6 +476,7 @@ static snd_pcm_fast_ops_t snd_pcm_dsnoop_fast_ops = {
.readn = snd_pcm_mmap_readn,
.avail_update = snd_pcm_dsnoop_avail_update,
.mmap_commit = snd_pcm_dsnoop_mmap_commit,
.htimestamp = snd_pcm_dsnoop_htimestamp,
.poll_descriptors = NULL,
.poll_descriptors_count = NULL,
.poll_revents = snd_pcm_direct_poll_revents,

View file

@ -259,6 +259,13 @@ snd_pcm_sframes_t snd_pcm_generic_avail_update(snd_pcm_t *pcm)
return snd_pcm_avail_update(generic->slave);
}
int snd_pcm_generic_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail,
snd_htimestamp_t *tstamp)
{
snd_pcm_generic_t *generic = pcm->private_data;
return snd_pcm_htimestamp(generic->slave, avail, tstamp);
}
int snd_pcm_generic_mmap(snd_pcm_t *pcm)
{
if (pcm->mmap_shadow) {

View file

@ -137,5 +137,7 @@ snd_pcm_sframes_t snd_pcm_generic_mmap_commit(snd_pcm_t *pcm,
snd_pcm_uframes_t offset,
snd_pcm_uframes_t size);
snd_pcm_sframes_t snd_pcm_generic_avail_update(snd_pcm_t *pcm);
int snd_pcm_generic_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail,
snd_htimestamp_t *timestamp);
int snd_pcm_generic_mmap(snd_pcm_t *pcm);
int snd_pcm_generic_munmap(snd_pcm_t *pcm);

View file

@ -159,6 +159,7 @@ static snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = {
.readn = snd_pcm_generic_readn,
.avail_update = snd_pcm_generic_avail_update,
.mmap_commit = snd_pcm_generic_mmap_commit,
.htimestamp = snd_pcm_generic_htimestamp,
.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
.poll_descriptors = snd_pcm_generic_poll_descriptors,
.poll_revents = snd_pcm_generic_poll_revents,

View file

@ -846,6 +846,26 @@ static snd_pcm_sframes_t snd_pcm_hw_avail_update(snd_pcm_t *pcm)
return avail;
}
static int snd_pcm_hw_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail,
snd_htimestamp_t *tstamp)
{
snd_pcm_sframes_t avail1;
int ok = 0;
/* unfortunately, loop is necessary to ensure valid timestamp */
while (1) {
avail1 = snd_pcm_hw_avail_update(pcm);
if (avail1 < 0)
return avail1;
if (ok && (snd_pcm_uframes_t)avail1 == *avail)
break;
*avail = avail1;
*tstamp = snd_pcm_hw_fast_tstamp(pcm);
ok = 1;
}
return 0;
}
static void snd_pcm_hw_dump(snd_pcm_t *pcm, snd_output_t *out)
{
snd_pcm_hw_t *hw = pcm->private_data;
@ -902,6 +922,7 @@ static snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
.readn = snd_pcm_hw_readn,
.avail_update = snd_pcm_hw_avail_update,
.mmap_commit = snd_pcm_hw_mmap_commit,
.htimestamp = snd_pcm_hw_htimestamp,
.poll_descriptors = NULL,
.poll_descriptors_count = NULL,
.poll_revents = NULL,

View file

@ -636,6 +636,13 @@ static snd_pcm_sframes_t snd_pcm_ioplug_avail_update(snd_pcm_t *pcm)
return (snd_pcm_sframes_t)avail;
}
static int snd_pcm_ioplug_htimestamp(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
snd_pcm_uframes_t *avail ATTRIBUTE_UNUSED,
snd_htimestamp_t *tstamp ATTRIBUTE_UNUSED)
{
return -EIO; /* not implemented yet */
}
static int snd_pcm_ioplug_nonblock(snd_pcm_t *pcm, int nonblock)
{
ioplug_priv_t *io = pcm->private_data;
@ -774,6 +781,7 @@ static snd_pcm_fast_ops_t snd_pcm_ioplug_fast_ops = {
.readn = snd_pcm_ioplug_readn,
.avail_update = snd_pcm_ioplug_avail_update,
.mmap_commit = snd_pcm_ioplug_mmap_commit,
.htimestamp = snd_pcm_ioplug_htimestamp,
.poll_descriptors_count = snd_pcm_ioplug_poll_descriptors_count,
.poll_descriptors = snd_pcm_ioplug_poll_descriptors,
.poll_revents = snd_pcm_ioplug_poll_revents,

View file

@ -163,6 +163,7 @@ typedef struct {
snd_pcm_sframes_t (*readn)(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
snd_pcm_sframes_t (*avail_update)(snd_pcm_t *pcm);
snd_pcm_sframes_t (*mmap_commit)(snd_pcm_t *pcm, snd_pcm_uframes_t offset, snd_pcm_uframes_t size);
int (*htimestamp)(snd_pcm_t *pcm, snd_pcm_uframes_t *avail, snd_htimestamp_t *tstamp);
int (*poll_descriptors_count)(snd_pcm_t *pcm);
int (*poll_descriptors)(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space);
int (*poll_revents)(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);

View file

@ -536,6 +536,7 @@ static snd_pcm_fast_ops_t snd_pcm_meter_fast_ops = {
.readn = snd_pcm_mmap_readn,
.avail_update = snd_pcm_meter_avail_update,
.mmap_commit = snd_pcm_meter_mmap_commit,
.htimestamp = snd_pcm_generic_htimestamp,
.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
.poll_descriptors = snd_pcm_generic_poll_descriptors,
.poll_revents = snd_pcm_generic_poll_revents,

View file

@ -370,6 +370,7 @@ static snd_pcm_fast_ops_t snd_pcm_mmap_emul_fast_ops = {
.readn = snd_pcm_generic_readn,
.avail_update = snd_pcm_mmap_emul_avail_update,
.mmap_commit = snd_pcm_mmap_emul_mmap_commit,
.htimestamp = snd_pcm_generic_htimestamp,
.poll_descriptors = snd_pcm_generic_poll_descriptors,
.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
.poll_revents = snd_pcm_generic_poll_revents,

View file

@ -431,6 +431,14 @@ static snd_pcm_sframes_t snd_pcm_multi_avail_update(snd_pcm_t *pcm)
return ret;
}
static int snd_pcm_multi_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail,
snd_htimestamp_t *tstamp)
{
snd_pcm_multi_t *multi = pcm->private_data;
snd_pcm_t *slave = multi->slaves[multi->master_slave].pcm;
return snd_pcm_htimestamp(slave, avail, tstamp);
}
static int snd_pcm_multi_prepare(snd_pcm_t *pcm)
{
snd_pcm_multi_t *multi = pcm->private_data;
@ -792,6 +800,7 @@ static snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = {
.unlink = snd_pcm_multi_unlink,
.avail_update = snd_pcm_multi_avail_update,
.mmap_commit = snd_pcm_multi_mmap_commit,
.htimestamp = snd_pcm_multi_htimestamp,
.poll_descriptors_count = snd_pcm_multi_poll_descriptors_count,
.poll_descriptors = snd_pcm_multi_poll_descriptors,
.poll_revents = snd_pcm_multi_poll_revents,

View file

@ -244,6 +244,13 @@ static snd_pcm_sframes_t snd_pcm_null_avail_update(snd_pcm_t *pcm)
return pcm->buffer_size;
}
static int snd_pcm_null_htimestamp(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
snd_pcm_uframes_t *avail ATTRIBUTE_UNUSED,
snd_htimestamp_t *tstamp ATTRIBUTE_UNUSED)
{
return -EIO;
}
static int snd_pcm_null_hw_refine(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
{
int err = snd_pcm_hw_refine_soft(pcm, params);
@ -312,6 +319,7 @@ static snd_pcm_fast_ops_t snd_pcm_null_fast_ops = {
.readn = snd_pcm_null_readn,
.avail_update = snd_pcm_null_avail_update,
.mmap_commit = snd_pcm_null_mmap_commit,
.htimestamp = snd_pcm_null_htimestamp,
};
/**

View file

@ -575,6 +575,7 @@ snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
.readn = snd_pcm_plugin_readn,
.avail_update = snd_pcm_plugin_avail_update,
.mmap_commit = snd_pcm_plugin_mmap_commit,
.htimestamp = snd_pcm_generic_htimestamp,
.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
.poll_descriptors = snd_pcm_generic_poll_descriptors,
.poll_revents = snd_pcm_generic_poll_revents,

View file

@ -1020,6 +1020,13 @@ static snd_pcm_sframes_t snd_pcm_rate_avail_update(snd_pcm_t *pcm)
}
}
static int snd_pcm_rate_htimestamp(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
snd_pcm_uframes_t *avail ATTRIBUTE_UNUSED,
snd_htimestamp_t *tstamp ATTRIBUTE_UNUSED)
{
return -EIO; /* not implemented yet */
}
static int snd_pcm_rate_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
{
snd_pcm_rate_t *rate = pcm->private_data;
@ -1189,6 +1196,7 @@ static snd_pcm_fast_ops_t snd_pcm_rate_fast_ops = {
.readn = snd_pcm_mmap_readn,
.avail_update = snd_pcm_rate_avail_update,
.mmap_commit = snd_pcm_rate_mmap_commit,
.htimestamp = snd_pcm_rate_htimestamp,
.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
.poll_descriptors = snd_pcm_generic_poll_descriptors,
.poll_revents = snd_pcm_rate_poll_revents,

View file

@ -798,6 +798,18 @@ static snd_pcm_sframes_t snd_pcm_share_avail_update(snd_pcm_t *pcm)
return avail;
}
static int snd_pcm_share_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail,
snd_htimestamp_t *tstamp)
{
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_htimestamp(slave->pcm, avail, tstamp);
Pthread_mutex_unlock(&slave->mutex);
return err;
}
/* Call it with mutex held */
static snd_pcm_sframes_t _snd_pcm_share_mmap_commit(snd_pcm_t *pcm,
snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
@ -1308,6 +1320,7 @@ static snd_pcm_fast_ops_t snd_pcm_share_fast_ops = {
.forward = snd_pcm_share_forward,
.resume = snd_pcm_share_resume,
.avail_update = snd_pcm_share_avail_update,
.htimestamp = snd_pcm_share_htimestamp,
.mmap_commit = snd_pcm_share_mmap_commit,
};

View file

@ -441,6 +441,13 @@ static snd_pcm_sframes_t snd_pcm_shm_avail_update(snd_pcm_t *pcm)
return err;
}
static int snd_pcm_shm_htimestamp(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
snd_pcm_uframes_t *avail ATTRIBUTE_UNUSED,
snd_htimestamp_t *tstamp ATTRIBUTE_UNUSED)
{
return -EIO; /* not implemented yet */
}
static int snd_pcm_shm_prepare(snd_pcm_t *pcm)
{
snd_pcm_shm_t *shm = pcm->private_data;
@ -609,6 +616,7 @@ static snd_pcm_fast_ops_t snd_pcm_shm_fast_ops = {
.readn = snd_pcm_mmap_readn,
.avail_update = snd_pcm_shm_avail_update,
.mmap_commit = snd_pcm_shm_mmap_commit,
.htimestamp = snd_pcm_shm_htimestamp,
};
static int make_local_socket(const char *filename)