1#!/usr/local/bin/perl -w
2
3# This is subtitle-offset-modificator version 0.1, a simple script
4# that allows to change the timestamp of a Subtitle file.
5#
6# Web : http://thomas.enix.org/wakka.php?wiki=SubtitleOffsetModificator
7#
8#   Copyright (C) 2004 Thomas Petazzoni
9#                      thomas.petazzoni@enix.org
10#
11#   This program is free software; you can redistribute it and/or modify
12#   it under the terms of the GNU General Public License as published by
13#   the Free Software Foundation; either version 2 of the License, or
14#   (at your option) any later version.
15#
16#   This program is distributed in the hope that it will be useful,
17#   but WITHOUT ANY WARRANTY; without even the implied warranty of
18#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19#   GNU General Public License for more details.
20#
21#   You should have received a copy of the GNU General Public License
22#   along with this program; if not, write to the Free Software
23#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24
25if (($#ARGV+1) != 3)
26{
27    die "Usage : subtitle-offset-modificator.pl infile outfile offset\n";
28}
29
30
31open SUBTITLEIN, $ARGV[0] or die $ARGV[0] . " : " . $!;
32open SUBTITLEOUT, ">$ARGV[1]" or die $ARGV[1] . " : " . $!;
33
34my ($offset_direction, $offset_hour, $offset_min, $offset_sec, $offset_frame);
35
36if($ARGV[2] =~ m/^([\+\-]{0,1})([0-9]{2}):([0-9]{2}):([0-9]{2}),([0-9]{3})$/)
37{
38    if($1 eq "+" || $1 eq "")
39    {
40	$offset_direction = 0;
41    }
42    else
43    {
44	$offset_direction = 1;
45    }
46
47    $offset_hour  = $2;
48    $offset_min   = $3;
49    $offset_sec   = $4;
50    $offset_frame = $5;
51}
52else
53{
54    die "offset must be in the format hh:mm:ss,fff eventually with a minus sign before\n";
55}
56
57if($offset_direction == 0)
58{
59    print "Incrementing";
60}
61else
62{
63    print "Decrementing";
64}
65
66print " from " . $offset_hour . "h " . $offset_min . "m " . $offset_sec . "s " . $offset_frame . " frames\n";
67
68sub compute
69{
70    my $initial_val = $_[0];
71    my $added_val   = $_[1];
72    my $carry       = $_[2];
73    my $max_val     = $_[3];
74    my $decrement   = $_[4];
75
76    my $ret_val;
77    my $ret_carry;
78
79    if($decrement == 0)
80    {
81	$ret_val   = $initial_val + $added_val + $carry;
82	$ret_carry = 0;
83
84	if($ret_val > $max_val)
85	{
86	    $ret_val -= ($max_val + 1);
87	    $ret_carry = 1;
88	}
89    }
90    else
91    {
92	$ret_val   = $initial_val - $added_val - $carry;
93	$ret_carry = 0;
94
95	if($ret_val < 0)
96	{
97	    $ret_val += ($max_val + 1);
98	    $ret_carry = 1;
99	}
100    }
101
102    return ($ret_val, $ret_carry);
103}
104
105while(<SUBTITLEIN>)
106{
107    chomp;
108
109    if(m/^([0-9]{2}):([0-9]{2}):([0-9]{2}),([0-9]{3}) --> ([0-9]{2}):([0-9]{2}):([0-9]{2}),([0-9]{3})$/)
110    {
111	($frame_s, $carry)  = compute($4, $offset_frame, 0, 999, $offset_direction);
112	($second_s, $carry) = compute($3, $offset_sec, $carry, 59, $offset_direction);
113	($minute_s, $carry) = compute($2, $offset_min, $carry, 59, $offset_direction);
114	($hour_s, $carry)   = compute($1, $offset_hour, $carry, 23, $offset_direction);
115
116	if($carry != 0)
117	{
118	    die "Overflow !\n";
119	}
120
121	($frame_e, $carry)  = compute($8, $offset_frame, 0, 999, $offset_direction);
122	($second_e, $carry) = compute($7, $offset_sec, $carry, 59, $offset_direction);
123	($minute_e, $carry) = compute($6, $offset_min, $carry, 59, $offset_direction);
124	($hour_e, $carry)   = compute($5, $offset_hour, $carry, 23, $offset_direction);
125
126	if($carry != 0)
127	{
128	    die "Overflow !\n";
129	}
130
131	printf(SUBTITLEOUT "%.2d:%.2d:%.2d,%.3d --> %.2d:%.2d:%.2d,%.3d\n",
132	       $hour_s, $minute_s, $second_s, $frame_s,
133	       $hour_e, $minute_e, $second_e, $frame_e);
134    }
135    else
136    {
137	print SUBTITLEOUT $_ . "\n";
138    }
139}
140