blind-repeat.c (2419B)
1 /* See LICENSE file for copyright and license details. */ 2 #include "common.h" 3 4 USAGE("([-f] count | 'inf') [file]") 5 6 static size_t count = 0; 7 static int inf; 8 static struct stream stream; 9 10 static int 11 repeat_regular_file(void) 12 { 13 stream.ptr = 0; 14 while (inf || count--) { 15 fadvise_sequential(stream.fd, (off_t)(stream.headlen), 0); 16 elseek(stream.fd, (off_t)(stream.headlen), SEEK_SET, stream.file); 17 if (esend_stream(&stream, STDOUT_FILENO, NULL)) 18 return -1; 19 } 20 return 0; 21 } 22 23 static int 24 repeat_regular_file_framewise(void) 25 { 26 size_t i; 27 off_t off = (off_t)(stream.headlen); 28 stream.ptr = 0; 29 echeck_dimensions(&stream, WIDTH | HEIGHT | LENGTH, "input"); 30 for (;; off += (off_t)(stream.frame_size)) { 31 for (i = 0; i < count; i++) { 32 elseek(stream.fd, off, SEEK_SET, stream.file); 33 if (!esend_frames(&stream, STDOUT_FILENO, 1, "<stdout>")) 34 return 0; 35 } 36 } 37 } 38 39 static int 40 repeat_stdin(void) 41 { 42 size_t ptr = stream.ptr; 43 size_t size = MAX(ptr, BUFSIZ); 44 char *buf = memcpy(emalloc(size), stream.buf, ptr); 45 egetfile(STDIN_FILENO, &buf, &ptr, &size, "<stdout>"); 46 while (inf || count--) 47 if (writeall(STDOUT_FILENO, buf, ptr)) 48 return free(buf), -1; 49 return free(buf), 0; 50 } 51 52 static int 53 repeat_stdin_framewise(void) 54 { 55 char *buf; 56 size_t i; 57 echeck_dimensions(&stream, WIDTH | HEIGHT, "input"); 58 buf = emalloc(stream.frame_size); 59 while (eread_frame(&stream, buf)) 60 for (i = 0; i < count; i++) 61 if (writeall(STDOUT_FILENO, buf, stream.frame_size)) 62 return free(buf), -1; 63 return free(buf), 0; 64 } 65 66 int 67 main(int argc, char *argv[]) 68 { 69 int framewise = 0; 70 71 ARGBEGIN { 72 case 'f': 73 framewise = 1; 74 break; 75 default: 76 usage(); 77 } ARGEND; 78 79 if (argc < 1 || argc > 2) 80 usage(); 81 82 if ((inf = !strcmp(argv[0], "inf"))) { 83 if (framewise) 84 usage(); 85 einf_check_fd(STDOUT_FILENO, "<stdout>"); 86 } else { 87 count = etozu_arg("the count", argv[0], 0, SIZE_MAX); 88 } 89 90 if (argv[1] && !strcmp(argv[1], "-")) 91 argv[1] = NULL; 92 93 eopen_stream(&stream, argv[1]); 94 if (stream.frames && count > SIZE_MAX / stream.frames) 95 eprintf("%s: video is too long\n", stream.file); 96 stream.frames *= count; 97 fprint_stream_head(stdout, &stream); 98 efflush(stdout, "<stdout>"); 99 100 if (!argv[1] 101 ? (framewise ? repeat_stdin_framewise() : repeat_stdin()) 102 : (framewise ? repeat_regular_file_framewise(): repeat_regular_file())) 103 if (!inf || errno != EPIPE) 104 eprintf("write <stdout>:"); 105 106 close(stream.fd); 107 return 0; 108 }