return snd_timer_async(dmix->timer, sig, pid);
}
+/* empty the timer read queue */
+static void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix)
+{
+ /* rbuf might be overwriten by multiple plugins */
+ /* we don't need the value */
+ snd_timer_tread_t rbuf;
+ while (snd_timer_read(dmix->timer, &rbuf, sizeof(rbuf)) == sizeof(rbuf))
+ ;
+}
+
+int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix)
+{
+ snd_timer_stop(dmix->timer);
+ snd_pcm_direct_clear_timer_queue(dmix);
+}
+
int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
{
snd_pcm_direct_t *dmix = pcm->private_data;
unsigned short events;
- /* rbuf might be overwriten by multiple plugins */
- /* we don't need the value */
- static snd_timer_tread_t rbuf;
assert(pfds && nfds == 1 && revents);
events = pfds[0].revents;
} else {
empty = snd_pcm_mmap_capture_avail(pcm) < pcm->avail_min;
}
- /* empty the timer read queue */
- while (empty && snd_timer_read(dmix->timer, &rbuf, sizeof(rbuf)) == sizeof(rbuf)) ;
+ if (empty)
+ snd_pcm_direct_clear_timer_queue(dmix);
if (empty)
events &= ~(POLLOUT|POLLIN);
}
diff = slave_hw_ptr - old_slave_hw_ptr;
if (diff == 0) /* fast path */
return 0;
+ if (dmix->state != SNDRV_PCM_STATE_RUNNING &&
+ dmix->state != SNDRV_PCM_STATE_DRAINING)
+ /* not really started yet - don't update hw_ptr */
+ return 0;
if (diff < 0) {
slave_hw_ptr += dmix->shmptr->s.boundary;
diff = slave_hw_ptr - old_slave_hw_ptr;
return 0;
if ((avail = snd_pcm_mmap_playback_avail(pcm)) >= pcm->stop_threshold) {
struct timeval tv;
- snd_timer_stop(dmix->timer);
+ snd_pcm_direct_timer_stop(dmix);
gettimeofday(&tv, 0);
dmix->trigger_tstamp.tv_sec = tv.tv_sec;
dmix->trigger_tstamp.tv_nsec = tv.tv_usec * 1000L;
return 0;
}
+static int snd_pcm_dmix_start_timer(snd_pcm_direct_t *dmix)
+{
+ int err;
+
+ snd_pcm_hwsync(dmix->spcm);
+ dmix->slave_appl_ptr = dmix->slave_hw_ptr = *dmix->spcm->hw.ptr;
+ err = snd_timer_start(dmix->timer);
+ if (err < 0)
+ return err;
+ dmix->state = SND_PCM_STATE_RUNNING;
+ return 0;
+}
+
static int snd_pcm_dmix_start(snd_pcm_t *pcm)
{
snd_pcm_direct_t *dmix = pcm->private_data;
if (dmix->state != SND_PCM_STATE_PREPARED)
return -EBADFD;
- snd_pcm_hwsync(dmix->spcm);
- dmix->slave_appl_ptr = dmix->slave_hw_ptr = *dmix->spcm->hw.ptr;
avail = snd_pcm_mmap_playback_hw_avail(pcm);
if (avail == 0)
dmix->state = STATE_RUN_PENDING;
else {
if (avail > (snd_pcm_sframes_t)pcm->buffer_size)
avail = pcm->buffer_size;
- err = snd_timer_start(dmix->timer);
- if (err < 0)
+ if ((err = snd_pcm_dmix_start_timer(dmix)) < 0)
return err;
- dmix->state = SND_PCM_STATE_RUNNING;
snd_pcm_dmix_sync_area(pcm, avail);
}
gettimeofday(&tv, 0);
snd_pcm_direct_t *dmix = pcm->private_data;
if (dmix->state == SND_PCM_STATE_OPEN)
return -EBADFD;
- snd_timer_stop(dmix->timer);
+ snd_pcm_direct_timer_stop(dmix);
dmix->state = SND_PCM_STATE_SETUP;
return 0;
}
snd_pcm_direct_t *dmix = pcm->private_data;
if (enable) {
if (dmix->state == SND_PCM_STATE_RUNNING)
- snd_timer_stop(dmix->timer);
+ snd_pcm_direct_timer_stop(dmix);
else if (dmix->state != STATE_RUN_PENDING)
return -EBADFD;
dmix->state = SND_PCM_STATE_PAUSED;
return -EBADFD;
if (snd_pcm_mmap_playback_hw_avail(pcm) > 0) {
dmix->state = SND_PCM_STATE_RUNNING;
+ /* FIXME: sync the hwptr */
snd_timer_start(dmix->timer);
} else
dmix->state = STATE_RUN_PENDING;
default:
break;
}
- snd_pcm_mmap_appl_forward(pcm, size);
if (dmix->state == STATE_RUN_PENDING) {
- err = snd_timer_start(dmix->timer);
- if (err < 0)
+ if ((err = snd_pcm_dmix_start_timer(dmix)) < 0)
return err;
- dmix->state = SND_PCM_STATE_RUNNING;
}
+ snd_pcm_mmap_appl_forward(pcm, size);
if (dmix->state == SND_PCM_STATE_RUNNING) {
err = snd_pcm_dmix_sync_ptr(pcm);
if (err < 0)