{
struct private_alsa_write_data *pad = wn->private_data;
struct writer_node_group *wng = wn->wng;
- size_t frames, bytes = *wng->loaded - wn->written;
+ size_t bytes = *wng->loaded - wn->written;
unsigned char *data = (unsigned char*)*wng->bufp + wn->written;
struct timeval tv;
- snd_pcm_sframes_t ret;
+ snd_pcm_sframes_t ret, frames, avail;
if (*wng->input_error < 0 && (!pad->handle || bytes < pad->bytes_per_frame)) {
wn->written = *wng->loaded;
return *wng->input_error;
}
if (!bytes) /* no data available */
- goto out;
+ return 0;
if (tv_diff(now, &pad->next_chunk, NULL) < 0)
- goto out;
+ return 0;
if (!pad->handle) {
int err = alsa_init(pad, wn->conf);
if (err < 0)
}
frames = bytes / pad->bytes_per_frame;
if (!frames) /* less than a single frame available */
- goto out;
+ return 0;
+ avail = snd_pcm_avail_update(pad->handle);
+ if (avail <= 0)
+ goto delay;
+ frames = PARA_MIN(frames, avail);
ret = snd_pcm_writei(pad->handle, data, frames);
- if (ret == -EPIPE) {
- PARA_WARNING_LOG("EPIPE\n");
- snd_pcm_prepare(pad->handle);
- return 1;
- }
- if (ret < 0 && ret != -EAGAIN) {
- PARA_WARNING_LOG("alsa error (%zu frames, ret = %d\n",
- frames, (int)ret);
+ if (ret < 0) {
+ PARA_WARNING_LOG("%s\n", snd_strerror(-ret));
+ if (ret == -EPIPE) {
+ snd_pcm_prepare(pad->handle);
+ return 0;
+ }
+ if (ret == -EAGAIN)
+ goto delay;
return -E_ALSA_WRITE;
}
- if (ret == -EAGAIN)
- PARA_DEBUG_LOG("EAGAIN\n");
- else
- wn->written += ret * pad->bytes_per_frame;
- if (ret == frames) /* we wrote everything, try again immediately */
- pad->next_chunk = *now;
- else { /* wait until 50% buffer space is available */
- ms2tv(pad->buffer_time / 2000, &tv);
- tv_add(now, &tv, &pad->next_chunk);
- }
-out:
+ wn->written += ret * pad->bytes_per_frame;
return 1;
+delay:
+ /* wait until 50% buffer space is available */
+ ms2tv(pad->buffer_time / 2000, &tv);
+ tv_add(now, &tv, &pad->next_chunk);
+ return 0;
}
static void alsa_close(struct writer_node *wn)