canplayer: add interactive single-step frame processing mode

Wait for ENTER key to process next CAN frame from the log file.

As the new line is printed each time this approach doesn't win a
design price. But this feature is very uncommon and setting the
terminal into some raw mode to get the raw keyboard hits would
introduce a big code overhead to handle e.g. CTRL-C signals which
is a vital functionality for canplayer.

Link: https://github.com/linux-can/can-utils/issues/280
Suggested-by: https://github.com/nico0481
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
pull/300/head
Oliver Hartkopp 2021-04-17 13:01:29 +02:00
parent 553f0d282b
commit aaa7fd215f
1 changed files with 18 additions and 1 deletions

View File

@ -87,6 +87,8 @@ void print_usage(char *prg)
"(Use 'i' for infinite loop - default: %d)\n", DEFAULT_LOOPS);
fprintf(stderr, " -t (ignore timestamps: "
"send frames immediately)\n");
fprintf(stderr, " -i (interactive - wait "
"for ENTER key to process next frame)\n");
fprintf(stderr, " -g <ms> (gap in milli "
"seconds - default: %d ms)\n", DEFAULT_GAP);
fprintf(stderr, " -s <s> (skip gaps in "
@ -244,6 +246,7 @@ int main(int argc, char **argv)
FILE *infile = stdin;
unsigned long gap = DEFAULT_GAP;
int use_timestamps = 1;
int interactive = 0; /* wait for ENTER keypress to process next frame */
static int verbose, opt, delay_loops;
static unsigned long skipgap;
static int loopback_disable = 0;
@ -254,7 +257,7 @@ int main(int argc, char **argv)
int eof, txmtu, i, j;
char *fret;
while ((opt = getopt(argc, argv, "I:l:tg:s:xv?")) != -1) {
while ((opt = getopt(argc, argv, "I:l:tig:s:xv?")) != -1) {
switch (opt) {
case 'I':
infile = fopen(optarg, "r");
@ -278,6 +281,10 @@ int main(int argc, char **argv)
use_timestamps = 0;
break;
case 'i':
interactive = 1;
break;
case 'g':
gap = strtoul(optarg, NULL, 10);
break;
@ -320,6 +327,12 @@ int main(int argc, char **argv)
printf("%d loops\n", loops);
}
/* ignore timestamps from logfile when in single step keypress mode */
if (interactive) {
use_timestamps = 0;
printf("interactive mode: press ENTER to process next CAN frame ...\n");
}
sleep_ts.tv_sec = gap / 1000;
sleep_ts.tv_nsec = (gap % 1000) * 1000000;
@ -413,6 +426,10 @@ int main(int argc, char **argv)
while ((!use_timestamps) ||
(frames_to_send(&today_tv, &diff_tv, &log_tv) < 0)) {
/* wait for keypress to process next frame */
if (interactive)
getchar();
/* log_tv/device/ascframe are valid here */
if (strlen(device) >= IFNAMSIZ) {