#!/usr/bin/perl -w

# This is subtitle-offset-modificator version 0.1, a simple script
# that allows to change the timestamp of a Subtitle file.
#
# Web : http://thomas.enix.org/wakka.php?wiki=SubtitleOffsetModificator
#
#   Copyright (C) 2004 Thomas Petazzoni
#                      thomas.petazzoni@enix.org
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

if (($#ARGV+1) != 3)
{
    die "Usage : subtitle-offset-modificator.pl infile outfile offset\n";
}


open SUBTITLEIN, $ARGV[0] or die $ARGV[0] . " : " . $!;
open SUBTITLEOUT, ">$ARGV[1]" or die $ARGV[1] . " : " . $!;

my ($offset_direction, $offset_hour, $offset_min, $offset_sec, $offset_frame);

if($ARGV[2] =~ m/^([\+\-]{0,1})([0-9]{2}):([0-9]{2}):([0-9]{2}),([0-9]{3})$/)
{
    if($1 eq "+" || $1 eq "")
    {
	$offset_direction = 0;
    }
    else
    {
	$offset_direction = 1;
    }

    $offset_hour  = $2;
    $offset_min   = $3;
    $offset_sec   = $4;
    $offset_frame = $5;
}
else
{
    die "offset must be in the format hh:mm:ss,fff eventually with a minus sign before\n";
}

if($offset_direction == 0)
{
    print "Incrementing";
}
else
{
    print "Decrementing";
}

print " from " . $offset_hour . "h " . $offset_min . "m " . $offset_sec . "s " . $offset_frame . " frames\n";

sub compute
{
    my $initial_val = $_[0];
    my $added_val   = $_[1];
    my $carry       = $_[2];
    my $max_val     = $_[3];
    my $decrement   = $_[4];

    my $ret_val;
    my $ret_carry;

    if($decrement == 0)
    {
	$ret_val   = $initial_val + $added_val + $carry;
	$ret_carry = 0;

	if($ret_val > $max_val)
	{
	    $ret_val -= ($max_val + 1);
	    $ret_carry = 1;
	}
    }
    else
    {
	$ret_val   = $initial_val - $added_val - $carry;
	$ret_carry = 0;

	if($ret_val < 0)
	{
	    $ret_val += ($max_val + 1);
	    $ret_carry = 1;
	}
    }

    return ($ret_val, $ret_carry);
}

while(<SUBTITLEIN>)
{
    chomp;

    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})$/)
    {
	($frame_s, $carry)  = compute($4, $offset_frame, 0, 999, $offset_direction);
	($second_s, $carry) = compute($3, $offset_sec, $carry, 59, $offset_direction);
	($minute_s, $carry) = compute($2, $offset_min, $carry, 59, $offset_direction);
	($hour_s, $carry)   = compute($1, $offset_hour, $carry, 23, $offset_direction);

	if($carry != 0)
	{
	    die "Overflow !\n";
	}

	($frame_e, $carry)  = compute($8, $offset_frame, 0, 999, $offset_direction);
	($second_e, $carry) = compute($7, $offset_sec, $carry, 59, $offset_direction);
	($minute_e, $carry) = compute($6, $offset_min, $carry, 59, $offset_direction);
	($hour_e, $carry)   = compute($5, $offset_hour, $carry, 23, $offset_direction);

	if($carry != 0)
	{
	    die "Overflow !\n";
	}

	printf(SUBTITLEOUT "%.2d:%.2d:%.2d,%.3d --> %.2d:%.2d:%.2d,%.3d\n",
	       $hour_s, $minute_s, $second_s, $frame_s,
	       $hour_e, $minute_e, $second_e, $frame_e);
    }
    else
    {
	print SUBTITLEOUT $_ . "\n";
    }
}
