alsa_write: Print duration of buffer undderuns.
[paraslash.git] / alsa_write.c
index 679962e0e00f276700138bb83517e7fbd7ab8bb7..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"
@@ -80,18 +81,19 @@ static int alsa_init(struct private_alsa_write_data *pad,
                        pad->channels) < 0)
                return -E_CHANNEL_COUNT;
        if (snd_pcm_hw_params_set_rate_near(pad->handle, hwparams,
-                       &pad->samplerate, 0) < 0)
+                       &pad->samplerate, NULL) < 0)
                return -E_SET_RATE;
-       err = snd_pcm_hw_params_get_buffer_time_max(hwparams, &pad->buffer_time, 0);
+       err = snd_pcm_hw_params_get_buffer_time_max(hwparams,
+               &pad->buffer_time, NULL);
        if (err < 0 || !pad->buffer_time)
                return -E_GET_BUFFER_TIME;
        PARA_INFO_LOG("buffer time: %d\n", pad->buffer_time);
        if (snd_pcm_hw_params_set_buffer_time_near(pad->handle, hwparams,
-                       &pad->buffer_time, 0) < 0)
+                       &pad->buffer_time, NULL) < 0)
                return -E_SET_BUFFER_TIME;
        if (snd_pcm_hw_params(pad->handle, hwparams) < 0)
                return -E_HW_PARAMS;
-       snd_pcm_hw_params_get_period_size(hwparams, &period_size, 0);
+       snd_pcm_hw_params_get_period_size(hwparams, &period_size, NULL);
        snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size);
        PARA_INFO_LOG("buffer size: %lu, period_size: %lu\n", buffer_size,
                period_size);
@@ -180,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)
 {
@@ -212,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;