#!/usr/bin/perl

# Author: Domjan Svilkovic (dsvilko@gmail.com)
# Licence: GPL 2.0

# only the initial values - can be changed in the GUI (no need to edit)
$ffmpeg="ffmpeg";   # the name (possibly with the full path) of the ffmpeg (with AMR support)
$tmp="/tmp";
$ver="1.0";
$subfont="/var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType/DejaVuSans.ttf";
$SW=176;
$SH=144;
$compress=1.2;
$zfactor=5;

@fields=("Foutput","Skbps","Skbps2","Fsubtitle","Ffont","Escale","Ssplit","Egain","Eopt","Sgamma","Scontrast","Sbrightnes","Ssaturation","Tsplit","Tsubtitles","Gcrop","Efps","Etitle","Teq","Lsource","Tskip","Tvolnorm","Tmp4","Taac","Tdir","Ftmp","Fffmpeg","Esh","Esw","Ecfactor","Ezfactor","Tflip","Tcad");

# parse the rc file
open RC, "$ENV{HOME}/.3gpwizrc2";
while(<RC>) {
  chop;
  ($x,$y)=split(/=/);
  print "|$x|$y|\n";
  for $f (@fields) { if ($f eq $x) { $field{$x}=$y; print "read $x=$y\n"; } }
}
close RC;
if(!$field{Foutput}) { $field{Foutput}="$ENV{HOME}"; }
if(!$field{Ftmp}) { $field{Ftmp}=$tmp; }
if(!$field{Fffmpeg}) { $field{Fffmpeg}=$ffmpeg; }
if(!$field{Ecfactor}) { $field{Ecfactor}=$compress; }
if(!$field{Ezfactor}) { $field{Ezfactor}=$zfactor; }
if(!$field{Esh}) { $field{Esh}=$SH; }
if(!$field{Esw}) { $field{Esw}=$SW; }

$SH=$field{Esh};
$SW=$field{Esw};
$ffmpeg=$field{Fffmpeg};
$tmp=$field{Ftmp};
$compress=$field{Ecfactor};
$zfactor=$field{Ezfactor};

$in=$ARGV[0];
$sdir=`dirname "$in"`; chop $sdir;
if($ARGV[1] eq "-q") { $quick=1; $tmpfile=`tempfile -s -3gptmp`; chop $tmpfile; $tmpfile="$tmpfile"} else { $tmpfile="$tmp/movie"; }
print "tmpfile=$tmpfile\n";
if(!$in) { 
  print <<EOF
3gpwiz ver. $ver (C) Domjan Svilkovic
Convert any movie format to a 3gp movie, suitable for watching on a mobile phone.
Syntax: 3gpwiz source_movie
... where source_movie can be either a filename or a dvd://title

EOF
  ;
  exit 1;
}

$formats=`$ffmpeg -formats`;
if(! ($formats=~/E.*3gp/)) { print "$ffmpeg does not have a 3gp support!\n"; $no3gp=1; } else { $supports="$supports 3gp"; }
if(! ($formats=~/E.*mp4/)) { print "$ffmpeg does not have a mp4 support (see README)!\n"; $nomp4=1; } else { $supports="$supports mp4"; }
if(! ($formats=~/E.*amr_nb/)) { print "$ffmpeg does not have a AMR support (see README)!\n"; $noamr=1; } else { $supports="$supports amr"; }
if(! ($formats=~/E.*aac/)) { print "$ffmpeg does not have a AAC support (see README)!\n"; $noaac=1; } else { $supports="$supports aac"; }
if(! ($formats=~/E.*mpeg4/)) { print "$ffmpeg does not have a mpeg4 support (see README)!\n"; $nopmeg4=1; } else { $supports="$supports mpeg4"; }
if(! ($formats=~/E.*h263/)) { print "$ffmpeg does not have a h263 support (see README)!\n"; $noh263=1; } else { $supports="$supports h263"; }

if(! ($in=~/^\//) && ! ($in=~/^dvd:/)) {
  $pwd=`pwd`;
  chop $pwd;
  $in="$pwd/$in";
}

# the splash screen
if(!$quick) {
  system "kmdr-executor /usr/share/apps/3gpwiz/splash.kmdr &";
  while(!$kmdr) {
    $kmdr=`dcop | grep kmdr-exec`;
    chop $kmdr;
  }
  print "$kmdr\n";
}

$title=`basename \"$in\"`;
chop $title; chop $f;
$title=~s/\.\w+$//;
$env="MOVIE=\"$in\"";

$HH[4]=$SH; $D[4]=0;
$HH[3]=$SH-16; $D[3]=0;
$HH[2]=$SH-32; $D[2]=16;
$HH[1]=$SH-48;  $D[1]=16;


# get the movie info
open I, "mplayer \"$in\" -identify -vo null -frames 1 2>&1 |";
while(<I>) {
  if(/^ID_VIDEO_WIDTH=(\d+)/) { $W=$1; }
  if(/^ID_VIDEO_HEIGHT=(\d+)/) { $H=$1; }
  if(/^ID_VIDEO_ASPECT=([\d.]+)/) { $A=$1; if(abs($A)<0.01) { $A=$W/$H; } }
  if(/^ID_LENGTH=(\d+)/) { $L=$1; $L2=int($L*3/4); }
}
if(`which tcprobe`) {
  if($in=~/dvd:\/\/(\d+)/) { 
    $L=`tcprobe -i /dev/dvd -T $1 2> /dev/null | grep "] V: " | cut -f5 -d" "`;
    chop $L;
    $L2=int($L*3/4);
  }
}
$LM=sprintf("%.1f",$L/60);
$env="$env MOVIELEN=$L";
if($in=~/.avi/i || $in=~/dvd:/) { 
  $seek="-ss $L2";
} else {
  $size=`du \"$in\"`;
  if($size=~/^(\d+)/) { $L2=int($1*3/4*1000); }
  $seek="-sb $L2";
}
close I;
print "$W $H $A $L\n";
if($field{Tcad} eq "true" && $L>5*60) {
  $cad=`/usr/share/apps/3gpwiz/findcrop "$in" $L2`;
  ($Wa,$Ha,$X0,$Y0)=split(":",$cad);
  if($Wa && $Ha) { 
    $W=$Wa; $H=$Ha;
    $crop0="crop=$cad,";
    $A=$W/$H;
  }
}

# crop calc
for $i (1,2,3,4) {
  $AA=$SW/$HH[$i];
  $W2=int($W*(1-$zfactor/100));
  $H2=int($H*(1-$zfactor/100));
  if($A>$AA) {  # the film is wider -> trim W
    if($H2*$AA*$compress<$W2) { $W2=int($H2*$AA*$compress); } else { $W2=int($H2*$AA); }
    $crop="$W2:$H2";
  } else { # the film is higher -> trim H
    if($W2/$AA*$compress<$H2) { $H2=int($W2/$AA*$compress); } else { $H2=int($W2/$AA); }
    $crop="$W2:$H2";
  }
  $scale="$SW:$HH[$i]";
  print "$i $crop\n";
  if(!$quick) {
    system "cd /tmp; mplayer \"$in\" -nosound -vo png $seek -frames 5 -vf $crop0"."crop=$crop,scale=$scale,expand=$SW:$SH:0:$D[$i] 2>/dev/null > /dev/null";
    print           "mplayer \"$in\" -nosound -vo png $seek -frames 5 -vf $crop0"."crop=$crop,scale=$scale,expand=$SW:$SH:0:$D[$i]\n";
    system "mv /tmp/00000005.png /tmp/crop$i.png";
    system "rm /tmp/0000000*.png";
    system "dcop $kmdr KommanderIf changeWidgetText ProgressBar $pb";
  }
  $vf[$i]=$crop0."crop=$crop,scale=$scale,expand=$SW:$SH:0:";
  $env="$env MOVIEVF$i='$crop0"."crop=$crop,scale=$scale,expand=$SW:$SH:0:0:1' MOVIEV$i='$crop0"."crop=$crop,scale=$scale,expand=$SW:$SH:0:$D[$i]'";
  $pb=$i*25;
}


# show the main 3gpwiz GUI
$field{Lsource}="$in";
if(!$quick) { 
  system "dcop $kmdr MainApplication-Interface quit"; 
  $kmdr="";
  open W, "$env kmdr-executor /usr/share/apps/3gpwiz/3gpwiz.kmdr |";
  while(!$kmdr) {
    $kmdr=`dcop | grep kmdr-exec`;
    chop $kmdr;
  }


  # set the fields from the rc file
  $field{Lsource}="$in";
  for $f (@fields) {
    if (exists $field{$f}) {
      $cmd="changeWidgetText";
      if($f=~/^T/) { $cmd="setChecked"; }
      if($field{$f} ne "") { 
        system "dcop $kmdr KommanderIf $cmd $f \"$field{$f}\""; 
        print "set $f=$field{$f} ($cmd)\n";
      }
    }
  }
  if($noaac) { 
    system "dcop $kmdr KommanderIf setChecked Taac false"; 
    system "dcop $kmdr KommanderIf setEnabled Taac false"; 
  }
  if($nomp4 || $nompeg4) { 
    system "dcop $kmdr KommanderIf setChecked Tmp4 false"; 
    system "dcop $kmdr KommanderIf setEnabled Tmp4 false"; 
  }
  if($noamr) { 
    system "dcop $kmdr KommanderIf setChecked Taac true"; 
    system "dcop $kmdr KommanderIf setEnabled Taac false"; 
  }
  if($no3gp || $noh263) { 
    system "dcop $kmdr KommanderIf setChecked Tmp4 true"; 
    system "dcop $kmdr KommanderIf setEnabled Tmp4 false"; 
  }
  system "dcop $kmdr KommanderIf changeWidgetText Lsupports \"$supports\""; 
}

# additional initialization
if(!$quick) {
  system "dcop $kmdr KommanderIf changeWidgetText Etitle \"$title\"";
  system "dcop $kmdr KommanderIf changeWidgetText ppid $$";
  system "dcop $kmdr KommanderIf changeWidgetText Llen $LM";
}
if(! exists($field{Ffont}) || $field{Ffont}=="") {
  print "Looking for a suitable subtitle font ...\n";
  $font=`locate DejaVu-Sans.ttf DejaVuSans.ttf FreeSans.ttf | head -1`;
  chop $font;
  if($font=~/ttf/) { 
    print "   found $font\n";
    if(!$quick) { system "dcop $kmdr KommanderIf changeWidgetText Ffont \"$font\""; }
    $field{Ffont}=$font;
  }
}
if(! exists($field{Escale}) || $field{Escale}=="") {
  if(!$quick) { system "dcop $kmdr KommanderIf changeWidgetText Escale \"3.8\""; }
  $field{Escale}=3.8;
}
if($field{Taac} eq "false") {
  if(!$quick) { system "dcop $kmdr KommanderIf changeWidgetText Skbps2 \"12\""; }
  $field{Skbps2}=12;
}
if(!$quick) {
  if( ($noamr && $noaac) || ($nompeg4 && $noh263) || ($no3gp && $nomp4) ) {
    system "dcop $kmdr KommanderIf changeWidgetText Lffmpeg \"Please install a cvs ffmpeg!\""; 
    system "dcop $kmdr KommanderIf setCurrentItem TabWidget1 2";
  } else { 
    system "dcop $kmdr KommanderIf setEnabled Bconvert true"; 
  }
}

$field{Etitle}=$title;
if(!$quick) {
  print "Waiting for command...\n";
  while(<W>) {
    print "Received: $_\n";
    chop;
    if($_=~/encode/) { last; }
    if($_=~/save/) { 
      $save=1; 
      system "dcop $kmdr KommanderIf changeWidgetText ExecButton8 \"Saving ...\"";
      last; 
    }
  }
  print "encode found!\n";
  system "dcop $kmdr KommanderIf setCurrentItem TabWidget1 4";

  # pull and save the values from the GUI 
  open RC, "> $ENV{HOME}/.3gpwizrc2";
  for $f (@fields) {
    $cmd="text";
    if($f=~/^T/) { $cmd="checked"; }
    $x=`dcop $kmdr KommanderIf $cmd $f`;
    chop $x;
    print "$f=$x ($cmd)\n";
    $field{$f}=$x;
    print RC "$f=$field{$f}\n";
  }
  close RC; 
}

if($save) {
  system "dcop $kmdr MainApplication-Interface quit";
  exit 0;
}

if(!$field{Foutput} && $field{Tdir} eq "false") { print "no output dir defined\n"; exit 1;}
if($field{Tdir} eq "true") { $odir=$sdir; } else { $odir=$field{Foutput}; } $odir=~s/\/$//g;

if($field{Tsplit} eq "true") {$length=$field{Ssplit};} else {$length=10000; }

$subf="$D[$field{Gcrop}]";
if($field{Tsubtitles} eq "true") { 
  $sub="-font \"$field{Ffont}\" -subfont-text-scale $field{Escale} -sub \"$field{Fsubtitle}\""; $subf="0:1"; 
}

if(!$quick) {
  system "dcop $kmdr KommanderIf setEnabled ProgressBar1 1";
  system "dcop $kmdr KommanderIf setEnabled Lencoding 1";
  system "dcop $kmdr KommanderIf setEnabled Le1 1";
  system "dcop $kmdr KommanderIf setEnabled Le2 1";
}

$fps=$field{Efps};

if($field{Teq} eq "true") { 
  $gamma=$field{Sgamma}/10;
  $contrast=$field{Scontrast}/10;
  $brightnes=$field{Sbrightnes}/10;
  $saturation=$field{Ssaturation}/10;
  $eq2="-vf-add eq2=$gamma:$contrast:$brightnes:$saturation";
} else { $eq2=""; }

if($field{Tmp4} eq "true") { $mp4=1; }
if($field{Taac} eq "true") { $aac=1; }

  $in=$field{Lsource};

  $p=0;
  $opp=0;
  if(!$quick) {
    system "dcop $kmdr KommanderIf setText Lencoding \"Preprocessing video ...\"";
    system "dcop $kmdr KommanderIf setEnabled preview1 1";
    system "dcop $kmdr KommanderIf changeWidgetText temp $tmpfile.avi";
  }

if($field{Tskip} eq "false") {
  $gain=sprintf("%+ddb",$field{Egain});
  if($field{Tvolnorm} eq "true") { $volnorm=",volnorm"; }
  if($field{Tflip} eq "true") { $flip="-flip"; }
  if(!$aac) { $resample="resample=8000,volume="; $oac="pcm"; } else { $resample="volume="; $oac="pcm"; }
     print "mencoder \"$in\" $sub -oac $oac -af $resample$gain:sc$volnorm -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=400 -vf $vf[$field{Gcrop}]$subf $eq2 -o $tmpfile.avi -ofps $fps $flip \n";
  open ME, "mencoder \"$in\" $sub -oac $oac -af $resample$gain:sc$volnorm -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=400 -vf $vf[$field{Gcrop}]$subf $eq2 -o $tmpfile.avi -ofps $fps $flip 2>&1 | perl -pe 's/\r/\n/g;' |";
  while(<ME>) {
    print;
    if(!$quick) {
      chop;
      if(/(\d+)%\)/) { 
        $pp=$1; 
        if($pp>$opp) {
          print "dcop $kmdr KommanderIf changeWidgetText ProgressBar1 $pp\n";
          system "dcop $kmdr KommanderIf changeWidgetText ProgressBar1 $pp";
          $opp=$pp;
        }
      }
    }
  }
  close ME;
}
  if(!$quick) { system "dcop $kmdr KommanderIf changeWidgetText ProgressBar1 100"; }
  
  #$d=`ffplay -stats -an -vn -nodisp $tmpfile.avi 2>&1 | grep Duration`;
  #if($d=~/(\d\d):(\d\d):(\d\d)/) { $h=$1; $m=$2; $s=$3; $M=$h*60+$m+$s/60; } else { exit; }
  $M=$L/60;
  print ">>>>>> Movie length: $M minutes\n";
  $i=0;
  $np=int($M/$length)+1;
  $step=100/$np/2;
  if(!$quick) {
    system "dcop $kmdr KommanderIf setEnabled ProgressBar2 1";
    system "dcop $kmdr KommanderIf setText Lencoding \"Encoding ...\"";
  }
  for($m=0;$m<$M;$m=$m+$length) {
    $i++;
    $ss=$m*60;
    $stop=$length*60+5;
    print "\n===============\nTranscoding part $i ($m minutes) to 3gp\n====$m:$M:$length============\n";
    system "rm $tmp/3gppass 2> /dev/null";
    
    for $pass (1,2) {
      print "========= Pass $pass ==========\n";
      if(!$quick) { system "dcop $kmdr KommanderIf setText Le2 \"part $i/$np (pass $pass)\""; }
      if($length>$M) { 
        if($mp4) {$out="$odir/$field{Etitle}.mp4"; }  
        else {$out="$odir/$field{Etitle}.3gp"; }  
      } else { 
        if($mp4) {$out="$odir/$field{Etitle}-$i.mp4"; }  
        else {$out="$odir/$field{Etitle}-$i.3gp"; }  
      }
      if(!$aac) { 
        $audio="-ac 1 -ab 12.2k -ar 8000 -acodec libamr_nb"; 
      }
      else { 
        $audio="-ac 1 -ab $field{Skbps2}k -acodec libfaac"; 
      }
      if(!$mp4) { 
        $cmd= "$ffmpeg -y -i $tmpfile.avi -pass $pass -passlogfile $tmpfile -b $field{Skbps}k -ss $ss -t $stop -r $fps $audio -vcodec h263 \"$out\""; 
      }
      else { 
        $cmd= "$ffmpeg -y -i $tmpfile.avi -pass $pass -passlogfile $tmpfile -b $field{Skbps}k -ss $ss -t $stop -r $fps $audio -vcodec mpeg4 \"$out\""; 
      }
      $pp=int((($i-1)*2+$pass)*$step);
      print "\nnp=$np step=$step i=$i pass=$pass pp=$pp\n";
      print "$cmd\n";
      system "$cmd";
      if(!$quick) { system "dcop $kmdr KommanderIf changeWidgetText ProgressBar2 $pp"; }
      if($pass==2) {
        if(!$quick) { 
          system "dcop $kmdr KommanderIf changeWidgetText part \"$out\"";
          system "dcop $kmdr KommanderIf setEnabled preview2 1";
        }
      }
    }
  }

if(!$quick) { 
  system "dcop $kmdr KommanderIf changeWidgetText ProgressBar2 100";
  system "dcop $kmdr MainApplication-Interface quit";
} else { 
  if($tmpfile=~/file/) { system "rm $tmpfile.avi $tmpfile-0.log $tmpfile"; }
}
