# Part of the StreamDVD project
package StreamDVD::Util;

use strict;
use vars qw($VERSION @ISA @EXPORT);

require Exporter;

@ISA = qw(Exporter);
@EXPORT = qw(

);

@EXPORT = qw(
                  DVD_Probe
                  DVD_Analyze
                  DVD_Build
                  DVD_Image
                  DVD_Burn
                  makedir
);


$VERSION = '0.1';

use StreamDVD::Defs;
use StreamDVD::Title;
use StreamDVD::Streams;


sub DVD_Probe {
   my ($c, $p, $reftitle_arr, $ref_text) = @_;
   my $oldtext = $$ref_text;
   my $movietitle = 1;
   my $command = $c->lsdvd() . " -xp " . $c->reader();
   my %lsdvd;


   $command = `$command`;
   $command =~ s/^our//;
   eval($command);

   for( my $i=0 ; $i<=$#{$lsdvd{track}} ; $i++ ) {

      my $t = new StreamDVD::Title;
      $t->length     ( $lsdvd{track}[$i]{length}                                  );
      $t->fps        ( $lsdvd{track}[$i]{fps}                                     );
      $t->aspect     ( $lsdvd{track}[$i]{aspect}                                  );
      $t->angle_count( $lsdvd{track}[$i]{angles}                                  );
      $t->resolution ( $lsdvd{track}[$i]{width} . "x" . $lsdvd{track}[$i]{height} );
      $t->format     ( $lsdvd{track}[$i]{format}                                  );
      $t->titlenum   ( $lsdvd{track}[$i]{ix}                                      );

      for( my $x=0 ; $x<=$#{$lsdvd{track}[$i]{chapter}} ; $x++ ) {
         my $ch = new StreamDVD::Chapter;
         $ch->num   ( $lsdvd{track}[$i]{chapter}[$x]{ix}     );
         $ch->length( $lsdvd{track}[$i]{chapter}[$x]{length} );
         $ch->cell  ( $lsdvd{track}[$i]{chapter}[$x]{cell}   );

         $t->chapter_add($ch);
      }

      for( my $x=0 ; $x<=$#{$lsdvd{track}[$i]{audio}} ; $x++ ) {
         my $a = new StreamDVD::Audio;
         $a->num     ( $lsdvd{track}[$i]{audio}[$x]{ix}           );
         $a->langcode( $lsdvd{track}[$i]{audio}[$x]{langcode}     );
         $a->language( $lsdvd{track}[$i]{audio}[$x]{language}     );
         $a->format  ( $lsdvd{track}[$i]{audio}[$x]{format}       );
         $a->freq    ( $lsdvd{track}[$i]{audio}[$x]{frequency}    );
         $a->quant   ( $lsdvd{track}[$i]{audio}[$x]{quantization} );
         $a->channel ( $lsdvd{track}[$i]{audio}[$x]{channels}     );
         $a->content ( $lsdvd{track}[$i]{audio}[$x]{content}      );
         $a->id      ( $lsdvd{track}[$i]{audio}[$x]{streamid}     );

         $t->audio_add($a);
      }

      for( my $x=0 ; $x<=$#{$lsdvd{track}[$i]{subp}} ; $x++ ) {
         my $s = new StreamDVD::Subtitle;
         $s->num     ( $lsdvd{track}[$i]{subp}[$x]{ix}       );
         $s->langcode( $lsdvd{track}[$i]{subp}[$x]{langcode} );
         $s->language( $lsdvd{track}[$i]{subp}[$x]{language} );
         $s->content ( $lsdvd{track}[$i]{subp}[$x]{content}  );
         $s->id      ( $lsdvd{track}[$i]{subp}[$x]{streamid} );

         $t->subtitle_add($s);
      }

      push @$reftitle_arr, $t;
   }

   $p->title($lsdvd{longest_track});

   return $p->title() -1;
}



sub DVD_Analyze {
   my ($c, $p, $t, $ref_text) = @_;
   my $command = $c->streamanalyze() . " -i " . $c->reader() . " -t " . $t->titlenum();
   my @streamlist;
   my $line;
   my $ok = 0;

   push @streamlist, "0xe0";

   for( my $i=0 ; $i<$t->audio_count() ; $i++ ) {                         # get id's of selected audio streams
      if( $p->audio_selected($i) ) {
         my $a = $t->audio($i);
         push @streamlist, sprintf("0x%x",$a->id());
      }
   }

   for( my $i=0 ; $i<$t->subtitle_count() ; $i++ ) {                      # get id's of selected subtitle streams
      if( $p->subtitle_selected($i) ) {
         my $s = $t->subtitle($i);
         push @streamlist, sprintf("0x%x",$s->id());
      }
   }

   $command .= " -s " . join(",", @streamlist);                           # build commandline
   $command .= " -c " . sprintf("%d",$p->chapter_first()+1);
   if( $p->chapter_first() != $p->chapter_last() ) {
      $command .= "-" . sprintf("%d",$p->chapter_last()+1); }
   $command .= " 2>&1";

   print("Executing: $command\n");

   $SIG{CHLD} = sub{ wait };
   if( open ANALYZE, "$command |" ) {
      while( $line = <ANALYZE> ) {
         if( $line =~ /^Factor\s+:\s+(.*)$/ ) {
            my $factor = $1;
            if( $factor !~ /needed/ ) {
               $p->factor($factor); }
            else {
               $p->factor(1); }

            $ok = 1;
         }
      }
      close(ANALYZE);
   }
   $SIG{CHLD} = 'DEFAULT';

   return $ok;
}



sub DVD_Build {
   my ($c, $p, $t, $ref_text) = @_;
   my $oldtext = $$ref_text;
   my $videofile;
   my $chaptertimes = "-c " . join(",", chaptertimelist($p,$t));
   my $audio_options = "";
   my $subtitle_options = "";
   my $streamdvd_command = $c->streamdvd() . " -i " . $c->reader() . " -t " . $t->titlenum();
   my $streamdvd_options;
   my $linelength = 90;
   my $ok = 0;
   my $command;
   my $line;

   $streamdvd_options = "-c " . sprintf("%d",$p->chapter_first()+1);      # build streamdvd chapter options
   if( $p->chapter_first() != $p->chapter_last() ) {
      $streamdvd_options .= "-" . sprintf("%d",$p->chapter_last()+1); }
   $streamdvd_options .= " -f " . $p->factor() if($p->factor() > 1);
   $streamdvd_options .= " -s 0xe0";

   for( my $i=0 ; $i<$t->audio_count() ; $i++ ) {                         # build audio track options
      if( not $p->audio_selected($i) ) {
         next; }
      my $a = $t->audio($i);
      $audio_options .= $a->format() . "+" . $a->langcode();
      $audio_options .= "," if( (($i+1) < $t->audio_count()) && $p->audio_selected($i+1) );
      $streamdvd_options .= "," . sprintf("0x%x",$a->id());
   }
   if( $audio_options ne "" ) {
      $audio_options = "-a " . $audio_options; }

   for( my $i=0 ; $i<$t->subtitle_count() ; $i++ ) {                      # build subtitle track options
      if( not $p->subtitle_selected($i) ) {
         next; }
      my $s = $t->subtitle($i);
      $subtitle_options .= $s->langcode();
      $subtitle_options .= "," if( ($i+1) < $t->subtitle_count() );
      $streamdvd_options .= "," . sprintf("0x%x",$s->id());
   }
   if( $subtitle_options ne "" ) {
      $subtitle_options  = "-s " . $subtitle_options; }

   $command = $c->dvdauthor() . " -t -o " . $p->dir() . DIR_DVD;
   $command .= " $audio_options $subtitle_options $chaptertimes";
   $command .= " -f '$streamdvd_command $streamdvd_options |' 2>&1";
   print("Executing: $command\n");

   $SIG{CHLD} = sub{ wait };
   if( open AUTHOR, "$command |" ) {
       while( read(AUTHOR, $line, $linelength) ) {
         if( $line =~ /ERR:/ ) {
            $ok = 0;
            last;
         }
         elsif( $line =~ /STAT:\s+VOBU.*(\d+:\d+:\d+)/ ) {
            $$ref_text = $oldtext . "timecode $1"; }
         elsif( $line =~ /STAT:\s+fixing.*(\d+)\%/ ) {
            $$ref_text = $oldtext . "fixing"; }

         main::gui_refresh();
         $ok = 1;
      }
      close(AUTHOR);

      if( $ok ) {
         $command = $c->dvdauthor() . " -T -o " . $p->dir() . DIR_DVD . " && echo SUCCESS";
         print("Executing: $command\n");
         my $result = `$command`;
         if( $result =~ /SUCCESS/ ) {
            $ok = 1; }
         else {
            $ok = 0; }
      }
   }
   $SIG{CHLD} = 'DEFAULT';

   return $ok;
}


sub DVD_Image {
   my ($c, $p, $t, $ref_text) = @_;
   my $oldtext = $$ref_text;
   my $ok = 0;
   my $line;
   my $imagefile = $p->dir() . DIR_ISO . "/movie.iso";
   my $named_pipe = $c->temp_dir() . "/recode.".$$;
   my $command = $c->mkisofs() . " -dvd-video -udf " . $p->dir() . DIR_DVD . " >$imagefile 2>$named_pipe &";

   print("Executing: $command\n");
   system($command);
   sleep(1);

   if( open MKISO, "$named_pipe" ) {
      while( $line = <MKISO> ) {
         if( $line =~ /(\S+)\%/ ) {
            $$ref_text = $oldtext . $1 . " %"; }
         main::gui_refresh();
      }
      close(MKISO);
      $ok = 1 if(-f $imagefile);
   }
   else {
      print("ERROR opening Pipe $named_pipe\n"); }
   unlink $named_pipe;

   if( $ok ) {
      $command = "rm -rf " . $p->dir() . DIR_DVD . " && echo SUCCESS";
      print("Executing: $command\n");
      my $result = `$command`;
      $ok = 0 if($result !~ /SUCCESS/);
   }

   return $ok;
}


# growisofs -Z /dev/scd0 -dvd-video -udf .
# 99.10% done, estimate finish Sun Mar  7 15:26:35 2004
sub DVD_Burn {
   my ($c, $p, $t, $ref_text) = @_;
   my $oldtext = $$ref_text;
   my $ok = 0;
   my $line;
   my $command = $c->growisofs() . " -Z " . $c->writer() . " -dvd-video -udf " . $p->dir() . DIR_DVD . " 2>&1";

   print("Executing: $command\n");
   $SIG{CHLD} = sub{ wait };

   if( open BURN, "$command |" ) {
      while( $line = <BURN> ) {
         if( $line =~ /(.*\%)/ ) {
            $$ref_text = $oldtext . $1; }
         elsif( $line =~ /reloading\s+tray/ ) {
            $ok = 1; }
         main::gui_refresh();
      }
      close(BURN);
   }

   $SIG{CHLD} = 'DEFAULT';

   return $ok;
}



sub chaptertimelist {
   my ($p, $t) = @_;
   my @list;
   my $selected;
   my $i = 0;
   my $time = "";
   my $hour = "";
   my $min = "";
   my $sec = "";
   my $sum = 0;

   $selected = $p->chapter_selected($i);
   while( (defined $selected) && (not $selected) ) {
      $i++;
      $selected = $p->chapter_selected($i);
   }

   push @list, "0";

   while( (defined $selected) && ($selected) ) {
      my $c = $t->chapter($i);
      $sum += $c->length();
      my $value = $sum;
      
      $time = "";
      $hour = "";
      $min = "";

      $hour = int($value / 3600);
      $value -= ($hour * 3600);
      $time .= sprintf("%.2d:", $hour); 

      $min = int($value / 60);
      $value -= ($min * 60);
      $time .= sprintf("%.2d:", $min);

      $sec = int($value);
      $time .= sprintf("%.2d", $sec);

      push @list, $time;
      $i++;
      $selected = $p->chapter_selected($i);
   }
   splice(@list, $#list, 1);

   return @list;
}



sub makedir {
   my ($path) = @_;
   my $ok = 1;
   my @dirnames = split /\//, $path;
   my $temp = "/";

   foreach (@dirnames) {
      $temp .= $_ . "/";
      if( not -d $temp ) {
         if( not mkdir($temp,0755) ) {
            $ok = 0;
            last;
         }
      }
   }

   return $ok;
}








1;

