#!/usr/bin/perl

use constant VERZE => '1.11';   #verze programu
use constant MIN_DELKA => 0.3; #minimalni delka titulku v sekundach
#use diagnostics;
use locale; #pro funkci -g
use Getopt::Std;


########################################################################
# 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 at http://www.gnu.org    #
######################################################################## 


&getopts( "hvcrs:fm:eo:ng:t:i:l:" );

#volby programu:
#-h        help
#-v        version
#-c        check - kontrola casovani titulku
#-r        repair - oprava casovani titulku
#-s cislo  shift - posun titulku o cislo sekund +/-
#-f        force shift - pri posunu titulku do zaporu je nezapise=osekavani titulku
#-m cislo  movement - zmena dynamiky titulku - prodlouzeni/zkraceni
#-e        empty - vynechavani titulku, ktere neobsahuji zadny text
#-o nazev  output - moznost zadat nazev vystupniho souboru
#-n        renumber - precislovani titulku od 1
#-g cislo  grammar - oprava textovych chyb titulku a zamena l za I
#	   1 - Cestina
#	   2 - Anglictina   
#-t cislo  transform - prevod SRT titulku do formatu SUB MicroDVD, cislo je FPS
#-i cislo  import - prevod titulku z formatu SUB MicroDVD do SRT, cislo je FPS
#-l nezev  load - z tohoto souboru pouzije casovani pro titulky ve zpracovavanem souboru

#=====================================================
#                 HLAVNI PROGRAM
#=====================================================

if ( $opt_c and $opt_r ) { die "Volby -c a -r nemohou být použity současně!\n"; }
if ( $opt_c and $opt_s ) { die "Volby -c a -s nemohou být použity současně!\n"; }
if ( $opt_s and $opt_r ) { die "Volby -s a -r nemohou být použity současně!\n"; }
if ( $opt_t and ( $opt_c or $opt_r or $opt_s or $opt_l )) { die "Volbu -t nelze použít současně s -c -r -s či -l !\n"; }
if ( $opt_l and ( $opt_c or $opt_r or $opt_s or $opt_t )) { die "Volbu -l nelze použít současně s -c -r -s či -t !\n"; }

if ( $opt_h or $opt_v or $opt_c or $opt_r or $opt_s or $opt_t or $opt_m or $opt_i or $opt_l ) {

    if ( $opt_i ) { &sub_na_srt; }
    else {
	if ( $opt_h ) { &napoveda; }
	if ( $opt_v ) { &verze; }
	if ( $opt_c ) { &check_tit; }
	if ( $opt_r ) { &repair_tit; }
	if ( $opt_s or $opt_m ) { &shift_tit; }
	if ( $opt_t ) { &trans_tit; }
	if ( $opt_l ) { &load_timing; }
    }

}
else { print "Nebyla zadána platná volba, viz srtrepair -h\n"; }




#=====================================================
#                 PODPROGRAMY
#=====================================================





#vstup:  retezec obsahujici casovani titulku formatu XX:XX:XX,XXX --> XX:XX:XX,XXX
#vystup: jedno cislo predstavujici zacatek titulku v sekundach
sub cas_tit_beg_cislo {
    my ( $radek ) = @_;
    my ( $hod, $min, $sec, $tis, $cas );
    ( $hod, $min, $sec, $tis ) = $radek =~ /\s*(\d+):(\d+):(\d+),(\d+).*->/;
#    print "zacatek: $hod:$min:$sec,$tis\n";
    $cas = 3600*$hod + 60*$min + $sec + $tis/1000;
    return $cas;
}


#vstup:  retezec obsahujici casovani titulku formatu XX:XX:XX,XXX --> XX:XX:XX,XXX
#vystup: jedno cislo predstavujici konec titulku v sekundach
sub cas_tit_end_cislo {
    my ( $radek ) = @_;
    my ( $hod, $min, $sec, $tis, $cas );
    ( $hod, $min, $sec, $tis ) = $radek =~ /->\s*(\d+):(\d+):(\d+),(\d+)/;
#    print "konec: $hod:$min:$sec,$tis\n";
    $cas = 3600*$hod + 60*$min + $sec + $tis/1000;
    return $cas;
}


#vstup:  cislo v sekundach
#vystup: retezec obsahujici cas ve formatu XX:XX:XX,XXX
sub cislo_na_cas {
    my ( $cas ) = @_;
    my ( $cas_text );
    my ( $cislo );
    
    $cislo = int($cas/3600);
    $cas_text = "0".$cislo.":";
    $cas -= $cislo*3600;
    
    $cislo = int($cas/60);
    if ( $cislo < 10 ) { $cas_text .= "0".$cislo.":"; }
    else { $cas_text .= $cislo.":"; }
    $cas -= $cislo*60;
    
    $cislo = int($cas);
    if ( $cislo < 10 ) { $cas_text .= "0".$cislo.","; }
    else { $cas_text .= $cislo.","; }
    $cas -= $cislo;
    
    $cislo = int($cas*1000);
    if ( $cislo < 10 ) { $cas_text .= "00".$cislo; }
    elsif ( $cislo < 100 ) { $cas_text .= "0".$cislo; }
    else { $cas_text .= $cislo; }

    return $cas_text;
}


#vstup:  retezec s titulky
#vystup: retezec s opravenymi titulky
sub grammar {
    my ( $opraveno ) = @_;


    if ( $opt_g == 1 ) {
    
	#obecne chyby v textu
#	$opraveno =~ s/00/__/g; for testing purpose only
	$opraveno =~ s/d\'\'\'/ď\"/g;
        $opraveno =~ s/t\'\'\'/ť\"/g;
        $opraveno =~ s/\'\'/\"/g;
        $opraveno =~ s/\'\"/\"/g;
        $opraveno =~ s/\"\'/\"/g;
        $opraveno =~ s/\ +\"/\"/g;
        $opraveno =~ s/\"\ +/\"/g;
        $opraveno =~ s/(\"[^\"]*\")/\ $1\ /g;
        $opraveno =~ s/\"\"/\"/g;
        $opraveno =~ s/,,/\"/g;
        $opraveno =~ s/\ +,/,/g;
        $opraveno =~ s/\ +\./\./g;
        $opraveno =~ s/\ +\?/\?/g;
        $opraveno =~ s/\ +!/!/g;
        $opraveno =~ s/(\d)\ (\d)/$1$2/g;
        $opraveno =~ s/(\d)\ (\d)/$1$2/g;
        $opraveno =~ s/,\.\.\./\.\.\./g;
        $opraveno =~ s/\?\./\?/g;
        $opraveno =~ s/!\./!/g;
        $opraveno =~ s/,([^\d\"|])/,\ $1/g;
        $opraveno =~ s/\;/\;\ /g;
        $opraveno =~ s/:([^\d])/:\ $1/g;
        $opraveno =~ s/\?([^!\?\"|\)\s])/\?\ $1/g;
        $opraveno =~ s/!([^!\?\"|\)\s])/!\ $1/g;
        $opraveno =~ s/\"\ \"([^\w])/\"$1/g;
        $opraveno =~ s/\ +/\ /g;
        $opraveno =~ s/d\'/ď/g;
        $opraveno =~ s/t\'/ť/g;
        $opraveno =~ s/^\ +//g;
        $opraveno =~ s/\ +$//g;
	#navaznost na pgm2srt.pl kdy dvojtecka v kurzive se zapise jako .^
        $opraveno =~ s/\.\^/:/g;
	#zmena velkeho i na male L vsude - dusledek nerozliseni v OCR software
        $opraveno =~ s/I/l/g;
#    	$opraveno =~ s/([[:lower:]])I/$1l/g;
#    	$opraveno =~ s/([[:upper:]])I([[:lower:]])/$1l$2/g;
#    	$opraveno =~ s/\bIi/li/g;
#    	$opraveno =~ s/\bIí/lí/g;
#    	$opraveno =~ s/\bIá/lá/g;
#    	$opraveno =~ s/\bIé/lé/g;
#    	$opraveno =~ s/\bIů/lů/g;
#    	$opraveno =~ s/\bIž/lž/g;

	#nahrazeni maleho L na velke i - dusledek nerozliseni v OCR software
        $opraveno =~ s/\blhned/Ihned/g;
        $opraveno =~ s/\blk([^aá])/Ik$1/g;
        $opraveno =~ s/\blkar/Ikar/g;
#   	$opraveno =~ s/\bln([^ouě])/In$1/g;
        $opraveno =~ s/\bln([^uě])/In$1/g;
        $opraveno =~ s/\blnov/Inov/g;
        $opraveno =~ s/\blnui/Inui/g;
        $opraveno =~ s/\blont/Iont/g;
        $opraveno =~ s/\bloniz/Ioniz/g;
        $opraveno =~ s/\blono/Iono/g;
        $opraveno =~ s/\blpsa/Ipsa/g;
        $opraveno =~ s/\blpeka/Ipeka/g;
        $opraveno =~ s/\blQ/IQ/g;
        $opraveno =~ s/\bls([^t])/Is$1/g;
        $opraveno =~ s/\bl([bcdfgjmrtwxz])/I$1/g;
        $opraveno =~ s/\bIze\b/lze/g;
	#rucne nutno projit slova lva/lvu,jestli nema byt Iva/Ivu
        $opraveno =~ s/\blan\b/Ian/g;
        $opraveno =~ s/\blvan/Ivan/g;
        $opraveno =~ s/\blvet/Ivet/g;
        $opraveno =~ s/\blvo\b/Ivo/g;
        $opraveno =~ s/\blvon/Ivon/g;
        $opraveno =~ s/\blvoš/Ivoš/g;
        $opraveno =~ s/\bl\b/I/g;
        $opraveno =~ s/\bIž/lž/g;
        $opraveno =~ s/n\.I\./n\.l\./g;
        $opraveno =~ s/\bll\b/II/g;
        $opraveno =~ s/\blll\b/III/g;
        $opraveno =~ s/Vll\b/VII/g;
        $opraveno =~ s/Vlll\b/VIII/g;
        $opraveno =~ s/Xll\b/XII/g;
        $opraveno =~ s/Xlll\b/XIII/g;
        $opraveno =~ s/l([[:upper:]])/I$1/g;
        $opraveno =~ s/([[:upper:]])l\b/$1I/g;
        $opraveno =~ s/\bAI\b/Al/g;
        $opraveno =~ s/\bll/Il/g;
        $opraveno =~ s/([^.])\.\ l([^ei])/$1\.\ I$2/g;

    }
    
    if ( $opt_g == 2 ) {

	#obecne chyby v textu
        $opraveno =~ s/\'\'/\"/g;
        $opraveno =~ s/\'\"/\"/g;
        $opraveno =~ s/\"\'/\"/g;
        $opraveno =~ s/\ +\"/\"/g;
        $opraveno =~ s/\"\ +/\"/g;
        $opraveno =~ s/(\"[^\"]*\")/\ $1\ /g;
        $opraveno =~ s/\"\"/\"/g;
        $opraveno =~ s/,,/\"/g;
        $opraveno =~ s/\ +,/,/g;
        $opraveno =~ s/\ +\./\./g;
        $opraveno =~ s/\ +\?/\?/g;
        $opraveno =~ s/\ +!/!/g;
        $opraveno =~ s/(\d)\ (\d)/$1$2/g;
        $opraveno =~ s/(\d)\ (\d)/$1$2/g;
        $opraveno =~ s/,\.\.\./\.\.\./g;
        $opraveno =~ s/\?\./\?/g;
        $opraveno =~ s/!\./!/g;
	$opraveno =~ s/,([^\d\"|])/,\ $1/g;
	$opraveno =~ s/\;/\;\ /g;
        $opraveno =~ s/:([^\d])/:\ $1/g;
        $opraveno =~ s/\?([^!\?\"|\)\s])/\?\ $1/g;
        $opraveno =~ s/!([^!\?\"|\)\s])/!\ $1/g;
        $opraveno =~ s/\"\ \"([^\w])/\"$1/g;
        $opraveno =~ s/\ +/\ /g;
        $opraveno =~ s/^\ +//g;
        $opraveno =~ s/\ +$//g;
	#navaznost na pgm2srt.pl kdy dvojtecka v kurzive se zapise jako .^
        $opraveno =~ s/\.\^/:/g;
	#zmena velkeho i na male L vsude - dusledek nerozliseni v OCR software
        $opraveno =~ s/I/l/g;

	#nahrazeni maleho L na velke i - dusledek nerozliseni v OCR software
	    #nezavisle na jazyku
        $opraveno =~ s/l([[:upper:]])/I$1/g;
        $opraveno =~ s/([[:upper:]])l\b/$1I/g;
        $opraveno =~ s/\bll\b/II/g;
        $opraveno =~ s/\blll\b/III/g;
        $opraveno =~ s/Vll\b/VII/g;
        $opraveno =~ s/Vlll\b/VIII/g;
        $opraveno =~ s/Xll\b/XII/g;
        $opraveno =~ s/Xlll\b/XIII/g;
        $opraveno =~ s/\bll/Il/g;
        $opraveno =~ s/([^.])\.\ l/$1\.\ I/g;
	    #specificke pro anglictinu
        $opraveno =~ s/\bl\b/I/g;
        $opraveno =~ s/\blt/It/g;
        $opraveno =~ s/\blf\b/If/g;
        $opraveno =~ s/\bln\b/In/g;
        $opraveno =~ s/\bl\'m\b/I\'m/g;
        $opraveno =~ s/\blt\'s/It\'s/g;
        $opraveno =~ s/\bl\'ll/I\'ll/g;
        $opraveno =~ s/\bl\'ve/I\'ve/g;
        $opraveno =~ s/\bl\'d\b/I\'d/g;



    }

    return $opraveno;
}


#vstup:  zadny, jen musi byt otevren soubor s titulky ZDROJ
#vystup: indexovane pole obsahujici jednotlive radky jednoho titulku
#        a pocet techto radku (horni index); posledni radek pole je prazdny;
#        index musi byt vracen jako prvni parametr, 
#        jinak ho na vystupu pohlti pole !!!
sub nacti_titulek {
    my( $radek, @titulek, $index );
    
    while ($radek = <ZDROJ>) {

	if ( $radek =~ /\s*\d+\s*/) {

    	    $index = 1;
	    $titulek[$index] = $radek;
    
	    while ( not $radek =~ /^\s*$/ ) {
		$index++;
		$radek = <ZDROJ>;
		$titulek[$index] = $radek;
	    }
	    print ".";
	    return ( $index, @titulek );
	}
    }
}


sub read_timing {
    
    while ( $progress <= @srt_file ) {

	$progress++;

	if ( $srt_file[$progress] =~ /.*-->.*/) {
#	    print ".";
	    return ( $srt_file[$progress], $progress );
	}

    }

}


#vstup:  nic
#vystup: nic resp. tisk napovedy na obrazovku
sub napoveda {

    print "\n";
    print "Program srtrepair slouží ke zpracování titulků ve formátu SRT vytvořených\n";
    print "např. programy subtitle2pgm + dvdsub/pgm2srt.\n";
    print "Použití: srtrepair [volby] Vstupní_SRT_titulky\n";
    print "Pozor!!! název vstupního SRT souboru musí být úplně poslední!\n";
    print "  -h          tento help\n";
    print "  -v          verze tohoto programu\n";
    print "  -c          check - kontrola překryvu časování titulků\n";
    print "  -r          repair - oprava překryvu časování titulků\n";
    print "  -o <název>  output - možno zadat název nového souboru při -r -s -t\n";
    print "                     - bez použití volby je vytvořen soubor *.new\n";
    print "  -s <číslo>  shift - posun všech titulků o <číslo> sekund +/-\n";
    print "                      nebo ve formátu h:m:s\n";
    print "                    - <číslo> může mít max. 3 desetinná místa\n";
    print "  -m <číslo>  movement - změna dynamiky(+/-) / celkové délky titulků\n";
    print "                       - <číslo> je změna v sec za 1 sec\n";
    print "                       - neovlivní 1.titulek\n";
    print "  -f          force - v případě vzniku záporných titulků při posunu\n";
    print "                      nezahlásí chybu, ale uloží je do separátního\n";
    print "                      souboru *.first_part; takto lze titulky rozdělit\n";
    print "                      na dvě části\n";
    print "                    - má smysl jen s volbami -r -s\n";
    print "  -g <číslo>  grammar - kontroluje chyby po OCR software a řeší problém\n";
    print "                        záměny malého L za velké i\n";
    print "                      - má smysl jen s volbami -r -s -t\n";
    print "                      - 1 ..čestina\n";
    print "                      - 2 ..angličtina\n";
    print "  -e          empty - vynechávání titulků, které neobsahují žádný text\n";
    print "                    - má smysl jen s volbami -r -s -t\n";
    print "  -n          renumber - přečísluje titulky postupně od 1\n";
    print "                       - doporučeno při použití -e\n";
    print "                       - má smysl jen s volbami -r -s\n";
    print "  -t <číslo>  transform - převede SRT titulky na formát SUB MicroDVD\n";
    print "                        - povinné <číslo> udává FPS videa (obvykle 25)\n";
    print "  -i <číslo>  import - převede titulky z formátu SUB MicroDVD na SRT\n";
    print "                     - povinné <číslo> udává FPS videa (obvykle 25)\n";
    print "  -l <název>  load - z tohoto souboru použije časování pro hlavní\n";
    print "                     vstupní soubor; volba se používá samostatně\n";
    print "---------------\n";
    print "Formáty výpisu:\n";
    print ".......  za každý načtený titulek je vypsána tečka; jakýsi ukazatel průběhu\n";
    print "128-129  titulek 129 začíná dříve, než titulek 128 končí; pomůže -r\n";
    print "130!!!   délka titulku 130 je menší než ",MIN_DELKA," sec popř. záporná,\n";
    print "         zde je nutný ruční zásah\n";
    print "---------------\n";
    print "Příklady:\n\n";
    print " srtrepair -reno Nové.srt Titulky.srt\n";
    print "    -opraví překrývající se Titulky.srt, vynechá titulky bez textu\n";
    print "     a všechny přečísluje od 1 a uloží výsledek do Nové.srt\n\n";
    print " srtrepair -ens -62.250 -o Nové.srt Titulky.srt\n";
    print "    -všechny titulky budou začínat (a končit :o) o 62.25 sec dříve,\n";
    print "     vynechá titulky bez textu a všechny přečísluje od 1 a výsledek\n";
    print "     uloží do Nové.srt\n\n";
    print " srtrepair -s 1.247 -m -0.008333 -o Nové.srt Titulky.srt\n";
    print "    -zrychlí titulky o 5sec na 10min (5/600=0.008333) a jejich začátek\n";
    print "     posune o 1.247sec a vše uloží do Nové.srt\n\n";
    print " srtrepair -et 25 -o Nové.sub Titulky.srt\n";
    print "    -převede SRT Titulky.srt na SUB formát, přitom vynechá titulky\n";
    print "     bez textu a vše uloží do Nové.sub\n";
    print "---------------\n";
    print "Pozn.: Pokud jako parametr pro -s dáváte nulu, pište -s 00 či -s 0.0 či -s -0\n";
    print "       Vyplývá to z požadavku Perlu: -s 0 totiž odpovídá opt_s=nedef;\n\n";

}


#vstup:  nic
#vystup: nic resp. tisk verze na obrazovku
sub verze {

    print "srtrepair ver. ",VERZE,"\n";
    print "Vytvořeno na platformě LinuxMandrake 9.2; Perl v5.8.1\n";
    print 'Tomáš Hanusek, xhant04@centrum.cz, http://hanus.host.sk',"\n";

}

sub check_tit {
    my ( $i, $index1, $index2, @titulek1, @titulek2, $opraveno, @priklad_text_chyby );
    my ( $cas_beg1, $cas_beg2, $cas_end1, $cas_end2, $chyby, $prazdne, $text_chyby );

    if ( $ARGV[0] ) {

	
	#podrpogram je volan i po oprave titulku - proto se otevira output soubor pro "kontroluji po sobe"
	if ( $opt_r ) {
	    if ( $opt_o ) { open( ZDROJ ,$opt_o ) or die ("Nemohu otevřít soubor \'$opt_o\'!\n"); }
	    else { open( ZDROJ, "$ARGV[0].new") or die ("Nemohu otevřít soubor \'$ARGV[0].new\'!\n"); }
	}
	else {
	    open( ZDROJ, $ARGV[0] ) or die ("Nemohu otevřít soubor \'$ARGV[0]\'!\n");
	}

	$chyby = $prazdne = $text_chyby = 0;

	( $index1, @titulek1 ) = &nacti_titulek;
	if ( $index1 < 4 ) { $prazdne++; }

	while ( $index1 ) {

	    ( $index2, @titulek2 ) = &nacti_titulek;
	    if ( $index2 < 4 ) { $prazdne++; }	    
	    
	    if ( $index2 ) {
		
		$cas_beg1 = &cas_tit_beg_cislo($titulek1[2]);
		$cas_end1 = &cas_tit_end_cislo($titulek1[2]);		
		
		$cas_beg2 = &cas_tit_beg_cislo($titulek2[2]);
		$cas_end2 = &cas_tit_end_cislo($titulek2[2]);		
		
		chomp($titulek1[1]);
		chomp($titulek2[1]);
		
		if ( ($cas_end1 - $cas_beg1)<MIN_DELKA ) {
		    print "$titulek1[1]!.";
		    $chyby++;
		}
		
		if ( $cas_end1 >= $cas_beg2 ) {
		    print "$titulek1[1]-$titulek2[1]";
		    $chyby++;
		}
		
		for ( $i=3 ; $i<=$index1 ; $i++ ) { 
		    #kontrola pravopisnych chyb jen pro text, ne pro casovani
		    $opraveno = &grammar($titulek1[$i]);
		    if ($opraveno ne $titulek1[$i]) {
			$text_chyby++;
			if ( $text_chyby < 6 ) {
			    $priklad_text_chyby[$text_chyby]=$titulek1[1];
			}
		    }
		}

		for ( $i=1 ; $i<=$index2 ; $i++ ) { 
		    $titulek1[$i] = $titulek2[$i];
		    $index1 = $index2;
		}

	    }
	    else { $index1 = undef; }	    

	}

	close(ZDROJ);
	print "\nCelkem nalezeno chyb: $chyby\n";
	$prazdne--; #po poslednim titulku se jeste jednou nacita
	print "Počet titulků bez textu: $prazdne\n";
	if ( $opt_g ) { 
	    print "Počet opravitelných chyb v textu titulků: $text_chyby, např.titulky: ";
	    foreach $i (1..5) { print "$priklad_text_chyby[$i],"; }
	}
	print "\n\n";

    }
    else {
	print "Nebylo zadáno jméno souboru s SRT titulky! viz srtrepair -h\n";
    }
}

#estimates time needed to read the subtitle according to the amount of text
sub estimate_tit_len {
    my ( $index ) = @_;
    my ( $tit_len_est );
    
    $index++; #index is originaly set to timing row
    $tit_len_est = 0;

    while ( $srt_file[$index] !~ /^\s*$/ ) {

	if ( length($srt_file[$index]) < 10 ) { $tit_len_est+=1; }
	else { $tit_len_est+=2; }

	$index++;

    }

    return $tit_len_est;

}


sub repair_tit {
    my ( $i, $index1, $index2, @titulek1, @titulek2, $cislo_titulku );
    my ( $cas_beg1, $cas_beg2, $cas_end1, $cas_end2, $tit1_len_est, $tit2_len_est );

    if ( $ARGV[0] ) {

	open( ZDROJ, $ARGV[0] ) or die ("Nemohu otevřít soubor \'$ARGV[0]\'!\n");
	if ( $opt_o ) { open( NOVY ,">$opt_o" ) or die ("Nemohu vytvořit soubor \'$opt_o\'!\n"); }
	else { open( NOVY, ">$ARGV[0].new") or die ("Nemohu vytvořit soubor \'$ARGV[0].new\'!\n"); }

	$cislo_titulku = 1;
	@srt_file = ();
	print "Opravuji titulky...\n";

	# read the very first subtitle
	if ( $opt_e ) {
	    do {
		( $index1, @titulek1 ) = &nacti_titulek;
	    } while ( $index1<4 );
	}
	else { ( $index1, @titulek1 ) = &nacti_titulek; }

	############## read whole SRT file into array @srt_file #################
	##############  and simultaneosly handle g e n options  #################
	while ( $index1 ) {

	    unless ( $opt_e and $index1<4 ) {

		if ( $opt_n ) { $titulek1[1] = $cislo_titulku."\n"; }
		for ( $i=1 ; $i<=$index1 ; $i++ ) {
		    if ( $opt_g and $i>2 ) { $titulek1[$i] = &grammar($titulek1[$i]); }
		    push(@srt_file,$titulek1[$i]);
		}

		$cislo_titulku++;

	    }

	    ( $index2, @titulek2 ) = &nacti_titulek; 

	    $cas_beg1 = &cas_tit_beg_cislo($titulek1[2]);
	    $cas_end1 = &cas_tit_end_cislo($titulek1[2]);
	    if ( $index2 ) {
		$cas_beg2 = &cas_tit_beg_cislo($titulek2[2]);
	        $cas_end2 = &cas_tit_end_cislo($titulek2[2]);
	    }

	    while ( $index2 and $cas_beg1==$cas_beg2 and $cas_end1==$cas_end2 ) {

		( $index2, @titulek2 ) = &nacti_titulek;
		if ( $index2 ) {
		    $cas_beg2 = &cas_tit_beg_cislo($titulek2[2]);
	            $cas_end2 = &cas_tit_end_cislo($titulek2[2]);
		}

	    }

	    if ( $index2 ) {

		for ( $i=1 ; $i<=$index2 ; $i++ ) { 
		    $titulek1[$i] = $titulek2[$i];
		    $index1 = $index2;
		}

	    } else { $index1 = undef; }

	}
	############## end of read whole SRT file into array @srt_file #################

	$progress = 0;

	( $timing1, $index1 ) = &read_timing;
	$cas_beg1 = &cas_tit_beg_cislo($timing1);
	$cas_end1 = &cas_tit_end_cislo($timing1);

	########################### timing repair ######################################
	while ( $progress < @srt_file ) {

	    ( $timing2, $index2 ) = &read_timing;

	    if ( $index2 ) {

		$cas_beg2 = &cas_tit_beg_cislo($timing2);
		$cas_end2 = &cas_tit_end_cislo($timing2);
		
		$tit1_len_est = &estimate_tit_len($index1);		    
		$tit2_len_est = &estimate_tit_len($index2);		    

		# the very first subtitle starts at 00:00:00 or is too short
		if ( ($cas_beg1 == 0  or ($cas_end1-$cas_beg1)<MIN_DELKA) and $index1<3 ) {

		    if ( ($cas_end1-$tit1_len_est)>0 ) { $cas_beg1 = $cas_end1 - $tit1_len_est; }

		    $srt_file[$index1] = &cislo_na_cas($cas_beg1)." --> ".&cislo_na_cas($cas_end1)."\n";

		}

		# predchazejici titulek zasahuje do nasledujiciho
		#   nebo nasledujici titulek nema ani minimalni delku
		if ( ($cas_end1>=$cas_beg2) or (($cas_end2-$cas_beg2)<MIN_DELKA) ) {

		    if ( ($cas_end2-$tit2_len_est) > $cas_end1 ) {

			$cas_beg2 = $cas_end2 - $tit2_len_est;
#			print "-$srt_file[$index2-1]";
			$srt_file[$index2] = &cislo_na_cas($cas_beg2)." --> ".&cislo_na_cas($cas_end2)."\n";

		    } elsif ( ($cas_end2-$cas_end1) > 0.5*$tit2_len_est ) {

			$cas_beg2 = $cas_end1 + 0.1;
#			print "*$srt_file[$index2-1]";
			$srt_file[$index2] = &cislo_na_cas($cas_beg2)." --> ".&cislo_na_cas($cas_end2)."\n";

		    } elsif ( ($cas_end1-$cas_beg1) > $tit1_len_est ) {

			$cas_end1 = $cas_beg1 + $tit1_len_est;
			$cas_beg2 = $cas_end1 + 0.1;
#			print "+$srt_file[$index1-1]_$srt_file[$index2-1]";
			$srt_file[$index1] = &cislo_na_cas($cas_beg1)." --> ".&cislo_na_cas($cas_end1)."\n";
			$srt_file[$index2] = &cislo_na_cas($cas_beg2)." --> ".&cislo_na_cas($cas_end2)."\n";

		    } elsif ( ($cas_end2-$cas_end1) >= MIN_DELKA ) {
		    
			$cas_beg2 = $cas_end1 + 0.06; #some reserve because of SUB format (1 frame is 0.04 sec)
			$srt_file[$index2] = &cislo_na_cas($cas_beg2)." --> ".&cislo_na_cas($cas_end2)."\n";
		    
		    } else {

			#print "unhandled at stage 1 - $srt_file[$index2-1]"

		    };

		}

		# titulek drive konci nez zacina
		if ( $cas_end1<=$cas_beg1 ) {

		    if ( ($cas_beg1+$tit1_len_est) < $cas_beg2 ) {

			$cas_end1 = $cas_beg1 + $tit1_len_est;
			$srt_file[$index1] = &cislo_na_cas($cas_beg1)." --> ".&cislo_na_cas($cas_end1)."\n";

		    } elsif ( ($cas_beg2-$cas_beg1) >= MIN_DELKA ) {

			$cas_end1 = $cas_beg2 - 0.05;
			$srt_file[$index1] = &cislo_na_cas($cas_beg1)." --> ".&cislo_na_cas($cas_end1)."\n";

		    } else {

			#print "unhandled at stage 2 - $srt_file[$index1-1]"

		    };

		}

		$timing1 = $timing2;
		$index1 = $index2;
		$index2 = undef;
		$cas_beg1 = $cas_beg2;
		$cas_end1 = $cas_end2;

	    }

	} # end of while
	########################### end of timing repair ######################################

	for ( $i=0; $i<=@srt_file; $i++ ) {
	    print NOVY $srt_file[$i];
	}

	close(ZDROJ);
	close(NOVY);
	
	print "\nKontroluji po sobě:\n";

	&check_tit;
	
    }
    else {
	print "Nebylo zadáno jméno souboru s SRT titulky! viz srtrepair -h\n";
    }
}


sub shift_tit {
    my ( $hod, $min, $sec, $i, $index1, @titulek1, $cislo_titulku );
    my ( $cas_beg1, $cas_end1, $posun, $mov );


    if ( $opt_s ) {

        if ( $opt_s =~ /.*:.*/ ) {

	    ( $hod, $min, $sec ) = split ( /:/, $opt_s );
	    $sec =~ s/,/\./;

#	    print "$hod hod,$min min,$sec sec\n";

    	    unless ( $opt_s =~ /\d+:\d+:\d+/ ) {
	
		die "Parametr pro volbu -s byl zadán špatně!\n";

	    } else {

		if ( $opt_s =~ /-.*/ ) {

		    $posun = $hod*3600 - $min*60 - $sec;

		} else {

		    $posun = $hod*3600 + $min*60 + $sec;

		}

	    }

	} else {
									
    
	    ( $posun ) = $opt_s =~ /^(-?\+?\d+\.?\d{0,3})$/;

	    ( $opt_s =~ /^(-?\+?\d+\.?\d{0,3})$/ ) or die ("Parametr pro volbu -s byl zadán špatně nebo vůbec!\n");

	}

    } else { $posun = 0; }

    if ( $opt_m ) {

	$opt_m =~ s/,/\./;

	( $mov ) = $opt_m =~ /^(-?\+?\d+\.?\d*)$/;

	( $opt_m =~ /^(-?\+?\d+\.?\d*)$/ ) or die ("Parametr pro volbu -m byl zadán špatně nebo vůbec!\n");

	$mov += 1;
    
    } else { $mov = 1; }

    if ( $ARGV[0] ) {

	open( ZDROJ, $ARGV[0] ) or die ("Nemohu otevřít soubor \'$ARGV[0]\'!\n");
	if ( $opt_o ) { open( NOVY ,">$opt_o" ) or die ("Nemohu vytvořit soubor \'$opt_o\'!\n"); }
	else { open( NOVY, ">$ARGV[0].new") or die ("Nemohu vytvořit soubor \'$ARGV[0].new\'!\n"); }

	$cislo_titulku = 1;
	$prvni_jiz_otevren = 0;

	( $index1, @titulek1 ) = &nacti_titulek;

	while ( $index1 ) {

	    if ( $posun != 0 or $opt_m ) {

		if ( $cislo_titulku>1 ) {
		    $cas_beg1 = &cas_tit_beg_cislo($titulek1[2]) * $mov + $posun;
		    $cas_end1 = &cas_tit_end_cislo($titulek1[2]) * $mov + $posun;
		}
		else {
		    $cas_beg1 = &cas_tit_beg_cislo($titulek1[2]) + $posun;
		    $cas_end1 = &cas_tit_end_cislo($titulek1[2]) + $posun;		
		}

		if ( not $opt_f and ( $cas_beg1<0 or $cas_end1<0 ) ) {
		    close (ZDROJ);
		    close (NOVY);
		    die ("Zadaný posun způsobí záporné časování titulků!!!\n");
		}

		if ( ($opt_f and $cas_beg1>=0 and $cas_end1>=0) or ( not $opt_f ) ) {
		    $titulek1[2] = &cislo_na_cas($cas_beg1)." --> ".&cislo_na_cas($cas_end1)."\n";
		}

	    }

	    if ( $opt_n and $cas_beg1>=0 and $cas_end1>=0 ) { $titulek1[1] = $cislo_titulku."\n"; }

	    unless ( $opt_e and $index1<4 ) {

		if ( $opt_f and ( $cas_beg1<0 or $cas_end1<0 ) ) {
		#titulek se uklada beze zmen do jineho souboru, pokud jsou titulky po posunu zaporne a je zvolena volba -f

		    unless ( $prvni_jiz_otevren ) {
		    
			if ( $opt_o ) {
			    open( PRVNI ,">$opt_o.first_part" ) or die ("Nemohu vytvořit soubor \'$opt_o.first_part\'!\n"); 
			}
			else {
			    open( PRVNI, ">$ARGV[0].new.first_part") or die ("Nemohu vytvořit soubor \'$ARGV[0].new.first_part\'!\n");
			}
			$prvni_jiz_otevren = 1;
			print "Vytvořen první soubor titulků *.first_part";

		    }

		    for ( $i=1 ; $i<=$index1 ; $i++ ) {
			if ( $opt_g and $i>2 ) { $titulek1[$i] = &grammar($titulek1[$i]); }
			print PRVNI $titulek1[$i];
		    }

		}
		else {
		    $cislo_titulku++; #cislovani pouze nezapornych titulku
		    for ( $i=1 ; $i<=$index1 ; $i++ ) {
			if ( $opt_g and $i>2 ) { $titulek1[$i] = &grammar($titulek1[$i]); }
			print NOVY $titulek1[$i];
		    }

		}

	    }

	    ( $index1, @titulek1 ) = &nacti_titulek;
	}

	close(ZDROJ);
	close(NOVY);
	if ( $prvni_jiz_otevren ) { close(PRVNI); }

	print "\n";

    }

    else {

	print "Nebylo zadáno jméno souboru s SRT titulky! viz srtrepair -h\n";

    }

}



sub trans_tit {
    my ( $i, $index1, @titulek1 );
    my ( $cas_beg1, $cas_end1, $fps, $radek );

    ( $fps ) = $opt_t =~ /(\d+\.?\d{0,3})/;

    ( $opt_t =~ /(\d+\.?\d{0,3})/ ) or die ("Parametr pro volbu -t byl zadán špatně nebo vůbec!\n");

    if ( $ARGV[0] ) {

	open( ZDROJ, $ARGV[0] ) or die ("Nemohu otevřít soubor \'$ARGV[0]\'!\n");
	if ( $opt_o ) { open( NOVY ,">$opt_o" ) or die ("Nemohu vytvořit soubor \'$opt_o\'!\n"); }
	else { open( NOVY, ">$ARGV[0].new") or die ("Nemohu vytvořit soubor \'$ARGV[0].new\'!\n"); }

	( $index1, @titulek1 ) = &nacti_titulek;

	while ( $index1 ) {

	    unless ( $opt_e and $index1<4 ) {
	
		$cas_beg1 = int( &cas_tit_beg_cislo($titulek1[2])*$fps );
		$cas_end1 = int( &cas_tit_end_cislo($titulek1[2])*$fps );		

		for ( $i=3 ; $i<$index1 ; $i++ ) {
	    	    chomp($titulek1[$i]);
		}

		$radek = "{$cas_beg1}{$cas_end1}";
		for ( $i=3 ; $i<$index1 ; $i++ ) {
	    	    $radek .= "$titulek1[$i]|";
		}
		unless ( $index1<4 ) { chop($radek); }
		$radek .= "\n";

		if ( $opt_g and $i>2 ) { $radek = &grammar($radek); }
		print NOVY $radek;

	    }

	    ( $index1, @titulek1 ) = &nacti_titulek;
	}
    
	close(ZDROJ);
	close(NOVY);
	
	print "\n";

    }
    else {
	print "Nebylo zadáno jméno souboru s SRT titulky! viz srtrepair -h\n";
    }
}


sub sub_na_srt {
    my ( $i, $index, $text, @titulek );
    my ( $frame_beg, $frame_end, $cas_beg, $cas_end, $fps, $radek );

    ( $fps ) = $opt_i =~ /(\d+\.?\d{0,3})/;

    ( $opt_i =~ /(\d+\.?\d{0,3})/ ) or die ("Parametr pro volbu -i byl zadán špatně nebo vůbec!\n");

    if ( $ARGV[0] ) {

	open( ZDROJ, $ARGV[0] ) or die ("Nemohu otevřít soubor \'$ARGV[0]\'!\n");
	if ( $opt_o ) { open( NOVY ,">$opt_o" ) or die ("Nemohu vytvořit soubor \'$opt_o\'!\n"); }
	else { open( NOVY, ">$ARGV[0].new") or die ("Nemohu vytvořit soubor \'$ARGV[0].new\'!\n"); }

	$index = 1;

	while ( $radek = <ZDROJ> ) {
	
	    print ".";
	    
	    if ( $radek =~ /\{\d+\}\{\d+\}/ ) {

		( $frame_beg ) = $radek =~ /\{(\d+)\}\{/;
		( $frame_end ) = $radek =~ /\}\{(\d+)\}/;
		( $text ) = $radek =~ /\{.*\}(.*)$/;
		@titulek = split (/\|/, $text);
		$cas_beg = &cislo_na_cas($frame_beg/$fps);
		$cas_end = &cislo_na_cas($frame_end/$fps);

		print NOVY "$index\n";
		print NOVY $cas_beg," --> ",$cas_end,"\n";
		foreach $text ( @titulek ) {
		    print NOVY "$text\n";
		}
		print NOVY "\n";
		
		$index++;

	    }
	    
	}
    
	close(ZDROJ);
	close(NOVY);
	
	print "\n";

    }
    else {
	print "Nebylo zadáno jméno souboru se SUB titulky! viz srtrepair -h\n";
    }
}

sub load_timing {

    my ( @titulek );

    if ( $ARGV[0] ) {

	open( ZDROJ, $ARGV[0] ) or die ("Nemohu otevřít soubor \'$ARGV[0]\'!\n");
	open( TIMING, $opt_l ) or die ("Nemohu otevřít soubor \'$opt_l\'!\n");
	if ( $opt_o ) { open( NOVY ,">$opt_o" ) or die ("Nemohu vytvořit soubor \'$opt_o\'!\n"); }
	else { open( NOVY, ">$ARGV[0].new") or die ("Nemohu vytvořit soubor \'$ARGV[0].new\'!\n"); }

	while ( $radek = <TIMING> and $radek2 = <TIMING> and $radek3 = <ZDROJ> ) {

	    print "$radek$radek2$radek3\n";

	    while ( $radek !~ /^\d+$/ or $radek2 !~ /.*-->.*/ ) {
		print "loop1\n";
		$radek = $radek2;
		unless ( $radek2 = <TIMING> ) { last; }
	    }
	    
	    if ( $radek2 =~ /.*-->.*/ ) {

		@titulek = ();

		while ( $radek3 =~ /^\d+$/ or $radek3 =~ /.*-->.*/ or $radek3 =~ /^\s*$/ ) {
		    $radek3 = <ZDROJ>;
		    print "loop2\n";
		}

		do {

		    unless ( $radek3 ) { last; }
		    push( @titulek, $radek3 );
		    $radek3 = <ZDROJ>;

		    print "loop3\n";

		} while ( $radek3 !~ /^\s*$/ );

		if ( @titulek > 0 ) {
		
		    print NOVY "$radek";
		    print NOVY "$radek2";
		    foreach $text ( @titulek ) {
			print NOVY "$text";
		    }
		    print NOVY "\n";
		
		}

	    }

	}

	close(ZDROJ);
	close(NOVY);
	close(TIMING);

    }
    else {
	print "Nebylo zadáno jméno souboru se SUB titulky! viz srtrepair -h\n";
    }

}


