From 3bd65336222a4d00cefc4db5e74a7a96c07ab567 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 15 Jul 2010 10:40:21 +0200 Subject: [PATCH 07/13] aplay/arecord: Added hardware pause support (press SPACE or Enter) Signed-off-by: Jaroslav Kysela --- aplay/aplay.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 73 insertions(+), 5 deletions(-) diff --git a/aplay/aplay.c b/aplay/aplay.c index e1d8e6a..b5203a7 100644 --- a/aplay/aplay.c +++ b/aplay/aplay.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -102,6 +103,7 @@ static int avail_min = -1; static int start_delay = 0; static int stop_delay = 0; static int monotonic = 0; +static int can_pause = 0; static int verbose = 0; static int vumeter = VUMETER_NONE; static int buffer_pos = 0; @@ -1111,6 +1113,7 @@ static void set_params(void) } assert(err >= 0); monotonic = snd_pcm_hw_params_is_monotonic(params); + can_pause = snd_pcm_hw_params_can_pause(params); err = snd_pcm_hw_params(handle, params); if (err < 0) { error(_("Unable to install hw params:")); @@ -1182,7 +1185,7 @@ static void set_params(void) int i; err = snd_pcm_mmap_begin(handle, &areas, &offset, &size); if (err < 0) { - error("snd_pcm_mmap_begin problem: %s", snd_strerror(err)); + error(_("snd_pcm_mmap_begin problem: %s"), snd_strerror(err)); prg_exit(EXIT_FAILURE); } for (i = 0; i < hwparams.channels; i++) @@ -1194,6 +1197,65 @@ static void set_params(void) buffer_frames = buffer_size; /* for position test */ } +static void init_stdin(void) +{ + struct termios term; + long flags; + + if (fd == fileno(stdin)) + return; + flags = fcntl(fileno(stdin), F_GETFL); + if (flags < 0 || fcntl(fileno(stdin), F_SETFL, flags|O_NONBLOCK) < 0) + fprintf(stderr, _("stdin O_NONBLOCK flag setup failed\n")); + tcgetattr(fileno(stdin), &term); + term.c_lflag &= ~ICANON; + tcsetattr(fileno(stdin), TCSANOW, &term); +} + +static void do_pause(void) +{ + int err; + unsigned char b; + + if (!can_pause) { + fprintf(stderr, _("\rPAUSE command ignored (no hw support)\n")); + return; + } + err = snd_pcm_pause(handle, 1); + if (err < 0) { + error(_("pause push error: %s"), snd_strerror(err)); + return; + } + while (1) { + while (read(fileno(stdin), &b, 1) != 1); + if (b == ' ' || b == '\r') { + while (read(fileno(stdin), &b, 1) == 1); + err = snd_pcm_pause(handle, 0); + if (err < 0) + error(_("pause release error: %s"), snd_strerror(err)); + return; + } + } +} + +static void check_stdin(void) +{ + unsigned char b; + + if (fd != fileno(stdin)) { + while (read(fileno(stdin), &b, 1) == 1) { + if (b == ' ' || b == '\r') { + while (read(fileno(stdin), &b, 1) == 1); + fprintf(stderr, _("\r=== PAUSE === ")); + fflush(stderr); + do_pause(); + fprintf(stderr, " \r"); + fflush(stderr); + } + } + } +} + #ifndef timersub #define timersub(a, b, result) \ do { \ @@ -1589,12 +1651,13 @@ static ssize_t pcm_write(u_char *data, size_t count) while (count > 0) { if (test_position) do_test_position(); + check_stdin(); r = writei_func(handle, data, count); if (test_position) do_test_position(); if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) { if (!test_nowait) - snd_pcm_wait(handle, 1000); + snd_pcm_wait(handle, 100); } else if (r == -EPIPE) { xrun(); } else if (r == -ESTRPIPE) { @@ -1635,12 +1698,13 @@ static ssize_t pcm_writev(u_char **data, unsigned int channels, size_t count) bufs[channel] = data[channel] + offset * bits_per_sample / 8; if (test_position) do_test_position(); + check_stdin(); r = writen_func(handle, bufs, count); if (test_position) do_test_position(); if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) { if (!test_nowait) - snd_pcm_wait(handle, 1000); + snd_pcm_wait(handle, 100); } else if (r == -EPIPE) { xrun(); } else if (r == -ESTRPIPE) { @@ -1678,12 +1742,13 @@ static ssize_t pcm_read(u_char *data, size_t rcount) while (count > 0) { if (test_position) do_test_position(); + check_stdin(); r = readi_func(handle, data, count); if (test_position) do_test_position(); if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) { if (!test_nowait) - snd_pcm_wait(handle, 1000); + snd_pcm_wait(handle, 100); } else if (r == -EPIPE) { xrun(); } else if (r == -ESTRPIPE) { @@ -1721,12 +1786,13 @@ static ssize_t pcm_readv(u_char **data, unsigned int channels, size_t rcount) bufs[channel] = data[channel] + offset * bits_per_sample / 8; if (test_position) do_test_position(); + check_stdin(); r = readn_func(handle, bufs, count); if (test_position) do_test_position(); if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) { if (!test_nowait) - snd_pcm_wait(handle, 1000); + snd_pcm_wait(handle, 100); } else if (r == -EPIPE) { xrun(); } else if (r == -ESTRPIPE) { @@ -2361,6 +2427,7 @@ static void playback(char *name) fd = fileno(stdin); name = "stdin"; } else { + init_stdin(); if ((fd = open64(name, O_RDONLY, 0)) == -1) { perror(name); prg_exit(EXIT_FAILURE); @@ -2616,6 +2683,7 @@ static void capture(char *orig_name) if (count > fmt_rec_table[file_type].max_filesize) count = fmt_rec_table[file_type].max_filesize; } + init_stdin(); do { /* open a file to write */ -- 1.7.2.1