snd_pcm_format_t sample_format;
/* The number of channels, again determined like \a sample_rate. */
unsigned channels;
+ /* time until buffer underrun occurs, in microseconds */
+ unsigned buffer_time;
struct timeval drain_barrier;
/* File descriptor for select(). */
int poll_fd;
snd_pcm_uframes_t start_threshold, stop_threshold;
snd_pcm_uframes_t buffer_size, period_size;
snd_output_t *output_log;
- unsigned buffer_time;
int ret;
const char *msg;
unsigned period_time;
if (ret < 0)
goto fail;
msg = "unable to get buffer time";
- ret = snd_pcm_hw_params_get_buffer_time_max(hwparams, &buffer_time,
+ ret = snd_pcm_hw_params_get_buffer_time_max(hwparams, &pad->buffer_time,
NULL);
- if (ret < 0 || buffer_time == 0)
+ if (ret < 0 || pad->buffer_time == 0)
goto fail;
/* buffer at most 500 milliseconds */
- buffer_time = PARA_MIN(buffer_time, 500U * 1000U);
+ pad->buffer_time = PARA_MIN(pad->buffer_time, 500U * 1000U);
msg = "could not set buffer time";
ret = snd_pcm_hw_params_set_buffer_time_near(pad->handle, hwparams,
- &buffer_time, NULL);
+ &pad->buffer_time, NULL);
if (ret < 0)
goto fail;
- period_time = buffer_time / 4;
+ period_time = pad->buffer_time / 4;
msg = "could not set period time";
ret = snd_pcm_hw_params_set_period_time_near(pad->handle, hwparams,
&period_time, 0);
sched_request_barrier_or_min_delay(&pad->drain_barrier, s);
return;
}
+ /* wait at most 50% of the buffer time */
+ sched_request_timeout_ms(pad->buffer_time / 2 / 1000, s);
ret = snd_pcm_poll_descriptors(pad->handle, &pfd, 1);
if (ret < 0) {
PARA_ERROR_LOG("could not get alsa poll fd: %s\n",
wn->min_iqs = pad->bytes_per_frame;
goto again;
}
- if (pad->poll_fd < 0 || !FD_ISSET(pad->poll_fd, &s->rfds))
- return 0;
frames = bytes / pad->bytes_per_frame;
frames = snd_pcm_writei(pad->handle, data, frames);
if (frames == 0 || frames == -EAGAIN) {
- /*
- * The alsa poll fd was ready for IO but we failed to write to
- * the alsa handle. This means another event is pending. We
- * don't care about that but we have to dispatch the event in
- * order to avoid a busy loop. So we simply read from the poll
- * fd.
- */
char buf[100];
- if (read(pad->poll_fd, buf, 100))
- do_nothing;
+ if (pad->poll_fd >= 0 && FD_ISSET(pad->poll_fd, &s->rfds))
+ if (read(pad->poll_fd, buf, 100))
+ do_nothing;
return 0;
}
if (frames > 0) {