]> git.alsa-project.org Git - alsa-utils.git/commitdiff
aplay/arecord: fix underrun/overrun time calculation for monotonic clock
authorJaroslav Kysela <perex@perex.cz>
Wed, 8 Apr 2009 07:22:16 +0000 (09:22 +0200)
committerJaroslav Kysela <perex@perex.cz>
Wed, 8 Apr 2009 07:22:16 +0000 (09:22 +0200)
Also, add librt check to configure.in.

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
aplay/Makefile.am
aplay/aplay.c
configure.in

index 60811de2542870c219e65e0162b5f75ce1e3ec9e..92323d1b1220648c10b82ef09183a9312d167591 100644 (file)
@@ -1,5 +1,7 @@
+LIBRT = @LIBRT@
+
 INCLUDES = -I$(top_srcdir)/include
-LDADD = $(LIBINTL)
+LDADD = $(LIBINTL) $(LIBRT)
 
 # debug flags
 #LDFLAGS = -static
index 837e46a97fbcccb4d0a75fae5e7afaef7e75b1fc..90824d0ceb739ed8421a888a3236e04298a3a769 100644 (file)
@@ -101,12 +101,14 @@ static snd_pcm_uframes_t buffer_frames = 0;
 static int avail_min = -1;
 static int start_delay = 0;
 static int stop_delay = 0;
+static int monotonic = 0;
 static int verbose = 0;
 static int vumeter = VUMETER_NONE;
 static int buffer_pos = 0;
 static size_t bits_per_sample, bits_per_frame;
 static size_t chunk_bytes;
 static int test_position = 0;
+static int test_nowait = 0;
 static snd_output_t *log;
 
 static int fd = -1;
@@ -188,7 +190,8 @@ _("Usage: %s [OPTION]... [FILE]...\n"
 "    --disable-channels  disable automatic channel conversions\n"
 "    --disable-format    disable automatic format conversions\n"
 "    --disable-softvol   disable software volume control (softvol)\n"
-"    --test-position     test ring buffer position\n")
+"    --test-position     test ring buffer position\n"
+"    --test-nowait       do not wait for ring buffer - eats whole CPU\n")
                , command);
        printf(_("Recognized sample formats are:"));
        for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
@@ -350,7 +353,8 @@ enum {
        OPT_DISABLE_CHANNELS,
        OPT_DISABLE_FORMAT,
        OPT_DISABLE_SOFTVOL,
-       OPT_TEST_POSITION
+       OPT_TEST_POSITION,
+       OPT_TEST_NOWAIT
 };
 
 int main(int argc, char *argv[])
@@ -389,6 +393,7 @@ int main(int argc, char *argv[])
                {"disable-format", 0, 0, OPT_DISABLE_FORMAT},
                {"disable-softvol", 0, 0, OPT_DISABLE_SOFTVOL},
                {"test-position", 0, 0, OPT_TEST_POSITION},
+               {"test-nowait", 0, 0, OPT_TEST_NOWAIT},
                {0, 0, 0, 0}
        };
        char *pcm_name = "default";
@@ -570,6 +575,9 @@ int main(int argc, char *argv[])
                case OPT_TEST_POSITION:
                        test_position = 1;
                        break;
+               case OPT_TEST_NOWAIT:
+                       test_nowait = 1;
+                       break;
                default:
                        fprintf(stderr, _("Try `%s --help' for more information.\n"), command);
                        return 1;
@@ -1017,6 +1025,7 @@ static void set_params(void)
                                                             &buffer_frames);
        }
        assert(err >= 0);
+       monotonic = snd_pcm_hw_params_is_monotonic(params);
        err = snd_pcm_hw_params(handle, params);
        if (err < 0) {
                error(_("Unable to install hw params:"));
@@ -1112,6 +1121,18 @@ do { \
 } while (0)
 #endif
 
+#ifndef timermsub
+#define        timermsub(a, b, result) \
+do { \
+       (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+       (result)->tv_nsec = (a)->tv_nsec - (b)->tv_nsec; \
+       if ((result)->tv_nsec < 0) { \
+               --(result)->tv_sec; \
+               (result)->tv_nsec += 1000000000L; \
+       } \
+} while (0)
+#endif
+
 /* I/O error handler */
 static void xrun(void)
 {
@@ -1124,13 +1145,29 @@ static void xrun(void)
                exit(EXIT_FAILURE);
        }
        if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) {
-               struct timeval now, diff, tstamp;
-               gettimeofday(&now, 0);
-               snd_pcm_status_get_trigger_tstamp(status, &tstamp);
-               timersub(&now, &tstamp, &diff);
-               fprintf(stderr, _("%s!!! (at least %.3f ms long)\n"),
-                       stream == SND_PCM_STREAM_PLAYBACK ? _("underrun") : _("overrun"),
-                       diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
+               if (monotonic) {
+#ifdef HAVE_CLOCK_GETTIME
+                       struct timespec now, diff, tstamp;
+                       clock_gettime(CLOCK_MONOTONIC, &now);
+                       snd_pcm_status_get_trigger_htstamp(status, &tstamp);
+                       printf("AAA: %li %li\n" "BBB\n", tstamp.tv_sec, now.tv_nsec);
+                       timermsub(&now, &tstamp, &diff);
+                       fprintf(stderr, _("%s!!! (at least %.3f ms long)\n"),
+                               stream == SND_PCM_STREAM_PLAYBACK ? _("underrun") : _("overrun"),
+                               diff.tv_sec * 1000 + diff.tv_nsec / 10000000.0);
+#else
+                       fprintf(stderr, "%s !!!\n", _("underrun"));
+#endif
+               } else {
+                       struct timeval now, diff, tstamp;
+                       gettimeofday(&now, 0);
+                       snd_pcm_status_get_trigger_tstamp(status, &tstamp);
+                       printf("AAA: %li %li\n", tstamp.tv_sec, now.tv_sec);
+                       timersub(&now, &tstamp, &diff);
+                       fprintf(stderr, _("%s!!! (at least %.3f ms long)\n"),
+                               stream == SND_PCM_STREAM_PLAYBACK ? _("underrun") : _("overrun"),
+                               diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
+               }
                if (verbose) {
                        fprintf(stderr, _("Status:\n"));
                        snd_pcm_status_dump(status, log);
@@ -1409,7 +1446,8 @@ static void do_test_position(void)
            delay < -4 * (snd_pcm_sframes_t)buffer_frames) {
          fprintf(stderr, "Suspicious buffer position (%i total): avail = %li, delay = %li, buffer = %li\n", ++counter, (long)avail, (long)delay, (long)buffer_frames);
        } else if (verbose) {
-         fprintf(stderr, "Buffer position: %li/%li (%li)\n", (long)avail, (long)delay, (long)buffer_frames);
+               if (avail != 0)
+                       fprintf(stderr, "Buffer position: %li/%li (%li)\n", (long)avail, (long)delay, (long)buffer_frames);
        }
 }
 
@@ -1433,7 +1471,8 @@ static ssize_t pcm_write(u_char *data, size_t count)
                if (test_position)
                        do_test_position();
                if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
-                       snd_pcm_wait(handle, 1000);
+                       if (!test_nowait)
+                               snd_pcm_wait(handle, 1000);
                } else if (r == -EPIPE) {
                        xrun();
                } else if (r == -ESTRPIPE) {
@@ -1478,7 +1517,8 @@ static ssize_t pcm_writev(u_char **data, unsigned int channels, size_t count)
                if (test_position)
                        do_test_position();
                if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
-                       snd_pcm_wait(handle, 1000);
+                       if (!test_nowait)
+                               snd_pcm_wait(handle, 1000);
                } else if (r == -EPIPE) {
                        xrun();
                } else if (r == -ESTRPIPE) {
@@ -1520,7 +1560,8 @@ static ssize_t pcm_read(u_char *data, size_t rcount)
                if (test_position)
                        do_test_position();
                if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
-                       snd_pcm_wait(handle, 1000);
+                       if (!test_nowait)
+                               snd_pcm_wait(handle, 1000);
                } else if (r == -EPIPE) {
                        xrun();
                } else if (r == -ESTRPIPE) {
@@ -1562,7 +1603,8 @@ static ssize_t pcm_readv(u_char **data, unsigned int channels, size_t rcount)
                if (test_position)
                        do_test_position();
                if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
-                       snd_pcm_wait(handle, 1000);
+                       if (!test_nowait)
+                               snd_pcm_wait(handle, 1000);
                } else if (r == -EPIPE) {
                        xrun();
                } else if (r == -ESTRPIPE) {
index 0facec4e1c2a0106f4186847bcb74374df0c9071..d26ae6519cf879a01a3ecafe0c52e31f4591c599 100644 (file)
@@ -44,6 +44,23 @@ AM_CONDITIONAL(HAVE_MIXER, test "$have_mixer" = "yes")
 AM_CONDITIONAL(HAVE_RAWMIDI, test "$have_rawmidi" = "yes")
 AM_CONDITIONAL(HAVE_SEQ, test "$have_seq" = "yes")
 
+dnl Check for librt
+LIBRT=""
+AC_MSG_CHECKING(for librt)
+AC_ARG_WITH(librt,
+  AS_HELP_STRING([--with-librt], [Use librt for monotonic clock (default = yes)]),
+  [ have_librt="$withval" ], [ have_librt="yes" ])
+if test "$have_librt" = "yes"; then
+  AC_CHECK_LIB([rt], [clock_gettime], [HAVE_LIBRT="yes"])
+  if test "$HAVE_LIBRT" = "yes" ; then
+    LIBRT="-lrt"
+    AC_DEFINE([HAVE_LIBRT], 1, [Have librt])
+    AC_DEFINE([HAVE_CLOCK_GETTIME], 1, [Have clock gettime])
+  fi
+else
+  AC_MSG_RESULT(no)
+fi
+
 dnl Disable alsamixer
 CURSESINC=""
 CURSESLIB=""
@@ -160,6 +177,8 @@ AC_SYS_LARGEFILE
 
 SAVE_UTIL_VERSION
 
+AC_SUBST(LIBRT)
+
 AC_OUTPUT(Makefile alsactl/Makefile alsactl/init/Makefile \
          alsamixer/Makefile amidi/Makefile amixer/Makefile \
          m4/Makefile po/Makefile.in \