Merge branch 'maint'
[paraslash.git] / alsa_write.c
index 67ab59ad357127dbc3b065b73f1a250ee91b22b4..9d99c8e91af6c4c78e402f9efde4ce00e40cb785 100644 (file)
@@ -16,6 +16,7 @@
 #include <sys/types.h>
 #include <dirent.h>
 #include <alsa/asoundlib.h>
+#include <sys/time.h>
 
 #include "para.h"
 #include "fd.h"
@@ -181,6 +182,23 @@ static int alsa_write_pre_select(struct sched *s, struct writer_node *wn)
        return 1;
 }
 
+static void xrun(snd_pcm_t *handle)
+{
+       snd_pcm_status_t *status;
+       int ret;
+       struct timeval tv, diff;
+
+       snd_pcm_status_alloca(&status);
+       ret = snd_pcm_status(handle, status);
+       if (ret < 0)
+               return;
+       if (snd_pcm_status_get_state(status) != SND_PCM_STATE_XRUN)
+               return;
+       snd_pcm_status_get_trigger_tstamp(status, &tv);
+       tv_diff(now, &tv, &diff);
+       PARA_WARNING_LOG("underrun: %lums\n", tv2ms(&diff));
+}
+
 static int alsa_write_post_select(__a_unused struct sched *s,
                struct writer_node *wn)
 {
@@ -213,11 +231,12 @@ static int alsa_write_post_select(__a_unused struct sched *s,
                wn->written += ret * pad->bytes_per_frame;
                return 1;
        }
-       PARA_WARNING_LOG("%s\n", snd_strerror(-ret));
        if (ret == -EPIPE) {
+               xrun(pad->handle);
                snd_pcm_prepare(pad->handle);
                return 0;
        }
+       PARA_WARNING_LOG("%s\n", snd_strerror(-ret));
        if (ret == -EAGAIN)
                return 0;
        return -E_ALSA_WRITE;