This diff adds an option to display variables periodically. Basically it replaces this usage:
while sleep 1; do audioctl play.errors; done by audioctl -w 1 play.errors The purpose of above audioctl commands is to debug underruns, so we don't want to fork a new process and reopen the device. This would trigger longer kernel code-paths and may cause additional underruns than the ones being investigated. OK? Index: audioctl.8 =================================================================== RCS file: /cvs/src/usr.bin/audioctl/audioctl.8,v retrieving revision 1.4 diff -u -p -r1.4 audioctl.8 --- audioctl.8 23 Apr 2020 00:16:59 -0000 1.4 +++ audioctl.8 9 Dec 2022 10:57:05 -0000 @@ -37,6 +37,7 @@ .Op Fl f Ar file .Nm audioctl .Op Fl n +.Op Fl w wait .Op Fl f Ar file .Ar name ... .Nm audioctl @@ -59,6 +60,12 @@ The default is Suppress printing of the variable name. .It Fl q Suppress all output when setting a variable. +.It Fl w Ar wait +Pause +.Ar wait +seconds between each display. +.Nm +will display variables until it is interrupted. .It Ar name Ns = Ns Ar value Attempt to set the specified variable .Ar name @@ -130,10 +137,10 @@ audio control devices audio devices .El .Sh EXAMPLES -Display the number of bytes of silence inserted during play buffer -underruns since device started: +Once per second, display the number of bytes of silence inserted +during play buffer underruns since device started: .Bd -literal -offset indent -# audioctl play.errors +# audioctl -w 1 play.errors .Ed .Pp Use signed 24-bit samples and 44100Hz sample rate: Index: audioctl.c =================================================================== RCS file: /cvs/src/usr.bin/audioctl/audioctl.c,v retrieving revision 1.43 diff -u -p -r1.43 audioctl.c --- audioctl.c 12 Jul 2021 15:09:19 -0000 1.43 +++ audioctl.c 9 Dec 2022 10:57:05 -0000 @@ -43,6 +43,7 @@ struct field { #define STR 2 #define ENC 3 int type; + int show; int set; } fields[] = { {"name", &rname.name, NULL, STR}, @@ -67,7 +68,7 @@ const char usagestr[] = " audioctl [-n] [-f file] name ...\n" " audioctl [-nq] [-f file] name=value ...\n"; -int fd, show_names = 1, quiet = 0; +int fd, show_names = 1, quiet = 0, period = 0; /* * parse encoding string (examples: s8, u8, s16, s16le, s24be ...) @@ -198,20 +199,9 @@ audio_main(int argc, char **argv) char *lhs, *rhs; int set = 0; - if (ioctl(fd, AUDIO_GETSTATUS, &rstatus) == -1) - err(1, "AUDIO_GETSTATUS"); - if (ioctl(fd, AUDIO_GETDEV, &rname) == -1) - err(1, "AUDIO_GETDEV"); - if (ioctl(fd, AUDIO_GETPAR, &rpar) == -1) - err(1, "AUDIO_GETPAR"); - if (ioctl(fd, AUDIO_GETPOS, &rpos) == -1) - err(1, "AUDIO_GETPOS"); if (argc == 0) { - for (f = fields; f->name != NULL; f++) { - printf("%s=", f->name); - print_field(f, f->raddr); - printf("\n"); - } + for (f = fields; f->name != NULL; f++) + f->show = 1; } AUDIO_INITPAR(&wpar); for (; argc > 0; argc--, argv++) { @@ -231,15 +221,38 @@ audio_main(int argc, char **argv) parse_field(f, f->waddr, rhs); f->set = 1; set = 1; - } else { + } else + f->show = 1; + } + + if (set && period) + errx(1, "Can't set variables periodically"); + + while (1) { + if (ioctl(fd, AUDIO_GETSTATUS, &rstatus) == -1) + err(1, "AUDIO_GETSTATUS"); + if (ioctl(fd, AUDIO_GETDEV, &rname) == -1) + err(1, "AUDIO_GETDEV"); + if (ioctl(fd, AUDIO_GETPAR, &rpar) == -1) + err(1, "AUDIO_GETPAR"); + if (ioctl(fd, AUDIO_GETPOS, &rpos) == -1) + err(1, "AUDIO_GETPOS"); + for (f = fields; f->name != NULL; f++) { + if (!f->show) + continue; if (show_names) printf("%s=", f->name); print_field(f, f->raddr); printf("\n"); } + if (period == 0) + break; + sleep(period); } + if (!set) return; + if (ioctl(fd, AUDIO_SETPAR, &wpar) == -1) err(1, "AUDIO_SETPAR"); if (ioctl(fd, AUDIO_GETPAR, &wpar) == -1) @@ -261,9 +274,10 @@ int main(int argc, char **argv) { char *path = "/dev/audioctl0"; + const char *errstr; int c; - while ((c = getopt(argc, argv, "anf:q")) != -1) { + while ((c = getopt(argc, argv, "anf:qw:")) != -1) { switch (c) { case 'a': /* ignored, compat */ break; @@ -275,6 +289,11 @@ main(int argc, char **argv) break; case 'q': quiet = 1; + break; + case 'w': + period = strtonum(optarg, 1, INT_MAX, &errstr); + if (errstr != NULL) + errx(1, "period is %s: %s", errstr, optarg); break; default: fputs(usagestr, stderr);