mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-11-09 17:25:42 +01:00
aplay/arecord: fix underrun/overrun time calculation for monotonic clock
Also, add librt check to configure.in. Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
parent
3924a249dd
commit
641556d963
3 changed files with 78 additions and 15 deletions
|
@ -1,5 +1,7 @@
|
||||||
|
LIBRT = @LIBRT@
|
||||||
|
|
||||||
INCLUDES = -I$(top_srcdir)/include
|
INCLUDES = -I$(top_srcdir)/include
|
||||||
LDADD = $(LIBINTL)
|
LDADD = $(LIBINTL) $(LIBRT)
|
||||||
|
|
||||||
# debug flags
|
# debug flags
|
||||||
#LDFLAGS = -static
|
#LDFLAGS = -static
|
||||||
|
|
|
@ -101,12 +101,14 @@ static snd_pcm_uframes_t buffer_frames = 0;
|
||||||
static int avail_min = -1;
|
static int avail_min = -1;
|
||||||
static int start_delay = 0;
|
static int start_delay = 0;
|
||||||
static int stop_delay = 0;
|
static int stop_delay = 0;
|
||||||
|
static int monotonic = 0;
|
||||||
static int verbose = 0;
|
static int verbose = 0;
|
||||||
static int vumeter = VUMETER_NONE;
|
static int vumeter = VUMETER_NONE;
|
||||||
static int buffer_pos = 0;
|
static int buffer_pos = 0;
|
||||||
static size_t bits_per_sample, bits_per_frame;
|
static size_t bits_per_sample, bits_per_frame;
|
||||||
static size_t chunk_bytes;
|
static size_t chunk_bytes;
|
||||||
static int test_position = 0;
|
static int test_position = 0;
|
||||||
|
static int test_nowait = 0;
|
||||||
static snd_output_t *log;
|
static snd_output_t *log;
|
||||||
|
|
||||||
static int fd = -1;
|
static int fd = -1;
|
||||||
|
@ -188,7 +190,8 @@ _("Usage: %s [OPTION]... [FILE]...\n"
|
||||||
" --disable-channels disable automatic channel conversions\n"
|
" --disable-channels disable automatic channel conversions\n"
|
||||||
" --disable-format disable automatic format conversions\n"
|
" --disable-format disable automatic format conversions\n"
|
||||||
" --disable-softvol disable software volume control (softvol)\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);
|
, command);
|
||||||
printf(_("Recognized sample formats are:"));
|
printf(_("Recognized sample formats are:"));
|
||||||
for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
|
for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
|
||||||
|
@ -350,7 +353,8 @@ enum {
|
||||||
OPT_DISABLE_CHANNELS,
|
OPT_DISABLE_CHANNELS,
|
||||||
OPT_DISABLE_FORMAT,
|
OPT_DISABLE_FORMAT,
|
||||||
OPT_DISABLE_SOFTVOL,
|
OPT_DISABLE_SOFTVOL,
|
||||||
OPT_TEST_POSITION
|
OPT_TEST_POSITION,
|
||||||
|
OPT_TEST_NOWAIT
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
@ -389,6 +393,7 @@ int main(int argc, char *argv[])
|
||||||
{"disable-format", 0, 0, OPT_DISABLE_FORMAT},
|
{"disable-format", 0, 0, OPT_DISABLE_FORMAT},
|
||||||
{"disable-softvol", 0, 0, OPT_DISABLE_SOFTVOL},
|
{"disable-softvol", 0, 0, OPT_DISABLE_SOFTVOL},
|
||||||
{"test-position", 0, 0, OPT_TEST_POSITION},
|
{"test-position", 0, 0, OPT_TEST_POSITION},
|
||||||
|
{"test-nowait", 0, 0, OPT_TEST_NOWAIT},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
char *pcm_name = "default";
|
char *pcm_name = "default";
|
||||||
|
@ -570,6 +575,9 @@ int main(int argc, char *argv[])
|
||||||
case OPT_TEST_POSITION:
|
case OPT_TEST_POSITION:
|
||||||
test_position = 1;
|
test_position = 1;
|
||||||
break;
|
break;
|
||||||
|
case OPT_TEST_NOWAIT:
|
||||||
|
test_nowait = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, _("Try `%s --help' for more information.\n"), command);
|
fprintf(stderr, _("Try `%s --help' for more information.\n"), command);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1017,6 +1025,7 @@ static void set_params(void)
|
||||||
&buffer_frames);
|
&buffer_frames);
|
||||||
}
|
}
|
||||||
assert(err >= 0);
|
assert(err >= 0);
|
||||||
|
monotonic = snd_pcm_hw_params_is_monotonic(params);
|
||||||
err = snd_pcm_hw_params(handle, params);
|
err = snd_pcm_hw_params(handle, params);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
error(_("Unable to install hw params:"));
|
error(_("Unable to install hw params:"));
|
||||||
|
@ -1112,6 +1121,18 @@ do { \
|
||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#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 */
|
/* I/O error handler */
|
||||||
static void xrun(void)
|
static void xrun(void)
|
||||||
{
|
{
|
||||||
|
@ -1124,13 +1145,29 @@ static void xrun(void)
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) {
|
if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) {
|
||||||
struct timeval now, diff, tstamp;
|
if (monotonic) {
|
||||||
gettimeofday(&now, 0);
|
#ifdef HAVE_CLOCK_GETTIME
|
||||||
snd_pcm_status_get_trigger_tstamp(status, &tstamp);
|
struct timespec now, diff, tstamp;
|
||||||
timersub(&now, &tstamp, &diff);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
fprintf(stderr, _("%s!!! (at least %.3f ms long)\n"),
|
snd_pcm_status_get_trigger_htstamp(status, &tstamp);
|
||||||
stream == SND_PCM_STREAM_PLAYBACK ? _("underrun") : _("overrun"),
|
printf("AAA: %li %li\n" "BBB\n", tstamp.tv_sec, now.tv_nsec);
|
||||||
diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
|
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) {
|
if (verbose) {
|
||||||
fprintf(stderr, _("Status:\n"));
|
fprintf(stderr, _("Status:\n"));
|
||||||
snd_pcm_status_dump(status, log);
|
snd_pcm_status_dump(status, log);
|
||||||
|
@ -1409,7 +1446,8 @@ static void do_test_position(void)
|
||||||
delay < -4 * (snd_pcm_sframes_t)buffer_frames) {
|
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);
|
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) {
|
} 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)
|
if (test_position)
|
||||||
do_test_position();
|
do_test_position();
|
||||||
if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
|
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) {
|
} else if (r == -EPIPE) {
|
||||||
xrun();
|
xrun();
|
||||||
} else if (r == -ESTRPIPE) {
|
} 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)
|
if (test_position)
|
||||||
do_test_position();
|
do_test_position();
|
||||||
if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
|
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) {
|
} else if (r == -EPIPE) {
|
||||||
xrun();
|
xrun();
|
||||||
} else if (r == -ESTRPIPE) {
|
} else if (r == -ESTRPIPE) {
|
||||||
|
@ -1520,7 +1560,8 @@ static ssize_t pcm_read(u_char *data, size_t rcount)
|
||||||
if (test_position)
|
if (test_position)
|
||||||
do_test_position();
|
do_test_position();
|
||||||
if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
|
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) {
|
} else if (r == -EPIPE) {
|
||||||
xrun();
|
xrun();
|
||||||
} else if (r == -ESTRPIPE) {
|
} 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)
|
if (test_position)
|
||||||
do_test_position();
|
do_test_position();
|
||||||
if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
|
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) {
|
} else if (r == -EPIPE) {
|
||||||
xrun();
|
xrun();
|
||||||
} else if (r == -ESTRPIPE) {
|
} else if (r == -ESTRPIPE) {
|
||||||
|
|
19
configure.in
19
configure.in
|
@ -44,6 +44,23 @@ AM_CONDITIONAL(HAVE_MIXER, test "$have_mixer" = "yes")
|
||||||
AM_CONDITIONAL(HAVE_RAWMIDI, test "$have_rawmidi" = "yes")
|
AM_CONDITIONAL(HAVE_RAWMIDI, test "$have_rawmidi" = "yes")
|
||||||
AM_CONDITIONAL(HAVE_SEQ, test "$have_seq" = "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
|
dnl Disable alsamixer
|
||||||
CURSESINC=""
|
CURSESINC=""
|
||||||
CURSESLIB=""
|
CURSESLIB=""
|
||||||
|
@ -160,6 +177,8 @@ AC_SYS_LARGEFILE
|
||||||
|
|
||||||
SAVE_UTIL_VERSION
|
SAVE_UTIL_VERSION
|
||||||
|
|
||||||
|
AC_SUBST(LIBRT)
|
||||||
|
|
||||||
AC_OUTPUT(Makefile alsactl/Makefile alsactl/init/Makefile \
|
AC_OUTPUT(Makefile alsactl/Makefile alsactl/init/Makefile \
|
||||||
alsamixer/Makefile amidi/Makefile amixer/Makefile \
|
alsamixer/Makefile amidi/Makefile amixer/Makefile \
|
||||||
m4/Makefile po/Makefile.in \
|
m4/Makefile po/Makefile.in \
|
||||||
|
|
Loading…
Reference in a new issue