update build scripts
[enigma2-plugins.git] / moviecut / src_cc / mcut.cc
1  /* Copyright (C) 2007, 2008, 2009 Anders Holst
2   *
3   * This program is free software; you can redistribute it and/or
4   * modify it under the terms of the GNU General Public License as
5   * published by the Free Software Foundation; either version 2, or
6   * (at your option) any later version.
7   * 
8   * This program is distributed in the hope that it will be useful,
9   * but WITHOUT ANY WARRANTY; without even the implied warranty of
10   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11   * GNU General Public License for more details.
12   * 
13   * You should have received a copy of the GNU General Public License
14   * along with this software; see the file COPYING.  If not, write to
15   * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16   * Boston, MA 02111-1307 USA
17   */
18
19 #define _LARGEFILE64_SOURCE
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <byteswap.h>
28
29 #define LEN 24064
30
31 static off64_t time_offset;
32 static off64_t size_offset;
33 static off64_t curr_size_offset;
34
35 int use_leadin = 1;
36 int use_leadout = 1;
37
38 inline int absless(long long int x, int lim)
39 {
40   return (x<lim && x>-lim);
41 }
42
43 double strtotime(char* str)
44 {
45   int i=0, t1, tt;
46   char *p1, *p2;
47   double tmp;
48   p1 = str;
49   tt = strtol(p1, &p2, 10);
50   if (p1==p2) return -1.0;
51   while (*p2 == ':' && i<2) {
52     i++;
53     if (p2-p1>2) return -1.0;
54     p1 = p2+1;
55     t1 = strtol(p1, &p2, 10);
56     if (p1==p2) return -1.0;
57     tt = 60*tt + t1;
58   }
59   if (i>0 && p2-p1>2) return -1.0;
60   if (*p2 == 0) return (double)tt;
61   if (*p2 != '.') return -1.0;
62   p1 = p2+1;
63   t1 = strtol(p1, &p2, 10);
64   for (i=0, tmp=1.0; i<(p2-p1); tmp*=0.1, i++);
65   return (double)tt + tmp*t1;
66 }
67
68 double inttotime(unsigned int t1, unsigned int t2)
69 {
70   return (bswap_32(t2)*1.1111111111111112e-05 + bswap_32(t1)*47721.858844444447);
71 }
72
73 double lltotime(long long int t)
74 {
75   return ((unsigned int)(t&0xffffffff)*1.1111111111111112e-05) + ((unsigned int)(t>>32)*47721.858844444447);
76 }
77
78 void timetoint(double tm, unsigned int& t1, unsigned int& t2)
79 {
80   double tmp=tm/47721.858844444447;
81   t1 = bswap_32((unsigned int)tmp);
82   t2 = bswap_32((unsigned int)((tm - t1*47721.858844444447)*90000));
83 }
84
85 void swapbuf(off64_t*& buf0, off64_t*& buf1)
86 {
87   off64_t* buf;
88   buf = buf0;
89   buf0 = buf1;
90   buf1 = buf;
91 }
92
93 int readbufinternal(int f, off64_t*& buf)
94 {
95   if (read(f, buf, 16) != 16)
96     return 0;
97   buf[0] = (off64_t)bswap_64((unsigned long long int)buf[0]);
98   buf[1] = (off64_t)bswap_64((unsigned long long int)buf[1]);
99   return 1;
100 }
101
102 void writebufinternal(int f, off64_t* buf)
103 {
104   off64_t tbuf[2];
105   tbuf[0] = (off64_t)bswap_64((unsigned long long int)buf[0] - curr_size_offset);
106   tbuf[1] = (off64_t)bswap_64((unsigned long long int)buf[1]);
107   write(f, tbuf, 16);
108 }
109
110 void movesc(int fs, int fso, off64_t off, int beg)
111 {
112   static off64_t* buf = 0;
113   static off64_t lastoff;
114   static int endp;
115   if (fs == -1 || fso == -1)
116     return;
117   if (!buf) {
118     buf = new off64_t[2];
119     lastoff = 0;
120     endp = 0;
121   }
122   if (off < lastoff) {
123     lseek(fs, 0, SEEK_SET);
124     lastoff = 0;
125     endp = 0;
126   }
127   if (off == lastoff || endp)
128     return;
129   lastoff = off;
130   if (!beg && !endp)
131     writebufinternal(fso, buf);
132   while (readbufinternal(fs, buf)) {
133     if (buf[0] >= off)
134       return;
135     if (!beg)
136       writebufinternal(fso, buf);
137   }
138   endp = 1;
139 }
140
141 off64_t readoff(int fa, int fao, int fs, int fso, double t, int beg, double& tr)
142 {
143   static off64_t* buf0 = 0;
144   static off64_t* buf1 = 0;
145   static off64_t lastreturn;
146   static double last;
147   static int endp;
148   off64_t sizetmp;
149   double tt, lt;
150   if (!buf0) {
151     buf0 = new off64_t[2];
152     buf1 = new off64_t[2];
153     if (!(readbufinternal(fa, buf0) && readbufinternal(fa, buf1))) {
154       printf("The corresponding \".ap\"-file is empty.\n");
155       exit(8);
156     }
157     time_offset = buf0[1];
158     if (buf1[1] > buf0[1] && buf1[1] - buf0[1] < 450000)
159       time_offset -= (buf1[1]-buf0[1])*buf0[0]/(buf1[0]-buf0[0]);
160     else if (buf1[1] > buf0[1] || buf0[1] - buf1[1] > 45000)
161       time_offset = buf1[1];
162     size_offset = buf0[0];
163     lastreturn = 0;
164     last = 0.0;
165     endp = 0;
166   }
167   if (t < last && t != -1.0) {
168     sizetmp = buf0[0];
169     lseek(fa, 0, SEEK_SET);
170     readbufinternal(fa, buf0);
171     readbufinternal(fa, buf1);
172     time_offset = buf0[1];
173     if (buf1[1] > buf0[1] && buf1[1] - buf0[1] < 450000)
174       time_offset -= (buf1[1]-buf0[1])*buf0[0]/(buf1[0]-buf0[0]);
175     else if (buf1[1] > buf0[1] || buf0[1] - buf1[1] > 45000)
176       time_offset = buf1[1];
177     size_offset += buf0[0] - sizetmp;
178     lastreturn = 0;
179     last = 0.0;
180     endp = 0;
181   }
182   if (t == last || endp == 1) {
183     return lastreturn;
184   }
185   if (!beg)
186     writebufinternal(fao, buf0);
187   last = t;
188   lt = lltotime(buf0[1] - time_offset);
189   if (buf0[1] - buf1[1] > 0 && buf0[1] - buf1[1] <= 45000)
190     tt = lt, buf1[1] = buf0[1];
191   else
192     tt = lltotime(buf1[1] - time_offset);
193   sizetmp = buf0[0];
194   while (tt < t || t == -1.0) {
195     swapbuf(buf0, buf1);
196     if (!readbufinternal(fa, buf1))
197       endp = 1;
198     if (!beg)
199       writebufinternal(fao, buf0);
200     if (endp)
201       break;
202     if (buf0[1] - buf1[1] > 45000 || buf1[1] - buf0[1] > 450000) {
203       if (absless(buf1[1] + ((long long int)1)<<33 - buf0[1], 450000))
204         time_offset -= ((long long int)1)<<33;
205       else
206         time_offset += buf1[1] - buf0[1];
207     }
208     lt = tt;
209     if (buf0[1] - buf1[1] > 0 && buf0[1] - buf1[1] <= 45000)
210       tt = lt, buf1[1] = buf0[1];
211     else
212       tt = lltotime(buf1[1] - time_offset);
213   }
214   if (endp) {
215     tr = tt;
216   } else if (beg ? (lt == tt || (t-lt > tt-t && tt-t<0.18)) : (t-lt >= tt-t || t-lt>0.18)) {
217     swapbuf(buf0, buf1);
218     if (!readbufinternal(fa, buf1))
219       endp = 1;
220     if (buf0[1] - buf1[1] > 0 && buf0[1] - buf1[1] <= 45000)
221       buf1[1] = buf0[1];
222     if (!beg)
223       writebufinternal(fao, buf0);
224     tr = tt;
225   } else {
226     tr = lt;
227   }
228   if (beg)
229     size_offset += buf0[0] - sizetmp;
230   lastreturn = buf0[0];
231   return lastreturn;
232 }
233
234 int framepid(char* buf, int pos)
235 {
236   return ((buf[pos+1] & 0x1f) << 8) + buf[pos+2];
237 }
238
239 int framesearch_f(char* buf, int start, int stop, int pid, int& tp)
240 {
241   char* p;
242   int pos = -1;
243   for (p = buf+start; p < buf+stop-5; p++)
244     if (p[0]==0 && p[1]==0 && p[2]==1) {
245       if (p[3]==0) {
246         pos = ((p - buf)/188)*188;
247         if (pid == -1 || framepid(buf, pos) == pid) {
248           tp = (p[5]>>3)&7;
249           return pos;
250         }
251       } else if (p[3]==0x09) {
252         pos = ((p - buf)/188)*188;
253         if ((buf[pos+1] & 0x40) && (pid == -1 || framepid(buf, pos) == pid)) {
254           tp = (p[4] >> 5) + 1;
255           return pos;
256         }
257       }
258     }
259   return -1;
260 }
261
262 int framesearch_b(char* buf, int start, int stop, int pid)
263 {
264   char* p;
265   int pos = -1;
266   for (p = buf+stop-1; p >= buf+start+3; p--)
267     if (p[-1]==1 && p[-2]==0 && p[-3]==0) {
268       if (p[0]==0) {
269         pos = ((p - buf)/188)*188;
270         if (pid == -1 || framepid(buf, pos) == pid)
271           return pos;
272       } else if (p[0]==0x09) {
273         pos = ((p - buf)/188)*188;
274         if ((buf[pos+1] & 0x40) && (pid == -1 || framepid(buf, pos) == pid))
275           return pos;
276       }
277     }
278   return -1;
279 }
280
281 int transfer_start(int f_ts, int f_out, off64_t n1, off64_t& n1ret)
282 {
283   off64_t num;
284   int pos, tmp;
285   char buf[LEN];
286   if (use_leadin) {
287     num = 0;
288     tmp = 0;
289     do {
290       num += LEN;
291       if (num > n1)
292         tmp = LEN - (int)(num - n1), num = n1;
293       else
294         tmp = LEN;
295       lseek64(f_ts, n1 - num, SEEK_SET);
296       if (read(f_ts, buf, tmp) != tmp) return 1;
297     } while ((pos = framesearch_b(buf, 0, tmp, -1)) == -1 && num < n1);
298     if (pos != -1) {
299       if (write(f_out, buf+pos, tmp-pos) != tmp-pos) return 1;
300       n1ret = n1 - (num - pos);
301       size_offset -= (num - pos);
302       num -= tmp;
303       while (num > 0) {
304         if (read(f_ts, buf, LEN) != LEN) return 1;
305         if (write(f_out, buf, LEN) != LEN) return 1;
306         num -= LEN;
307       }
308     } else {
309       n1ret = n1;
310     }
311     return 0;
312   }
313   else {
314     lseek64(f_ts, n1, SEEK_SET);
315     n1ret = n1;
316     return 0;
317   }
318 }
319
320 int transfer_rest(int f_ts, int f_out, off64_t n1, off64_t n2, off64_t& n2ret)
321 {
322   off64_t i;
323   int num, pos, st, pid, tp, tmp;
324   char buf[LEN];
325   static off64_t lastn2 = -1, lastn2ret;
326   if (n1 == lastn2) {
327     i = lastn2ret;
328     lseek64(f_ts, i, SEEK_SET);
329   } else
330     i = n1;
331   for (; i+LEN<=n2; i+=LEN) {
332     if (read(f_ts, buf, LEN) != LEN) return 1;
333     if (write(f_out, buf, LEN) != LEN) return 1;
334   }
335   if (use_leadout) {
336     num = read(f_ts, buf, LEN);
337     pid = framepid(buf, n2-i);
338     st = (i < n2 ? n2-i : 0);
339     tmp = -st;
340     st += 188;
341     while ((pos = framesearch_f(buf, st, num, pid, tp)) == -1 ? num == LEN : tp == 3) {
342       if (pos != -1) {
343         st = pos + 188;
344       } else {
345         if (write(f_out, buf, LEN) != LEN) return 1;
346         num = read(f_ts, buf, LEN);
347         st = 0;
348         tmp += LEN;
349       }
350     }
351     if (st && num < st)
352       return 1;
353     else if (pos == -1) {
354       if (write(f_out, buf, num) != num) return 1;
355       tmp += num;
356       size_offset -= tmp;
357     } else {
358       if (write(f_out, buf, pos) != pos) return 1;
359       tmp += pos;
360       size_offset -= tmp;
361     }
362     lastn2 = n2;
363     lastn2ret = n2ret = n2 + tmp;
364     return 0;
365   } else {
366     if (i < n2) {
367       if (read(f_ts, buf, n2-i) != n2-i) return 1;
368       if (write(f_out, buf, n2-i) != n2-i) return 1;
369     }
370     lastn2 = lastn2ret = n2ret = n2;
371     return 0;
372   }
373 }
374
375 int donextinterval1(int fc, int fco, int fa, int fao, int fs, int fso, int fts, int ftso)
376 {
377   static int n = -1;
378   static double tlast, toff = 0.0;
379   static off64_t c2;
380   off64_t c1, c1ret, c2ret;
381   double ttmp;
382   unsigned int buf[3];
383   unsigned int tmp, lcheck=0;
384   if (n==0)
385     return 0;
386   else if (n==-1) {
387     n = lseek(fc, 0, SEEK_END) / 12;
388     lseek(fc, 0, SEEK_SET);
389     while (1) {
390       if (n == 0)
391         return 0;
392       read(fc, buf, 12);
393       n--;
394       tmp = bswap_32(buf[2]);
395       if (tmp == 1) {
396         c1 = readoff(fa, fao, fs, fso, 0.0, 1, toff);
397         if (transfer_start(fts, ftso, c1, c1ret)) return -1;
398         curr_size_offset = size_offset;
399         movesc(fs, fso, c1ret, 1);
400         c2 = readoff(fa, fao, fs, fso, inttotime(buf[0], buf[1]), 0, tlast);
401         if (transfer_rest(fts, ftso, c1, c2, c2ret)) return -1;
402         movesc(fs, fso, c2ret, 0);
403         printf("Interval: %lld - %lld\n", c1ret, c2ret);
404         // move all passed marks
405         lseek(fc, 0, SEEK_SET);
406         read(fc, buf, 12);
407         while (bswap_32(buf[2]) != 1) {
408           write(fco, buf, 12);
409           read(fc, buf, 12);
410         }
411         return 1;
412       } else if (tmp == 0) {
413         c1 = readoff(fa, fao, fs, fso, inttotime(buf[0], buf[1]), 1, toff);
414         if (transfer_start(fts, ftso, c1, c1ret)) return -1;
415         curr_size_offset = size_offset;
416         movesc(fs, fso, c1ret, 1);
417         if (lcheck) {
418           buf[0] = buf[1] = 0;
419           write(fco, buf, 12);
420         }
421         break;
422       } else if (tmp == 3)
423         lcheck = 1;
424     }
425   } else {
426     while (1) {
427       read(fc, buf, 12);
428       n--;
429       tmp = bswap_32(buf[2]);
430       if (tmp == 0) {
431         c1 = readoff(fa, fao, fs, fso, inttotime(buf[0], buf[1]), 1, ttmp);
432         use_leadin = 0;
433         if (c1 != c2) {
434           if (transfer_start(fts, ftso, c1, c1ret)) return -1;
435           curr_size_offset = size_offset;
436         } else {
437           c1ret = c2ret;
438           size_offset = curr_size_offset;
439         }
440         movesc(fs, fso, c1ret, 1);
441         toff += ttmp - tlast;
442         break;
443       } else if (tmp == 3) {
444         timetoint(tlast-toff, buf[0], buf[1]);
445         write(fco, buf, 12);
446       }
447       if (n == 0)
448         return 0;
449     }
450   }
451   while (1) {
452     if (n == 0) {
453       c2 = readoff(fa, fao, fs, fso, -1.0, 0, tlast);
454       if (transfer_rest(fts, ftso, c1, c2, c2ret)) return -1;
455       movesc(fs, fso, c2ret, 0);
456       printf("Interval: %lld - %lld\n", c1ret, c2ret);
457       return 1;
458     }
459     read(fc, buf, 12);
460     n--;
461     tmp = bswap_32(buf[2]);
462     if (tmp == 1) {
463       c2 = readoff(fa, fao, fs, fso, inttotime(buf[0], buf[1]), 0, tlast);
464       if (transfer_rest(fts, ftso, c1, c2, c2ret)) return -1;
465       movesc(fs, fso, c2ret, 0);
466       printf("Interval: %lld - %lld\n", c1ret, c2ret);
467       return 1;
468     } else if (tmp != 0) {
469       timetoint(inttotime(buf[0], buf[1])-toff, buf[0], buf[1]);
470       write(fco, buf, 12);
471     }
472   }
473   return 0;
474 }
475
476 int donextinterval2(int barg, int earg, char* argv[], int fc, int fco, int fa, int fao, int fs, int fso, int fts, int ftso)
477 {
478   static int n = -1, i, lio = -1, lcheck=0;
479   static double tlast = 0.0, toff = 0.0;
480   static off64_t c2 = -1;
481   off64_t c1, c1ret, c2ret;
482   double ttmp, ttmp2;
483   int j, io = -1;
484   unsigned int buf[3];
485   unsigned int buff[3];
486   unsigned int tmp;
487   if (i>=earg) {
488     if (!lcheck && n>0) {
489       lseek(fc, 0, SEEK_SET);
490       for (j=0; j<n; j++) {
491         read(fc, buf, 12);
492         tmp = bswap_32(buf[2]);
493         if (tmp == 3) {
494           timetoint(tlast-toff, buf[0], buf[1]);
495           write(fco, buf, 12);
496           break;
497         }
498       }
499     }
500     return 0;
501   }
502   if (n==-1) {
503     i = barg;
504     n = (fc != -1 ? lseek(fc, 0, SEEK_END) / 12 : 0);
505   }
506   c1 = readoff(fa, fao, fs, fso, strtotime(argv[i]), 1, ttmp);
507   if (c1 != c2) {
508     if (transfer_start(fts, ftso, c1, c1ret)) return -1;
509     curr_size_offset = size_offset;
510   } else {
511     c1ret = c2ret;
512     size_offset = curr_size_offset;
513   }
514   movesc(fs, fso, c1ret, 1);
515   use_leadin = 0;
516   toff += ttmp - tlast;
517   c2 = readoff(fa, fao, fs, fso, strtotime(argv[i+1]), 0, tlast);
518   if (transfer_rest(fts, ftso, c1, c2, c2ret)) return -1;
519   movesc(fs, fso, c2ret, 0);
520   printf("Interval: %lld - %lld\n", c1ret, c2ret);
521   if (n > 0) lseek(fc, 0, SEEK_SET);
522   for (j=0; j<n; j++) {
523     read(fc, buf, 12);
524     tmp = bswap_32(buf[2]);
525     ttmp2=inttotime(buf[0], buf[1]);
526     if (tmp == 3) {
527       if (!lcheck) {
528         if (ttmp2 <= ttmp) {
529           timetoint(ttmp-toff, buf[0], buf[1]);
530           write(fco, buf, 12);
531           lcheck = 1;
532         } else if (ttmp2 <= tlast) {
533           timetoint(ttmp2-toff, buf[0], buf[1]);
534           write(fco, buf, 12);
535           lcheck = 1;
536         }
537       }
538     } else if (ttmp2 >= ttmp && ttmp2 <= tlast) {
539       if (tmp < 2) {
540         if (lio != io && lio != -1) {
541           buff[2] = bswap_32(io);
542           timetoint(ttmp-toff, buff[0], buff[1]);
543           write(fco, buff, 12);
544         }
545         lio = io = tmp;
546       }
547       timetoint(ttmp2-toff, buf[0], buf[1]);
548       write(fco, buf, 12);
549     } else if (tmp < 2) {
550       io = tmp;
551     }
552   }
553   i+=2;
554   return 1;
555 }
556
557 char* makefilename(const char* base, const char* pre, const char* ext, const char* post, int delext = 0)
558 {
559   static char buf[256];
560   int len1, len2, len3;
561   len1 = strlen(base);
562   len2 = (pre ? strlen(pre) : 0);
563   len3 = (ext ? strlen(ext) : 0);
564   strcpy(buf, base);
565   if (ext && len1>=len3 && !strcmp(base+len1-len3,ext))
566     len1 -= len3;
567   if (pre)
568     strcpy(buf+len1, pre);
569   if (ext && !delext)
570     strcpy(buf+len1+len2, ext);
571   if (post)
572     strcpy(buf+len1+len2+(delext ? 0 : len3), post);
573   return buf;
574 }
575
576 void copymeta(int n, int f1, int f2, const char* title, const char* suff, const char* descr)
577
578   int i, j, k;
579   char* buf = new char[n];
580   read(f1, buf, n);
581   for (i=0; i<n; i++)
582     if (buf[i] == 10)
583       break;
584   write(f2, buf, i);
585   if (i == n) return;
586   for (j=i+1; j<n; j++)
587     if (buf[j] == 10)
588       break;
589   if (title) {
590     write(f2, buf+i, 1);
591     for (k=0; title[k] && title[k] != 10; k++);
592     write(f2, title, k);
593   } else {
594     write(f2, buf+i, j-i);
595     if (suff && j-i>1)
596       write(f2, suff, strlen(suff));
597   }
598   if (j == n) return;
599   i = j;
600   for (j=i+1; j<n; j++)
601     if (buf[j] == 10)
602       break;
603   if (descr) {
604     write(f2, buf+i, 1);
605     for (k=0; descr[k] && descr[k] != 10; k++);
606     write(f2, descr, k);
607   } else {
608     write(f2, buf+i, j-i);
609   }
610   if (j < n)
611     write(f2, buf+j, n-j);
612   delete [] buf;
613 }
614
615 void copysmallfile(int n, int f1, int f2)
616
617   char* buf = new char[n];
618   read(f1, buf, n);
619   write(f2, buf, n);
620   delete [] buf;
621 }
622
623 int main(int argc, char* argv[])
624 {
625   int f_ts, f_out, f_cuts, f_cutsout, f_ap, f_apout, f_sc, f_scout, f_meta, f_metaout, f_eit, f_eitout;
626   char* tmpname;
627   const char* suff = 0;
628   char* inname = 0;
629   char* outname = 0;
630   char* title = 0;
631   char* descr = 0;
632   int cutarg = 0, cutargend = 0;
633   int replace = 0, metafailed = 0;
634   int i, j, ok, bad = 0;
635   double t1, t2;
636   struct stat statbuf;
637   struct stat64 statbuf64;
638
639   for (i=1; i<argc; i++) {
640     if (!strcmp(argv[i], "-r"))
641       replace = 1;
642     else if (!strcmp(argv[i], "-o")) {
643       if (i == argc-1) {
644         bad = 1;
645         break;
646       }
647       outname = argv[++i];
648     } else if (!strcmp(argv[i], "-n")) {
649       if (i == argc-1) {
650         bad = 1;
651         break;
652       }
653       title = argv[++i];
654     } else if (!strcmp(argv[i], "-d")) {
655       if (i == argc-1) {
656         bad = 1;
657         break;
658       }
659       descr = argv[++i];
660     } else if (!strcmp(argv[i], "-c")) {
661       cutarg = ++i;
662       for (j=i; j<argc; j+=2) {
663         t1 = strtotime(argv[j]);
664         t2 = (j+1<argc ? strtotime(argv[j+1]) : -1.0);
665         if (t1 < 0 || t2 < 0)
666           break;
667         else if (t1 > t2) {
668           printf("Bad time interval: %s - %s\n", argv[j], argv[j+1]);
669           bad = 1;
670           break;
671         }
672       }
673       cutargend = i = j;
674       if (bad)
675         break;
676     } else if (*argv[i] == '-' && (*(argv[i]+1) == 0 ||*(argv[i]+2) == 0)) {
677       bad = 1;
678       break;
679     } else if (!inname)
680       inname = argv[i];
681     else {
682       bad = 1;
683       break;
684     }
685   }
686   if (argc == 1 || bad) {
687     printf("Usage: mcut [-r] [-o output_ts_file] [-n title] [-d description] ts_file [-c start1 end1 [start2 end2] ... ]\n");
688     printf("   -r : Replace (= remove) the original movie.\n");
689     printf("   -o : Filename of resulting movie (defaults to the original name appended by \" cut\", unless -r is given).\n");
690     printf("   -n : Title of resulting movie.\n");
691     printf("   -d : Description of resulting movie.\n");
692     printf("   -c : A sequence of starttime and endtime pairs. Each time is given as hour:min:sec. The portion between start and end is retained (i.e. not cut away).\n");
693     exit(1);
694   }
695   if (outname) {
696     suff = 0;
697   } else {
698     outname = inname;
699     suff = (replace ? "_" : " cut");
700   }
701   tmpname = makefilename(inname, 0, ".ts", 0);
702   f_ts = open(tmpname, O_RDONLY | O_LARGEFILE);
703   if (f_ts == -1) {
704     printf("Failed to open input stream file \"%s\"\n", tmpname);
705     exit(2);
706   }
707   tmpname = makefilename(inname, 0, ".ts", ".cuts");
708   f_cuts = open(tmpname, O_RDONLY);
709   if (f_cuts == -1 && !cutarg) {
710     printf("Failed to open input cuts file \"%s\"\n", tmpname);
711     close(f_ts);
712     exit(3);
713   }
714   tmpname = makefilename(inname, 0, ".ts", ".ap");
715   f_ap = open(tmpname, O_RDONLY);
716   if (f_ap == -1) {
717     printf("Failed to open input ap file \"%s\"\n", tmpname);
718     close(f_ts);
719     if (f_cuts != -1) close(f_cuts);
720     exit(4);
721   }
722   tmpname = makefilename(inname, 0, ".ts", ".sc");
723   f_sc = open(tmpname, O_RDONLY);
724
725   if (fstat64(f_ts, &statbuf64)) {
726     printf("Failed to stat input stream file.\n");
727     close(f_ts);
728     close(f_ap);
729     if (f_sc != -1) close(f_sc);
730     if (f_cuts != -1) close(f_cuts);
731     exit(2);
732   }
733   tmpname = makefilename(outname, suff, ".ts", 0);
734   f_out = open(tmpname, O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, statbuf64.st_mode & 0xfff);
735   if (f_out == -1) {
736     printf("Failed to open output stream file \"%s\"\n", tmpname);
737     close(f_ts);
738     close(f_ap);
739     if (f_sc != -1) close(f_sc);
740     if (f_cuts != -1) close(f_cuts);
741     exit(5);
742   }
743   if (f_cuts != -1 && fstat(f_cuts, &statbuf)) {
744     if (!cutarg) {
745       printf("Failed to stat input cuts file.\n");
746       close(f_ts);
747       close(f_out);
748       close(f_ap);
749       if (f_sc != -1) close(f_sc);
750       close(f_cuts);
751       unlink(makefilename(outname, suff, ".ts", 0));
752       exit(3);
753     } else {
754       close(f_cuts);
755       f_cuts = -1;
756     }
757   }
758   if (f_cuts != -1) {
759     tmpname = makefilename(outname, suff, ".ts", ".cuts");
760     f_cutsout = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, statbuf.st_mode & 0xfff);
761     if (f_cutsout == -1) {
762       printf("Failed to open output cuts file \"%s\"\n", tmpname);
763       close(f_ts);
764       close(f_out);
765       close(f_ap);
766       if (f_sc != -1) close(f_sc);
767       close(f_cuts);
768       unlink(makefilename(outname, suff, ".ts", 0));
769       exit(6);
770     }
771   } else
772     f_cutsout = -1;
773   if (fstat(f_ap, &statbuf)) {
774     printf("Failed to stat input ap file.\n");
775     close(f_ts);
776     close(f_out);
777     close(f_ap);
778     if (f_sc != -1) close(f_sc);
779     if (f_cuts != -1) {
780       close(f_cuts);
781       close(f_cutsout);
782       unlink(makefilename(outname, suff, ".ts", ".cuts"));
783     }
784     unlink(makefilename(outname, suff, ".ts", 0));
785     exit(4);
786   }
787   tmpname = makefilename(outname, suff, ".ts", ".ap");
788   f_apout = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, statbuf.st_mode & 0xfff);
789   if (f_apout == -1) {
790     printf("Failed to open output ap file \"%s\"\n", tmpname);
791     close(f_ts);
792     close(f_out);
793     close(f_ap);
794     if (f_sc != -1) close(f_sc);
795     if (f_cuts != -1) {
796       close(f_cuts);
797       close(f_cutsout);
798       unlink(makefilename(outname, suff, ".ts", ".cuts"));
799     }
800     unlink(makefilename(outname, suff, ".ts", 0));
801     exit(7);
802   }
803   if (f_sc != -1 && fstat(f_sc, &statbuf)) {
804     close(f_sc);
805     f_sc = -1;
806   }
807   if (f_sc != -1) {
808     tmpname = makefilename(outname, suff, ".ts", ".sc");
809     f_scout = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, statbuf.st_mode & 0xfff);
810     if (f_scout == -1) {
811       printf("Failed to open output sc file \"%s\"\n", tmpname);
812       close(f_ts);
813       close(f_out);
814       close(f_ap);
815       close(f_apout);
816       close(f_sc);
817       if (f_cuts != -1) {
818         close(f_cuts);
819         close(f_cutsout);
820         unlink(makefilename(outname, suff, ".ts", ".cuts"));
821       }
822       unlink(makefilename(outname, suff, ".ts", 0));
823       unlink(makefilename(outname, suff, ".ts", ".ap"));
824       exit(7);
825     }
826   }
827   if (cutarg)
828     ok = donextinterval2(cutarg, cutargend, argv, f_cuts, f_cutsout, f_ap, f_apout, f_sc, f_scout, f_ts, f_out);
829   else
830     ok = donextinterval1(f_cuts, f_cutsout, f_ap, f_apout, f_sc, f_scout, f_ts, f_out);
831   if (!ok) {
832     printf("There are no cuts specified. Leaving the movie as it is.\n");
833     close(f_ts);
834     close(f_out);
835     close(f_ap);
836     close(f_apout);
837     if (f_cuts != -1) {
838       close(f_cuts);
839       close(f_cutsout);
840       unlink(makefilename(outname, suff, ".ts", ".cuts"));
841     }
842     if (f_sc != -1) {
843       close(f_sc);
844       close(f_scout);
845       unlink(makefilename(outname, suff, ".ts", ".sc"));
846     }
847     unlink(makefilename(outname, suff, ".ts", 0));
848     unlink(makefilename(outname, suff, ".ts", ".ap"));
849     exit(9);
850   }
851
852   while (ok > 0) {
853     if (cutarg)
854       ok = donextinterval2(cutarg, cutargend, argv, f_cuts, f_cutsout, f_ap, f_apout, f_sc, f_scout, f_ts, f_out);
855     else
856       ok = donextinterval1(f_cuts, f_cutsout, f_ap, f_apout, f_sc, f_scout, f_ts, f_out);
857   }
858
859   close(f_ts);
860   close(f_out);
861   close(f_ap);
862   close(f_apout);
863   if (f_cuts != -1) {
864     close(f_cuts);
865     close(f_cutsout);
866   }
867   if (f_sc != -1) {
868     close(f_sc);
869     close(f_scout);
870   }
871   if (ok < 0) {
872     printf("Copying %s failed, read/write error.\n", makefilename(inname, 0, ".ts", 0));
873     unlink(makefilename(outname, suff, ".ts", 0));
874     unlink(makefilename(outname, suff, ".ts", ".ap"));
875     if (f_cuts != -1)
876       unlink(makefilename(outname, suff, ".ts", ".cuts"));
877     if (f_sc != -1)
878       unlink(makefilename(outname, suff, ".ts", ".sc"));
879     exit(10);
880   }
881
882   if (!replace) {
883     tmpname = makefilename(inname, 0, ".ts", ".eit", 1);
884     f_eit = open(tmpname, O_RDONLY);
885     if (f_eit != -1) {
886       if (fstat(f_eit, &statbuf))
887         close(f_eit);
888       else {
889         tmpname = makefilename(outname, suff, ".ts", ".eit", 1);
890         f_eitout = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, statbuf.st_mode & 0xfff);
891         if (f_eitout == -1)
892           close(f_eit);
893         else {
894           copysmallfile((int)statbuf.st_size, f_eit, f_eitout);
895           close(f_eit);
896           close(f_eitout);
897         }
898       }
899     }
900   }
901
902   metafailed = 0;
903   tmpname = makefilename(inname, 0, ".ts", ".meta");
904   f_meta = open(tmpname, O_RDONLY);
905   if (f_meta == -1) {
906     metafailed = 1;
907   } else if (fstat(f_meta, &statbuf)) {
908     metafailed = 1;
909     close(f_meta);
910   } else {
911     tmpname = makefilename(outname, suff, ".ts", ".meta");
912     f_metaout = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, statbuf.st_mode & 0xfff);
913     if (f_metaout == -1) {
914       metafailed = 1;
915       close(f_meta);
916     } else {
917       copymeta((int)statbuf.st_size, f_meta, f_metaout, title, (replace ? 0 : suff), descr);
918       close(f_meta);
919       close(f_metaout);
920     }
921   }
922
923   if (replace) {
924     if (suff) {
925       tmpname = makefilename(inname, 0, ".ts", 0);
926       tmpname = strcpy(new char[strlen(tmpname)+1], tmpname);
927       unlink(tmpname);
928       rename(makefilename(outname, suff, ".ts", 0), tmpname);
929       tmpname = makefilename(inname, 0, ".ts", ".ap");
930       tmpname = strcpy(new char[strlen(tmpname)+1], tmpname);
931       unlink(tmpname);
932       rename(makefilename(outname, suff, ".ts", ".ap"), tmpname);
933       if (f_sc != -1) {
934         tmpname = makefilename(inname, 0, ".ts", ".sc");
935         tmpname = strcpy(new char[strlen(tmpname)+1], tmpname);
936         unlink(tmpname);
937         rename(makefilename(outname, suff, ".ts", ".sc"), tmpname);
938       }
939       if (f_cuts != -1) {
940         tmpname = makefilename(inname, 0, ".ts", ".cuts");
941         tmpname = strcpy(new char[strlen(tmpname)+1], tmpname);
942         unlink(tmpname);
943         rename(makefilename(outname, suff, ".ts", ".cuts"), tmpname);
944       }
945       if (!metafailed) {
946         tmpname = makefilename(inname, 0, ".ts", ".meta");
947         tmpname = strcpy(new char[strlen(tmpname)+1], tmpname);
948         unlink(tmpname);
949         rename(makefilename(outname, suff, ".ts", ".meta"), tmpname);
950       }
951     } else {
952       unlink(makefilename(inname, 0, ".ts", 0));
953       unlink(makefilename(inname, 0, ".ts", ".ap"));
954       if (f_sc != -1)
955         unlink(makefilename(inname, 0, ".ts", ".sc"));
956       if (f_cuts != -1)
957         unlink(makefilename(inname, 0, ".ts", ".cuts"));
958       tmpname = makefilename(inname, 0, ".ts", ".eit", 1);
959       tmpname = strcpy(new char[strlen(tmpname)+1], tmpname);
960       rename(tmpname, makefilename(outname, 0, ".ts", ".eit", 1));
961       if (!metafailed) 
962         unlink(makefilename(inname, 0, ".ts", ".meta"));
963       else {
964         tmpname = makefilename(inname, 0, ".ts", ".meta");
965         tmpname = strcpy(new char[strlen(tmpname)+1], tmpname);
966         rename(tmpname, makefilename(outname, 0, ".ts", ".meta"));
967       }
968     }
969   }
970 }
971