X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: f996b,ac750d31c700498f X-Google-Attributes: gidf996b,public X-Google-ArrivalTime: 1993-11-10 06:16:09 PST Path: gmd.de!xlink.net!howland.reston.ans.net!agate!doc.ic.ac.uk!daresbury!vj From: vj@gserv1.dl.ac.uk (Dave Hines) Newsgroups: alt.ascii-art Subject: slowcat.c: How to slow down animation Date: 10 Nov 1993 14:07:14 GMT Organization: SERC Daresbury Laboratory, Warrington, UK Lines: 139 Message-ID: References: Reply-To: D.Hines@daresbury.ac.uk NNTP-Posting-Host: dlsi.dl.ac.uk In-reply-to: blblam@cantor.math.uwaterloo.ca's message of Wed, 10 Nov 1993 11:23:40 GMT In article Bernard Lam wrote: > I'm just wondering how to slow down the animated files. When I view the > files using the 'cat' command in UNIX, it goes so fast that I can't see it. Since this group started I had the same problem. Here is a little filter I knocked together to solve the problem, and lets you specify the output rate. I've only tested it on a Sun sparcstation, under SunOS 4.1.3. It's not pretty, but it works here! Happy viewing ! Dave. -------------------------------- Cut here -------------------------------- /* slowcat.c */ #include #include #include /* * Cat files, but delay the characters. Useful for ASCII animations * when the line (eg xterm) is too fast. The output rate is in units * of characters per second, and defaults to 1000. * * Usage: slowcat [-r rate] [file...] */ extern int getopt(); /* Decodes option args. */ extern char *optarg; /* Required by getopt() */ extern int optind, opterr; /* Required by getopt() */ long interval; /* To wait between characters */ #define DEFAULT_RATE 1000 /* Characters per second */ #define M 1000000L /* us (tv_usec units) per second */ main(int argc, char **argv) { int rate = DEFAULT_RATE; register int c; while ((c = getopt(argc, argv, "r:")) != -1) { switch (c) { case 'r': /* Rate, chars per second */ if ((rate = atoi(optarg)) < 10) rate = 10; break; case '?': default: fputs("Usage: slowcat [-r rate] [file...]\n", stderr); exit(1); } } interval = M / rate; if (optind < argc) { for ( ; optind < argc; ++optind) { FILE *fp; if (fp = fopen(argv[optind], "r")) { scat(fp); fclose(fp); } else perror(argv[optind]); } } else scat(stdin); } scat(FILE *fp) { long uwait; /* Wait time in microseconds */ struct timeval time; /* long tv_sec, tv_usec; Secs & microsecs */ struct timeval next_due; register char c = getc(fp); /* Do first getc before gettimeofday so a */ /* delayed first read doesn't matter. */ /* Delayed data can come from pipes like: */ /* zcat animation.Z | slowcat */ if (gettimeofday(&next_due, NULL)) /* Keep next char due time here */ { perror("gettimeofday() failed"); exit(1); } time.tv_sec = 0; /* Initialise to force gettimeofday */ while (c != EOF) { if ((time.tv_sec < next_due.tv_sec) || /* Don't bother to get */ ((time.tv_sec == next_due.tv_sec) && /* time & wait when */ (time.tv_usec < next_due.tv_usec))) /* output is due */ { if (gettimeofday(&time, NULL)) /* Current time */ { perror("gettimeofday() failed"); exit(1); } /* * Calculate the number of microseconds to wait until the next * character is due. This can be negative if the char is late. */ if ((uwait = (next_due.tv_sec - time.tv_sec) * M + next_due.tv_usec - time.tv_usec) > 0) { fflush(stdout); /* We have to wait anyway... */ time.tv_sec = 0; time.tv_usec = uwait; if (select(0, NULL, NULL, NULL, &time) < 0) { perror("select failed"); exit(1); } } } putchar(c); if ((next_due.tv_usec += interval) >= M) { next_due.tv_usec -= M; ++next_due.tv_sec; } c = getc(fp); } } -- Snail: David Hines, Daresbury Lab, UUCP: D.Hines@daresbury Warrington, WA4 4AD, U.K. JANET: D.Hines@uk.ac.daresbury ('phone: +44 925 603357) Other: D.Hines@daresbury.ac.uk