blind-reverse.c - blind - suckless command-line video editing utility
 (HTM) git clone git://git.suckless.org/blind
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       blind-reverse.c (2377B)
       ---
            1 /* See LICENSE file for copyright and license details. */
            2 #include "common.h"
            3 
            4 USAGE("[-i] file")
            5 
            6 static void
            7 to_stdout(struct stream *stream)
            8 {
            9         size_t ptr, end, n;
           10         char buf[BUFSIZ];
           11 
           12         while (stream->frames--) {
           13                 ptr = stream->frames * stream->frame_size + stream->headlen;
           14                 end = ptr + stream->frame_size;
           15                 while (ptr < end) {
           16                         if (!(n = epread(stream->fd, buf, MIN(sizeof(buf), end - ptr),
           17                                          (off_t)ptr, stream->file)))
           18                                 eprintf("%s: file is shorter than expected\n", stream->file);
           19                         ptr += n;
           20                         ewriteall(STDOUT_FILENO, buf, n, "<stdout>");
           21                 }
           22         }
           23 }
           24 
           25 static void
           26 elseek_set(int fd, off_t offset, const char *fname)
           27 {
           28         off_t r = elseek(fd, offset, SEEK_SET, fname);
           29         if (r != offset)
           30                 eprintf("%s: file is shorter than expected\n", fname);
           31 }
           32 
           33 static void
           34 epread_frame(struct stream *stream, char *buf, off_t off)
           35 {
           36         stream->ptr = stream->xptr = 0;
           37         elseek_set(stream->fd, off, stream->file);
           38         eread_frame(stream, buf);
           39 }
           40 
           41 static void
           42 epwrite_frame(struct stream *stream, char *buf, off_t off)
           43 {
           44         elseek_set(stream->fd, off, stream->file);
           45         ewriteall(stream->fd, buf, stream->frame_size, stream->file);
           46 }
           47 
           48 static void
           49 in_place(struct stream *stream)
           50 {
           51         size_t f, fm = stream->frames - 1;
           52         off_t pa, pb;
           53         char *bufa, *bufb;
           54 
           55         bufa = emalloc(stream->frame_size);
           56         bufb = emalloc(stream->frame_size);
           57 
           58         for (f = 0; f < stream->frames >> 1; f++) {
           59                 pa = (off_t)f        * (off_t)(stream->frame_size) + (off_t)(stream->headlen);
           60                 pb = (off_t)(fm - f) * (off_t)(stream->frame_size) + (off_t)(stream->headlen);
           61 
           62                 epread_frame(stream, bufa, pa);
           63                 epread_frame(stream, bufb, pb);
           64 
           65                 epwrite_frame(stream, bufa, pb);
           66                 epwrite_frame(stream, bufb, pa);
           67         }
           68 
           69         free(bufa);
           70         free(bufb);
           71 }
           72 
           73 int
           74 main(int argc, char *argv[])
           75 {
           76         struct stream stream;
           77         int inplace = 0;
           78 
           79         ARGBEGIN {
           80         case 'i':
           81                 inplace = 1;
           82                 break;
           83         default:
           84                 usage();
           85         } ARGEND;
           86         
           87         if (argc != 1)
           88                 usage();
           89 
           90         stream.file = argv[0];
           91         stream.fd = eopen(stream.file, inplace ? O_RDWR : O_RDONLY);
           92         einit_stream(&stream);
           93         if (!inplace) {
           94                 fprint_stream_head(stdout, &stream);
           95                 efflush(stdout, "<stdout>");
           96         }
           97         echeck_dimensions(&stream, WIDTH | HEIGHT, NULL);
           98         if (stream.frames * stream.frame_size > (size_t)SSIZE_MAX - stream.headlen)
           99                 eprintf("%s: video is too large\n", stream.file);
          100 
          101         fadvise_random(stream.fd, 0, 0);
          102 
          103         (inplace ? in_place : to_stdout)(&stream);
          104         close(stream.fd);
          105         return 0;
          106 }