#!/usr/bin/perl -w
#+
# Name:
#
#
# Funktion:
#
#
# Parameter:
#
#
# Autor:
#   
#
# nderungen:
#   2004-10-25:  Erste Version
#   2005-01-06:  HdR  Configfile, Einstellungsfenster, Bug beim Brennen ohne Image behoben, Testen auf Programme (1.9.1)
#   2005-01-06:  HdR  2% Reserve bei Verkleinerungsfaktor (1.9.2)
#   2005-01-08:  HdR  Fehler beim Rippen von Untertiteln behoben (1.9.3)
#   2005-01-08:  HdR  DVD-Titel aenderbar (1.9.3) 
#   2005-01-08:  HdR  Richtige Reihenfolge bei Audiospuren & Untertiteln (1.9.3)
#   2005-04-23:  HdR  Benoetigte Zeit wird angezeigt
#   2005-04-30:  HdR  Beruecksichtigen des Nice-Werts 
#   2005-06-13:  HdR  Progressbar hinzugefuegt 
#   2005-07-17:  HdR  Bug beim Brennfenster gefixt
#   2006-01-03:  HdR  Optimaler Testrip zur Faktor bestimmung (2.0.2)
#   2006-01-05:  HdR  Videooptinen an dvdauthor uebergeben (2.0.2) 
#-

$| = 1;
use strict;
use Gtk2;
use POSIX;

my $name = "LDVD";
my $sh_name = "ldvd";
my $version = "2.0.2";

sub FALSE () {0};
sub TRUE () {1};
sub NO_PADDING () {0};
sub NO_SPACING () {0};

sub LANG_LOAD ($);
sub SETTINGS_LOAD ($);

sub READ_DVD ();

sub TITLE_LABELS ();
sub TITLE_SELECT ($);

sub SET_AUDIO ($);
sub AUDIO_SELECT ($);
sub SET_SUB ($);
sub SUB_SELECT ($);
sub TITLE_RIP ($);

sub FAKTOR ();
sub TESTRIP ();

sub BUILD_DVD();

sub ende ();

sub STD_SEK ($);
sub SEK_STD ($);
sub COMMAND ($);

sub BR_MODE ($);
sub BR_SELECTION ($);
sub BR_SELECT_IMAGE ();
sub BR_COMPAT ();
sub SET_BRUN_SPEED ($);

sub BURN_DVD ();

sub SAVE_SETTINGS ();

sub CHECK_PROGRAM ($);
sub NEEDED_TIME ($);

sub STATUS ();
sub DIR_SIZE ($);

sub SE_TEST_RIP ();

my %LANG;
my %SETTINGS;
$SETTINGS{'LANG'} = "en";

my ($FORK, $FORK2);

my %DVD_INFO;
my @DVD_RIP;
my ($akt_title, $akt_audio, $akt_sub);
my $trip = 0;

my (@items, @audio_items, @sub_items);

$SETTINGS{'DVD_PATH'} = "/dev/dvd";
$SETTINGS{'PATH'} = "./dvd";
$SETTINGS{'DVD_BURN_DEVICE'} = "/dev/dvd";
$SETTINGS{'DVD_COMPAT'} = 1;
$SETTINGS{'BURN_SPEED'} = 0;
$SETTINGS{'BURN_MODE'} = 1;
$SETTINGS{'DVD_SIZE'} = 4600000000;
$SETTINGS{'TEST_RIP'} = 1;

$SETTINGS{'P_LDVD_LS'} = "ldvd-ls";
$SETTINGS{'P_MPLEX'} = "mplex";
$SETTINGS{'P_BUFFER'} = "buffer";
$SETTINGS{'P_TCEXTRACT'} = "tcextract";
$SETTINGS{'P_TCREQUANT'} = "tcrequant";
$SETTINGS{'P_TCCAT'} = "tccat";
$SETTINGS{'P_DVDAUTHOR'} = "dvdauthor";
$SETTINGS{'P_SPUUNMUX'} = "spuunmux";
$SETTINGS{'P_SPUMUX'} = "spumux";
$SETTINGS{'P_MKISOFS'} = "mkisofs";
$SETTINGS{'P_GROWISOFS'} = "growisofs";

$SETTINGS{'NICE'} = 10;

SETTINGS_LOAD ("/etc/ldvd.conf");
SETTINGS_LOAD ($ENV{'HOME'} . "/.ldvd/ldvd.conf");

# LANG_LOAD ("./" . $SETTINGS{'LANG'} . ".lang");
LANG_LOAD ("/usr/share/$sh_name-$version/" . $SETTINGS{'LANG'} . ".lang");

my $dvd_info = 0;

##### Fenster ###################

my $table_r = 6;
my $table_u = 13;

# 1. Initialisieren von Gtk

Gtk2->init;
set_locale Gtk2;

# 2. Create Widgets, set Attributes
# 2. a

my $window = new Gtk2::Window( "toplevel" );
my $table = new Gtk2::Table ($table_u, $table_r, TRUE);

my $hseparator = new Gtk2::HSeparator();

my $menubar = new Gtk2::MenuBar ();
my $datei_item = new Gtk2::MenuItem ($LANG{'MENU_FILE'});
my $datei_menu = new Gtk2::Menu ();
my $datei_beenden = new Gtk2::MenuItem ($LANG{'MENU_FILE_EXIT'});
my $option_item = new Gtk2::MenuItem ($LANG{'MENU_OPTIONS'});
  my $option_menu = new Gtk2::Menu ();
my $option_settings = new Gtk2::MenuItem ($LANG{'MENU_OPTIONS_SETTINGS'});

my $handlebox = new Gtk2::HandleBox();

my $toolbar = new Gtk2::Toolbar();
$toolbar->set_orientation('horizontal');
$toolbar->set_style('both');

my $style = $window->get_style()->bg( 'normal' );
$window->realize;
my $pixmapwid = Gtk2::Image->new_from_icon_name('go-jump', 'small-toolbar');
$pixmapwid->show();
my $menu_readdvd = Gtk2::Toolbar::append_item ($toolbar, $LANG{'READ_DVD'}, $LANG{'READ_DVD_TOOLTIP'}, "privat", $pixmapwid);

$pixmapwid = Gtk2::Image->new_from_icon_name('drive-cdrom', 'small-toolbar');
$pixmapwid->show();
my $menu_builddvd = Gtk2::Toolbar::append_item ($toolbar, $LANG{'BUILD_DVD'}, $LANG{'BUILD_DVD_TOOLTIP'}, "privat", $pixmapwid);

$pixmapwid = Gtk2::Image->new_from_icon_name('media-cdrom', 'small-toolbar');
$pixmapwid->show();
my $menu_burndvd = Gtk2::Toolbar::append_item ($toolbar, $LANG{'BURN_DVD'}, $LANG{'BURN_DVD_TOOLTIP'}, "privat", $pixmapwid);

my $align = new Gtk2::Alignment( 0, 0, 1, 1);
#my $adj = new Gtk2::Adjustment( 0, 0, 1, 0, 0, 0 );
my $pbar = new Gtk2::ProgressBar(); #$adj

my $label_title = new Gtk2::Label ($LANG{'TITLE'});
my $entry_title = Gtk2::Entry->new_with_max_length(32);

my $paned = new Gtk2::HPaned();
my $scrolled_l = new Gtk2::ScrolledWindow(undef,undef);
my $scrolled_r = new Gtk2::ScrolledWindow(undef,undef);

my $list_l = new Gtk2::List();

my $vbox_r = new Gtk2::VBox (FALSE, NO_PADDING);
my $label_topt = new Gtk2::Label ($LANG{'TITLE_SELECT'} . ":");

my $frame_audio = new Gtk2::Frame ($LANG{'AUDIO_SELECT'});
my $hbox_a = new Gtk2::HBox (FALSE, NO_PADDING);
my $opt_a_source = new Gtk2::OptionMenu ();
my $opt_a_source_m = new Gtk2::Menu ();
my $label_a = new Gtk2::Label (' => ');
my $opt_a_target = new Gtk2::OptionMenu ();
my $opt_a_target_m = new Gtk2::Menu ();

my $frame_sub = new Gtk2::Frame ($LANG{'SUBTITLE_SELECT'});
my $hbox_s = new Gtk2::HBox (FALSE, NO_PADDING);
my $opt_s_source = new Gtk2::OptionMenu ();
my $opt_s_source_m = new Gtk2::Menu ();
my $label_s = new Gtk2::Label (' => ');
my $opt_s_target = new Gtk2::OptionMenu ();
my $opt_s_target_m = new Gtk2::Menu ();

my $button_rip_title_0 = new Gtk2::Button ($LANG{'BUTTON_RIP_0'});
my $button_rip_title_1 = new Gtk2::Button ($LANG{'BUTTON_RIP_1'});

my $statusbar = new Gtk2::Statusbar();

my $timer = Glib::Timeout->add( 100, \&STATUS);

### BurnWindow ###

my $br_window = new Gtk2::Window -toplevel; $br_window->set_title ($LANG{'BR_TITLE'});
my $br_table = new Gtk2::Table (4, 4, TRUE); ### (u, r, 1)
$br_window->add ($br_table);
$br_table->show;

my $br_radio = new Gtk2::RadioButton ($LANG{'BR_IMAGE'});
$br_radio->signal_connect ("clicked" => \&BR_MODE, 1);
$br_table->attach_defaults ($br_radio, 0, 1, 0, 1);
$br_radio->show;

$br_radio = new Gtk2::RadioButton ($LANG{'BR_BURN'}, $br_radio);
$br_radio->signal_connect ("clicked" => \&BR_MODE, 2);
$br_table->attach_defaults ($br_radio, 1, 2, 0, 1);
$br_radio->show;

$br_radio = new Gtk2::RadioButton ($LANG{'BR_BURN_I'}, $br_radio);
$br_radio->signal_connect ("clicked" => \&BR_MODE, 3);
$br_table->attach_defaults ($br_radio, 2, 4, 0, 1);
$br_radio->show;

my $br_label_image = new Gtk2::Label ($LANG{'BR_IMAGE_FILE'});
$br_table->attach_defaults ($br_label_image, 0, 1, 1, 2);
$br_label_image->show;

my $br_entry = new Gtk2::Entry ();
$br_table->attach_defaults ($br_entry, 1, 3, 1, 2);
$br_entry->show;

my $br_button = new Gtk2::Button ($LANG{'BR_SELECT'});
$br_button->signal_connect ("clicked" => \&BR_SELECTION, 1);
$br_table->attach_defaults ($br_button, 3, 4, 1, 2);
$br_button->show;

my $file_dialog = new Gtk2::FileSelection($name . " - " . $version);
$file_dialog->signal_connect("destroy" => \&BR_SELECTION, 0);
$file_dialog->ok_button->signal_connect("clicked" => \&BR_SELECT_IMAGE);
$file_dialog->cancel_button->signal_connect( "clicked" => \&BR_SELECTION, 0);

my $br_label_brenner = new Gtk2::Label ($LANG{'BR_BURN_DEVICE'});
$br_table->attach_defaults ($br_label_brenner, 0, 1, 2, 3);
$br_label_brenner->show;

my $brenner_entry = new Gtk2::Entry ();
$brenner_entry->set_text ($SETTINGS{'DVD_BURN_DEVICE'});
$br_table->attach_defaults ($brenner_entry, 1, 3, 2, 3);
$brenner_entry->show;

my $br_dvd_compat = new Gtk2::CheckButton ("-dvd-compat");
$br_dvd_compat->signal_connect("clicked" => \&BR_COMPAT);
$br_table->attach_defaults ($br_dvd_compat, 3, 4, 2, 3);
$br_dvd_compat->show;

my $br_label_speed = new Gtk2::Label ($LANG{'BR_SPEED'});
$br_table->attach_defaults ($br_label_speed, 0, 1, 3, 4);
$br_label_speed->show;

my $br_opt_speed = new Gtk2::OptionMenu ();
$br_table->attach_defaults ($br_opt_speed, 1, 2, 3, 4);
my $br_opt_menu = new Gtk2::Menu ();
$br_opt_speed->set_menu ($br_opt_menu);

my $br_item = new Gtk2::MenuItem ("auto");
$br_item->signal_connect ('activate' => \&SET_BRUN_SPEED, 0);
$br_opt_menu->append ($br_item);

$br_opt_menu->select_item ($br_item);
$br_item->show;
$br_opt_speed->show;

for (my $n = 1; $n <= 16; $n *= 2)
{ $br_item = new Gtk2::MenuItem ($n . "x");
  $br_item->signal_connect ('activate' => \&SET_BRUN_SPEED, $n);
  $br_opt_menu->append ($br_item);
  $br_item->show;
}

my $br_burn = new Gtk2::Button ($LANG{'BR_BURN'});
$br_burn->signal_connect ('clicked' => \&BURN_DVD);
$br_table->attach_defaults ($br_burn, 2, 3, 3, 4);
$br_burn->show;

my $br_close = new Gtk2::Button ($LANG{'BR_CLOSE'});
$br_close->signal_connect ('clicked' => sub {$br_window->hide});
$br_table->attach_defaults ($br_close, 3, 4, 3, 4);
$br_close->show;

$br_label_image->set_sensitive(1);
$br_entry->set_sensitive(1);
$br_button->set_sensitive(1);

$br_label_brenner->set_sensitive(0);
$brenner_entry->set_sensitive(0);
$br_dvd_compat->set_sensitive(0);
$br_label_speed->set_sensitive(0);
$br_opt_speed->set_sensitive(0);

###### Settings #####
my $se_window = new Gtk2::Window ("toplevel");
$se_window->set_title ($LANG{'SE_TITLE'});

my $se_table = new Gtk2::Table (8, 4, TRUE);
$se_window->add ($se_table);
$se_table->show;

my $se_lang_label = new Gtk2::Label ($LANG{'SE_LANG'});
$se_table->attach_defaults ($se_lang_label, 0, 1, 0, 1);
$se_lang_label->show;

my $se_opt_lang = new Gtk2::OptionMenu ();
$se_table->attach_defaults ($se_opt_lang, 1, 4, 0, 1);
$se_opt_lang->show;

my $se_opt_menu = new Gtk2::Menu ();
$se_opt_lang->set_menu ($se_opt_menu);

if (-d "/usr/share/$sh_name-$version")
{ opendir(DIR, "/usr/share/$sh_name-$version/");
  my @dir = readdir (DIR);
  closedir(DIR);

  @dir = sort (@dir);
  for (@dir)
  { my $file = $_;
    if ($file =~ /\.lang$/)
    { $file = $`;
      my $se_item = new Gtk2::MenuItem ($file);
      $se_opt_menu->append ($se_item);
      $se_item->signal_connect ('activate' => sub {$SETTINGS{'LANG'} = $file; });
      $se_item->show;
    }
  }
}

my $se_label_dvd = new Gtk2::Label ($LANG{'SE_DVD'});
$se_table->attach_defaults ($se_label_dvd, 0, 1, 1, 2);
$se_label_dvd->show;

my $se_entry_dvd = new Gtk2::Entry ();
$se_table->attach_defaults ($se_entry_dvd, 1, 4, 1, 2);
$se_entry_dvd->set_text ($SETTINGS{'DVD_PATH'});
$se_entry_dvd->show;

my $se_label_dvd_device = new Gtk2::Label ($LANG{'SE_DVD_BURN_DEVICE'});
$se_table->attach_defaults ($se_label_dvd_device, 0, 1, 2, 3);
$se_label_dvd_device->show;

my $se_entry_dvd_device = new Gtk2::Entry ();
$se_table->attach_defaults ($se_entry_dvd_device, 1, 4, 2, 3);
$se_entry_dvd_device->set_text ($SETTINGS{'DVD_BURN_DEVICE'});
$se_entry_dvd_device->show;

my $se_label_path = new Gtk2::Label ($LANG{'SE_PATH'});
$se_table->attach_defaults ($se_label_path, 0, 1, 3, 4);
$se_label_path->show;

my $se_entry_path = new Gtk2::Entry ();
$se_table->attach_defaults ($se_entry_path, 1, 4, 3, 4);
$se_entry_path->set_text ($SETTINGS{'PATH'});
$se_entry_path->show;

my $se_label_size = new Gtk2::Label ($LANG{'SE_DVD_SIZE'});
$se_table->attach_defaults ($se_label_size, 0, 1, 4, 5);
$se_label_size->show;

my $se_entry_size = new Gtk2::Entry ();
$se_table->attach_defaults ($se_entry_size, 1, 4, 4, 5);
$se_entry_size->set_text ($SETTINGS{'DVD_SIZE'});
$se_entry_size->show;

my $se_label_nice = new Gtk2::Label ($LANG{'SE_NICE'});
$se_table->attach_defaults ($se_label_nice, 0, 1, 5, 6);
$se_label_nice->show;

my $se_adj_nice = new Gtk2::Adjustment ($SETTINGS{'NICE'}, -20, 19, 1, 1, 0);
my $spin = new Gtk2::SpinButton ($se_adj_nice, 0, 0);
$spin->set_wrap (TRUE);
#$spin->set_shadow_type ('out');
$se_table->attach_defaults ($spin, 1, 4, 5, 6);
$spin->show;

my $se_testrip = new Gtk2::CheckButton ($LANG{'SE_TEST_RIP'});
if ($SETTINGS{'TEST_RIP'})
{ $se_testrip->set_active(1);
}
$se_testrip->signal_connect("clicked" => \&SE_TEST_RIP);
$se_table->attach_defaults ($se_testrip, 1, 2, 6, 7);
$se_testrip->show;

my $se_save = new Gtk2::Button ($LANG{'SE_SAVE'});
$se_save->signal_connect( "clicked" => \&SAVE_SETTINGS);
$se_table->attach_defaults ($se_save, 2, 3, 7, 8);
$se_save->show;

my $se_close = new Gtk2::Button ($LANG{'SE_CLOSE'});
$se_close->signal_connect( "clicked" => sub {$se_window->hide;});
$se_table->attach_defaults ($se_close, 3, 4, 7, 8);
$se_close->show;

###########################################################
# 2. b

$window->set_title ("$name $version");
$window->set_size_request (500, 275);

$scrolled_l->set_policy('automatic', 'always');
$scrolled_r->set_policy('automatic', 'always');

#$pbar->set_format_string( "%v MB " . $LANG{'PROGRESS_FROM'} . "  ~ %u MB (~ %p%%)" );
#$pbar->set_show_text(1);

# 3. Callbacks

$window->signal_connect ('destroy' => \&ende);

$datei_beenden->signal_connect ('activate' => \&ende);
$option_settings->signal_connect ('activate' => sub {$se_window->show;});

$menu_readdvd->signal_connect( "clicked", \&READ_DVD);
# $menu_builddvd->signal_connect( "clicked", \&FAKTOR);
$menu_builddvd->signal_connect( "clicked", \&BUILD_DVD);
$menu_burndvd->signal_connect( "clicked" => sub {$br_window->show;});

$entry_title->signal_connect( "changed" => sub {$DVD_INFO{'DISC_TITLE'} = $entry_title->get_text (); });

$button_rip_title_0->signal_connect( "clicked", \&TITLE_RIP, 0);
$button_rip_title_1->signal_connect( "clicked", \&TITLE_RIP, 1);

# 4. Defining the Instance Hierachy

$window->add ($table);
$table->attach_defaults ($menubar, 0, $table_r, 0, 1);
$table->attach_defaults ($handlebox, 0, $table_r, 1, 3);
$table->attach_defaults ($align, 0, $table_r, 3, 4);
$table->attach_defaults ($label_title, 0, 1, 4, 5);
$table->attach_defaults ($entry_title, 1, $table_r, 4, 5);
$table->attach_defaults ($paned, 0, $table_r, 5, 12);
$table->attach_defaults ($statusbar, 0, $table_r, 12, 13);


$menubar->append ($datei_item);
$menubar->append ($option_item);

$datei_item->set_submenu ($datei_menu);
$datei_menu->append ($datei_beenden);

$option_item->set_submenu ($option_menu);
$option_menu->append ($option_settings);

$handlebox->add($toolbar);

$align->add ($pbar);

$paned->add1($scrolled_l);
$paned->add2($scrolled_r);
$scrolled_l->add_with_viewport($list_l);
$scrolled_r->add_with_viewport($vbox_r);

$vbox_r->pack_start ($label_topt, FALSE, FALSE, 2);
$vbox_r->pack_start ($hseparator, FALSE, FALSE, 2);
$vbox_r->pack_start ($frame_audio, FALSE, FALSE, 2);
$vbox_r->pack_start ($frame_sub, FALSE, FALSE, 2);
$vbox_r->pack_start ($button_rip_title_0, FALSE, FALSE, 2);
$vbox_r->pack_start ($button_rip_title_1, FALSE, FALSE, 2);

$frame_audio->add ($hbox_a);
$hbox_a->pack_start ($opt_a_source, TRUE, TRUE, 2);
$hbox_a->pack_start ($label_a, FALSE, FALSE, 2);
$hbox_a->pack_start ($opt_a_target, TRUE, TRUE, 2);

$opt_a_source->set_menu ($opt_a_source_m);
$opt_a_target->set_menu ($opt_a_target_m);

$frame_sub->add ($hbox_s);
$hbox_s->pack_start ($opt_s_source, TRUE, TRUE, 2);
$hbox_s->pack_start ($label_s, FALSE, FALSE, 2);
$hbox_s->pack_start ($opt_s_target, TRUE, TRUE, 2);

$opt_s_source->set_menu ($opt_s_source_m);
$opt_s_target->set_menu ($opt_s_target_m);

# 5. Showing the Widgets

$statusbar->show;

$button_rip_title_0->show;

$opt_s_target_m->show;
$opt_s_target->show;
$opt_a_target_m->show;
$opt_a_target->show;

$opt_s_source_m->show;
$opt_s_source->show;
$opt_a_source_m->show;
$opt_a_source->show;

$label_s->show;
$label_a->show;

$hbox_s->show;
$hbox_a->show;
$frame_sub->show;
$frame_audio->show;
$label_topt->show;
$vbox_r->show;
$scrolled_r->show;

$list_l->show;
$scrolled_l->show;

$paned->show;

$entry_title->show;
$label_title->show;

$pbar->show();
$align->show();

$menu_builddvd->show;
$menu_readdvd->show;
$toolbar->show;
$handlebox->show;

$option_settings->show;
$option_menu->show;
$option_item->show;

$datei_beenden->show;
$datei_menu->show;
$datei_item->show;

$menubar->show;

$hseparator->show;
$table->show;
$window->show;

main Gtk2;

###############################

sub LANG_LOAD ($)
{ my $lang_file = shift;
  if (-r $lang_file)
  { open (LANG_DAT, $lang_file);
    my @lines = <LANG_DAT>;
    close (LANG_DAT);
  
    my $length = @lines+0;
    my $loop = 0;
  
    while ($loop < $length)
    { chop $lines[$loop];
      my ($par, $value) = (split /=/, $lines[$loop]);
      $LANG{$par} = $value;
      ++$loop;
    }
  
    print "$LANG{'LANG_LOADED'}, $LANG{'LANG2'} ($LANG{'LANG'})!\n";
  }
  else
  { print "Couldn't load the Language file please check $lang_file!\n";
  
    exit;
  }
}

sub SETTINGS_LOAD ($)
{ my $conf = shift;
  if (-r $conf)
  { open (CONF, $conf);
    my @lines = <CONF>;
    close (CONF);

    for (my $i = 0; $i < @lines+0; ++$i)
    { chop $lines[$i];
      my ($par, $value) = (split /=/, $lines[$i]);
      $SETTINGS{$par} = $value;
    }
  }
  else
  { print "Couldn't open configfile \"$conf\"\n";
  }
}
sub READ_DVD ()
{ if ($dvd_info == 0)
  { my $dvd_drive = $SETTINGS{'DVD_PATH'};
    print "$dvd_drive\n";
  
    open (LSDVD, $SETTINGS{'P_LDVD_LS'} . " -ancsv " . $dvd_drive . " |");
    my @info_lines = <LSDVD>;
    close (LSDVD);

    if ((split /\|/, $info_lines[((@info_lines+0)-1)])[0] eq "DVDSize")
    { my $loop = 0;
      my $length = @info_lines+0;
    
      my (@aline, $disc_title, @palette, @title_length, @audio, @chapters, @sectors, @chap_sectors, @subtitle, $longest, @vidopts, $size);
    
      while ($loop < $length)
      { chop $info_lines[$loop];
    
        if ($info_lines[$loop] ne "")
        { @aline = (split /\|/, $info_lines[$loop]); 
    
          if ($aline[0] eq "Disc Title")
          { $disc_title = $aline[1];
          }
    
          if ($aline[1] eq "VTS" && $aline[17] eq "Palette")
          { $palette[$aline[0]] = $aline[18];
            my $format = $aline[8];
            $format =~ tr/A-Z/a-z/;
            my $ratio = $aline[10];
            $ratio =~ s/\//:/;
            my $df;
            if ($aline[16] eq "Letterbox")
            { $df = "nopanscan";
            }
            else
            { $df = "noletterbox";
            }
            $vidopts[$aline[0]] = "$format+$ratio+$df+" . $aline[12] . "x" . $aline[14];
          }
    
          if ($aline[1] eq "Length")
          { $title_length[$aline[0]] = STD_SEK ($aline[2]);
          }
          elsif ($aline[1] eq "Audio")
          { $audio[$aline[0]]->[$aline[2]]->{'LANG'} = $aline[4];
            $audio[$aline[0]]->[$aline[2]]->{'FORMAT'} = $aline[7];
            $audio[$aline[0]]->[$aline[2]]->{'FREQ'} = $aline[9];
            $audio[$aline[0]]->[$aline[2]]->{'CHANNELS'} = $aline[13];
            $audio[$aline[0]]->[$aline[2]]->{'CONTENT'} = $aline[17];
          }
          elsif ($aline[1] eq "Chapter")
          { $chapters[$aline[0]]->[$aline[2]] = $aline[4];
            $chap_sectors[$aline[0]]->[$aline[2]] = $aline[8] + 0;
          }
          elsif ($aline[1] eq "Total Sectors")
          { $sectors[$aline[0]] = $aline[2];
          }
          elsif ($aline[1] eq "Subtitle")
          { $subtitle[$aline[0]]->[$aline[2]]->{'LANG'} = $aline[4];
            $subtitle[$aline[0]]->[$aline[2]]->{'CONTENT'} = $aline[7];
          }
    
          if ($aline[0] eq "Longest track")
          { $longest = $aline[1];
          }

          if ($aline[0] eq "DVDSize")
          { $size = $aline[1];

          }
        }
        ++$loop;
      }
      $DVD_INFO{'DISC_TITLE'} = $disc_title;
      $DVD_INFO{'PALETTE'} = \@palette;
      $DVD_INFO{'TITLE_LENGTH'} = \@title_length;
      $DVD_INFO{'AUDIO'} = \@audio;
      $DVD_INFO{'CHAPTERS'} = \@chapters;
      $DVD_INFO{'SECTOR'} = \@sectors;
      $DVD_INFO{'CHAP_SECTORS'} = \@chap_sectors;
      $DVD_INFO{'SUBTITLE'} = \@subtitle;
      $DVD_INFO{'LONGEST_TITLE'} = $longest;
      $DVD_INFO{'VIDOPTS'} = \@vidopts;
      $DVD_INFO{'DVD_SIZE'} = $size;
    
      $entry_title->set_text ($DVD_INFO{'DISC_TITLE'});
    
      #### Gren berechnen ####
    
      for (my $i = 1; $i < @title_length+0; ++$i)
      { my $tmp_size = 0;
        my $audio_length = defined $audio[$i]? @{$audio[$i]}+0: 0;
        for (my $u = 1; $u < $audio_length; ++$u)
        { if ($DVD_INFO{'AUDIO'}->[$i]->[$u]->{'FORMAT'} eq "ac3")
          { if ($DVD_INFO{'AUDIO'}->[$i]->[$u]->{'CHANNELS'} eq "1" || $DVD_INFO{'AUDIO'}->[$i]->[$u]->{'CHANNELS'} eq "2")
            { $DVD_INFO{'AUDIO_SIZE'}->[$i]->[$u] = $DVD_INFO{'TITLE_LENGTH'}->[$i]*128*125;
              $tmp_size += $DVD_INFO{'AUDIO_SIZE'}->[$i]->[$u];
            }
            else
            { $DVD_INFO{'AUDIO_SIZE'}->[$i]->[$u] = $DVD_INFO{'TITLE_LENGTH'}->[$i]*384*125;
              $tmp_size += $DVD_INFO{'AUDIO_SIZE'}->[$i]->[$u];
            }
          }
          else   # dts: 786
          { $DVD_INFO{'AUDIO_SIZE'}->[$i]->[$u] = $DVD_INFO{'TITLE_LENGTH'}->[$i]*786*125;
            $tmp_size += $DVD_INFO{'AUDIO_SIZE'}->[$i]->[$u];
          }
        }
        $DVD_INFO{'VIDEO_SIZE'}->[$i] = $DVD_INFO{'SECTOR'}->[$i] * 2048 - $tmp_size;
      }
  
      $dvd_info = 1;
    
      TITLE_LABELS;
    }
    else
    { print $LANG{'ERROR_NO_DVD'} . "\n";
    }
  }
}

sub TITLE_LABELS ()
{ my @title_length = @{$DVD_INFO{'TITLE_LENGTH'}};
  
  my $length = @title_length+0;
  my $loop = 1;
  my $label;

  while ($loop < $length)
  { $label = sprintf("%3d - ", $loop) . SEK_STD($title_length[$loop]);
    
    $items[$loop] = new Gtk2::ListItem($label);
    $items[$loop]->signal_connect ('select' => \&TITLE_SELECT, $loop);

    $list_l->add($items[$loop]);

    $items[$loop]->show;

    $DVD_RIP[$loop]->{'RIP'} = 0;

    ++$loop;
  }

  $list_l->select_child($items[$DVD_INFO{'LONGEST_TITLE'}]);
}

sub TITLE_SELECT ($)
{ shift;

  $akt_title = shift;
  $label_topt->set_text($LANG{'TITLE_SELECT'} . " - " . $akt_title . ":");
  
  ### Audio ###

  my @audio = @{$DVD_INFO{'AUDIO'}->[$akt_title]};

  my $length = @audio+0;
  my $loop = 1;

  $opt_a_source->remove_menu ();
  $opt_a_source_m = new Gtk2::Menu ();
  $opt_a_source->set_menu ($opt_a_source_m);

  while ($loop < $length)
  { my $item = new Gtk2::MenuItem ($loop . ": " . $audio[$loop]->{'LANG'} . " " . $audio[$loop]->{'FORMAT'} . " " 
     . ($audio[$loop]->{'FREQ'}/1000) . "kHz " . $audio[$loop]->{'CHANNELS'} . "Ch");
    $opt_a_source_m->append ($item);
    $item->signal_connect ('activate' => \&SET_AUDIO, $loop);
    $item->show;

    ++$loop;
  }

  ### Subtitle ###

  $opt_s_source->remove_menu ();
  $opt_s_source_m = new Gtk2::Menu ();
  $opt_s_source->set_menu ($opt_s_source_m);

  if (defined @{$DVD_INFO{'SUBTITLE'}->[$akt_title]})
  { my @subtitle = @{$DVD_INFO{'SUBTITLE'}->[$akt_title]};

    $length = @subtitle+0;
    $loop = 1;
  
    while ($loop < $length)
    { my $item = new Gtk2::MenuItem ($loop . ": " . $subtitle[$loop]->{'LANG'} . " " . $subtitle[$loop]->{'CONTENT'});
      $opt_s_source_m->append ($item);
      $item->signal_connect ('activate' => \&SET_SUB, $loop);
      $item->show;
  
      ++$loop;
    }
  }

  if ($DVD_RIP[$akt_title]->{'RIP'} != 1)
  { $button_rip_title_0->show;
    $button_rip_title_1->hide;
  }
  else
  { $button_rip_title_0->hide;
    $button_rip_title_1->show;
  }

  $opt_a_source->set_sensitive(0);
  $opt_a_target->set_sensitive(0);
  $opt_s_source->set_sensitive(0);
  $opt_s_target->set_sensitive(0);
}

sub SET_AUDIO ($)
{ shift;
  $akt_audio = shift;

  my $length = @{$DVD_INFO{'AUDIO'}->[$akt_title]}+0;
  my $loop = 1;

  $opt_a_target->remove_menu ();
  $opt_a_target_m = new Gtk2::Menu ();
  $opt_a_target->set_menu ($opt_a_target_m);

  $audio_items[0] = new Gtk2::MenuItem ($LANG{'LABEL_A_TARGET_NONE'});
  $opt_a_target_m->append ($audio_items[0]);
  $audio_items[0]->signal_connect ('activate' => \&AUDIO_SELECT, 0);
  $audio_items[0]->show;

  while ($loop < $length)
  { $audio_items[$loop] = new Gtk2::MenuItem ($LANG{'LABEL_A_TARGET'} . ": " . $loop);
    $opt_a_target_m->append ($audio_items[$loop]);
    $audio_items[$loop]->signal_connect ('activate' => \&AUDIO_SELECT, $loop);
    $audio_items[$loop]->show;

    ++$loop;
  }

  foreach my $akt (@{$DVD_RIP[$akt_title]->{'AUDIO'}})
   { if (defined $akt && $akt != 0 && (!defined $DVD_RIP[$akt_title]->{'AUDIO'}->[$akt_audio] || $akt != $DVD_RIP[$akt_title]->{'AUDIO'}->[$akt_audio]))
     { $audio_items[$akt]->set_sensitive(0); 
     }
   }

  if (defined $DVD_RIP[$akt_title]->{'AUDIO'}->[$akt_audio])
  { $opt_a_target->set_history ($DVD_RIP[$akt_title]->{'AUDIO'}->[$akt_audio]);
  }
  else
  { $opt_a_target->set_history (0);
  }
}

sub AUDIO_SELECT ($)
{ shift;
  my $target = shift;

  if ($DVD_RIP[$akt_title]->{'RIP'} == 1)
  { $DVD_RIP[$akt_title]->{'AUDIO'}->[$akt_audio] = $target;
    # print "$akt_audio -> $target\n";
  }
  else
  { print $LANG{'ERROR_SELECT_TITLE'} . "!\n";
  }

  FAKTOR ();
}

sub SET_SUB ($)
{ shift;
  $akt_sub = shift;

  my $length = @{$DVD_INFO{'SUBTITLE'}->[$akt_title]}+0;
  my $loop = 1;

  $opt_s_target->remove_menu ();
  $opt_s_target_m = new Gtk2::Menu ();
  $opt_s_target->set_menu ($opt_s_target_m);

  $sub_items[0] = new Gtk2::MenuItem ($LANG{'LABEL_S_TARGET_NONE'});
  $opt_s_target_m->append ($sub_items[0]);
  $sub_items[0]->signal_connect ('activate' => \&SUB_SELECT, 0);
  $sub_items[0]->show;

  while ($loop < $length)
  { $sub_items[$loop] = new Gtk2::MenuItem ($LANG{'LABEL_S_TARGET'} . ": " . $loop);
    $opt_s_target_m->append ($sub_items[$loop]);
    $sub_items[$loop]->signal_connect ('activate' => \&SUB_SELECT, $loop);
    $sub_items[$loop]->show;

    ++$loop;
  }

  foreach my $akt (@{$DVD_RIP[$akt_title]->{'SUBTITLE'}})
   { if (defined $akt && $akt != 0 && (!defined $DVD_RIP[$akt_title]->{'SUBTITLE'}->[$akt_sub] || $akt != $DVD_RIP[$akt_title]->{'SUBTITLE'}->[$akt_sub]))
     { # print $akt . "\n";
       $sub_items[$akt]->set_sensitive(0);
     }
   }

  if (defined $DVD_RIP[$akt_title]->{'SUBTITLE'}->[$akt_sub])
  { $opt_s_target->set_history ($DVD_RIP[$akt_title]->{'SUBTITLE'}->[$akt_sub]);
  }
  else
  { $opt_s_target->set_history (0);
  }
}

sub SUB_SELECT ($)
{ shift;
  my $target = shift;

  if ($DVD_RIP[$akt_title]->{'RIP'} == 1)
  { $DVD_RIP[$akt_title]->{'SUBTITLE'}->[$akt_sub] = $target;
    # print "$akt_sub -> $target\n";
  }
  else
  { print $LANG{'ERROR_SELECT_TITLE'} . "!\n";
  }

  FAKTOR ();
}

sub TITLE_RIP ($)
{ shift;
  my $mode = shift;

  if ($mode == 0 && defined $akt_title)
  { $button_rip_title_0->hide;
    $button_rip_title_1->show;

    $DVD_RIP[$akt_title]->{'RIP'} = 1;

    # print "$akt_title\n";

    $opt_a_source->set_sensitive(1);
    $opt_a_target->set_sensitive(1);
    $opt_s_source->set_sensitive(1);
    $opt_s_target->set_sensitive(1);
  }
  else
  { $button_rip_title_1->hide;
    $button_rip_title_0->show;

    $DVD_RIP[$akt_title]->{'RIP'} = 0;

    # print "-$akt_title\n";

    $opt_a_source->set_sensitive(0);
    $opt_a_target->set_sensitive(0);
    $opt_s_source->set_sensitive(0);
    $opt_s_target->set_sensitive(0);
  }

  FAKTOR ();
}

sub FAKTOR ()
{ my $video_size = 0;
  my $audio_size = 0;
  
  for (my $i = 1; $i < @DVD_RIP+0; ++$i)
  { if ($DVD_RIP[$i]->{'RIP'} == 1)
    { if (defined $DVD_RIP[$i]->{'AUDIO'})
      { for (my $u = 1; $u < @{$DVD_RIP[$i]->{'AUDIO'}}+0; ++$u)
        { if (defined $DVD_RIP[$i]->{'AUDIO'}->[$u] && $DVD_RIP[$i]->{'AUDIO'}->[$u] != 0)
          { $audio_size += $DVD_INFO{'AUDIO_SIZE'}->[$i]->[$u];
          }
        }
      }

      $video_size += $DVD_INFO{'VIDEO_SIZE'}->[$i];
    }
  }

  $DVD_INFO{'FACTOR'} = $video_size / ($SETTINGS{'DVD_SIZE'} - $audio_size);
  $DVD_INFO{'FACTOR'} += $DVD_INFO{'FACTOR'}/50; ### 2% Reserve

  if ($DVD_INFO{'FACTOR'} < 1)
  { $DVD_INFO{'FACTOR'} = 1;
  }

  $DVD_INFO{'END_SIZE'} = int((($video_size/$DVD_INFO{'FACTOR'}) + $audio_size) / (1024*1024));

  my $smile;

  if ($DVD_INFO{'FACTOR'} < 1.2)
  { $smile = ":-D";
  }
  elsif ($DVD_INFO{'FACTOR'} < 1.4)
  { $smile = ":-)";
  }
  elsif ($DVD_INFO{'FACTOR'} < 1.6)
  { $smile = ":-|";
  }
  else
  { $smile = ":-(";
  }

  $statusbar->push(1, $LANG{'FACTOR'} . ": " . sprintf("%1.2f ", $DVD_INFO{'FACTOR'}) . $smile . " " . $LANG{'EXPECT_SIZE'} . ": " . $DVD_INFO{'END_SIZE'} . " MB");
}

sub TESTRIP ()
{ my $video_size = 0;
  my $audio_size = 0;

  for (my $i = 1; $i < @DVD_RIP+0; ++$i)
  { if ($DVD_RIP[$i]->{'RIP'} == 1)
    { # my $chapters = (@{@{$DVD_INFO{'CHAPTERS'}}[6]}+0) -1;
      my (@buffer, @audio, $tee);
      my $testchap = int ((((@{@{$DVD_INFO{'CHAPTERS'}}[$i]}+0) -1)/2) + 0.5); 

      push (@buffer, "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_BUFFER'} . " -s 64k -m 16m -i /tmp/ldvd_" . $i . "_video.vob | "
       . "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_TCEXTRACT'} . " -t vob -x mpeg2 > /tmp/ldvd_" . $i . "_video.m2v &");
      $tee = "/tmp/ldvd_" . $i . "_video.vob";
      COMMAND ("mkfifo /tmp/ldvd_" . $i . "_video.vob");

      if (defined $DVD_RIP[$i]->{'AUDIO'})
      { my @array_a;
        for (my $u = 1; $u < @{$DVD_RIP[$i]->{'AUDIO'}}+0; ++$u)
        { if (defined $DVD_RIP[$i]->{'AUDIO'}->[$u] && $DVD_RIP[$i]->{'AUDIO'}->[$u] != 0)
          { # $audio_size += $DVD_INFO{'AUDIO_SIZE'}->[$i]->[$u];
            $array_a[$DVD_RIP[$i]->{'AUDIO'}->[$u]] = $u;
          }
        }

        for (my $xy = 1; $xy < @array_a+0; ++ $xy)
        { if (defined $array_a[$xy] && $array_a[$xy] != 0)
          { my $uu = $array_a[$xy];
            $tee .= " /tmp/ldvd_" . $i . "_audio" . $uu . ".vob";
            COMMAND ("mkfifo /tmp/ldvd_" . $i . "_audio" . $uu . ".vob");
            push (@buffer, "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_BUFFER'} . " -s 64k -m 16m -i /tmp/ldvd_" . $i . "_audio" . $uu . ".vob | "
             . "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_TCEXTRACT'}
             . " -t vob -x " . $DVD_INFO{'AUDIO'}->[$i]->[$uu]->{'FORMAT'} . " -a " . ($uu-1) . " > /tmp/ldvd_" . $i . "_audio" . $uu . ".mpa &");
            push (@audio, "/tmp/ldvd_" . $i . "_audio" . $uu . ".mpa");
          }
        }
      }
    
      foreach my $p (@buffer)
      { COMMAND($p);
        sleep (2);
      }
      COMMAND ("nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_TCCAT'} . " -i " . $SETTINGS{'DVD_PATH'} . " -T $i,$testchap | tee $tee > /dev/null");  ## &

      $video_size += ((stat "/tmp/ldvd_" . $i . "_video.m2v")[7]) * (($DVD_INFO{'SECTOR'}->[$i]) / ($DVD_INFO{'CHAP_SECTORS'}->[$i]->[$testchap]));
      COMMAND ("rm /tmp/ldvd_" . $i . "_video.m2v $tee");
      foreach my $a (@audio)
      { $audio_size += ((stat $a)[7]) * (($DVD_INFO{'SECTOR'}->[$i]) / ($DVD_INFO{'CHAP_SECTORS'}->[$i]->[$testchap]));
        COMMAND ("rm $a");
      }
    }
  }

  my $faktor = $video_size / ($SETTINGS{'DVD_SIZE'} - $audio_size);
  $faktor += $faktor/50;

  if ($faktor < 1)
  { $faktor = 1;
  }

  print "Testrip done; New factor: $faktor\n"; 
  $DVD_INFO{'FACTOR'} = $faktor;
}

sub BUILD_DVD ()
{ pipe (READHANDLE,WRITEHANDLE);

  $FORK = fork();
  if ($FORK == 0) {
  my $time = time();
  $SETTINGS{'NICE'} = $spin->get_value_as_int();

  my $anzahl = 0;

  for (my $a = 1; $a < @DVD_RIP+0; ++$a)
  { if ($DVD_RIP[$a]->{'RIP'} == 1)
    { ++$anzahl;
    }
  }

    for (my $i = 1; $i < @DVD_RIP+0; ++$i)
    { if ($DVD_RIP[$i]->{'RIP'} == 1)
      { my ($tee, $mplex, @buffer, @buffer_sub, @subs, @pids);
        my $sub_rip = 0;
        my $audio_opts = "";
        my $sub_opts = "";
      
        #### Title ####
  
        my @chapter = @{$DVD_INFO{'CHAPTERS'}->[$i]};
        my $chapters = "00:00:00.000";
  
        for (my $l = 1; $l < (@chapter+0) - 1; ++$l)
        { $chapters .= "," . $chapter[$l];
        }
  
        $tee = "/tmp/ldvd_" . $i . "_video.vob";

#        COMMAND ("mkfifo /tmp/ldvd_" . $i . "_video.vob");
#        COMMAND ("mkfifo /tmp/ldvd_" . $i . "_video.m2v");

        $mplex = "/tmp/ldvd_" . $i . "_video.m2v";
#         if ($DVD_INFO{'FACTOR'} > 1)
#         { my $factor = "$DVD_INFO{'FACTOR'}";
#           $factor =~ s/,/./;
#           push (@buffer, "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_BUFFER'} . " -s 64k -m 16m -i /tmp/ldvd_" . $i . "_video.vob | " 
#           . "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_TCEXTRACT'} . " -t vob -x mpeg2 | "
#           . "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_TCREQUANT'} . " -f $factor > /tmp/ldvd_" . $i . "_video.m2v &");
#         }
#         else
#         { push (@buffer, "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_BUFFER'} . " -s 64k -m 16m -i /tmp/ldvd_" . $i . "_video.vob | " 
#            . "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_TCEXTRACT'} . " -t vob -x mpeg2 > /tmp/ldvd_" . $i . "_video.m2v &");
#         }
      
        if (defined $DVD_RIP[$i]->{'AUDIO'})
        { my @array_a;
        
          for (my $q = 1; $q < @{$DVD_RIP[$i]->{'AUDIO'}}+0; ++$q)
          { if (defined $DVD_RIP[$i]->{'AUDIO'}->[$q] && $DVD_RIP[$i]->{'AUDIO'}->[$q] != 0)
            { $array_a[$DVD_RIP[$i]->{'AUDIO'}->[$q]] = $q;
            }
          }

          for (my $xy = 1; $xy < @array_a+0; ++ $xy)
          { if (defined $array_a[$xy] && $array_a[$xy] != 0)
            { # print "$array_u[$xy]\n";
              # print "AUDIO: " . $DVD_RIP[$i]->{'AUDIO'}->[$u] . "\n";
              my $u = $array_a[$xy];
  
              #### Audio ####
              $tee .= " /tmp/ldvd_" . $i . "_audio_" . $u . ".vob";
              COMMAND ("mkfifo /tmp/ldvd_" . $i . "_audio_" . $u . ".vob");
              COMMAND ("mkfifo /tmp/ldvd_" . $i . "_audio_" . $u . ".mpa");
              $mplex .= " /tmp/ldvd_" . $i . "_audio_" . $u . ".mpa";
              push (@buffer, "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_BUFFER'} . " -s 64k -m 16m -i /tmp/ldvd_" . $i . "_audio_" . $u . ".vob | " 
               . "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_TCEXTRACT'} 
               . " -t vob -x " . $DVD_INFO{'AUDIO'}->[$i]->[$u]->{'FORMAT'} . " -a " . ($u-1) . " > /tmp/ldvd_" . $i . "_audio_" . $u . ".mpa &");

              if (!defined $audio_opts || $audio_opts eq "")
              { $audio_opts = " -a " . $DVD_INFO{'AUDIO'}->[$i]->[$u]->{'FORMAT'} . "+" . $DVD_INFO{'AUDIO'}->[$i]->[$u]->{'LANG'};
              }
              else
              { $audio_opts .= "," . $DVD_INFO{'AUDIO'}->[$i]->[$u]->{'FORMAT'} . "+" . $DVD_INFO{'AUDIO'}->[$i]->[$u]->{'LANG'};
              }
            }
          }
        }
        if (defined $DVD_RIP[$i]->{'SUBTITLE'})
        { my @array_s;

          for (my $q = 1; $q < @{$DVD_RIP[$i]->{'SUBTITLE'}}+0; ++$q)
          { if (defined $DVD_RIP[$i]->{'SUBTITLE'}->[$q] && $DVD_RIP[$i]->{'SUBTITLE'}->[$q] != 0)
            { $array_s[$DVD_RIP[$i]->{'SUBTITLE'}->[$q]] = $q;
            }
          }

          for (my $xy = 1; $xy < @array_s+0; ++ $xy)
          { if (defined $array_s[$xy] && $array_s[$xy] != 0)
            { my $u = $array_s[$xy];
  
              #### Subtitle ####
              $tee .= " /tmp/ldvd_" . $i . "_subtitle_" . $u . ".vob";
              COMMAND ("mkfifo /tmp/ldvd_" . $i . "_subtitle_" . $u . ".vob");
              $sub_rip = 1;
              push (@buffer_sub, "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_BUFFER'} . " -s 64k -m 16m -i /tmp/ldvd_" . $i . "_subtitle_" . $u . ".vob | " 
               . "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_SPUUNMUX'} . " -o " . $SETTINGS{'PATH'} . "/" . $DVD_INFO{'DISC_TITLE'} . "/sub_$u -s " 
               . ($u-1) . " -p /tmp/palette_$i /dev/stdin");
              push (@subs, $SETTINGS{'PATH'} . "/" . $DVD_INFO{'DISC_TITLE'} . "/sub_$u");

              if (!defined $sub_opts || $sub_opts eq "")
              { $sub_opts = " -s " . $DVD_INFO{'SUBTITLE'}->[$i]->[$u]->{'LANG'};
              }
              else
              { $sub_opts .= "," . $DVD_INFO{'SUBTITLE'}->[$i]->[$u]->{'LANG'};
              }
            }
          }
        }

        print WRITEHANDLE "$sub_rip\n";

        if ($SETTINGS{'TEST_RIP'})
        { if ($trip == 0)
          { $pbar->set_activity_mode(1);
            TESTRIP();
            $trip = 1;
            $pbar->set_activity_mode(0);
          }
        }

        COMMAND ("mkfifo /tmp/ldvd_" . $i . "_video.vob");
        COMMAND ("mkfifo /tmp/ldvd_" . $i . "_video.m2v");

        if ($DVD_INFO{'FACTOR'} > 1)
        { my $factor = "$DVD_INFO{'FACTOR'}";
          $factor =~ s/,/./;
          push (@buffer, "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_BUFFER'} . " -s 64k -m 16m -i /tmp/ldvd_" . $i . "_video.vob | "
          . "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_TCEXTRACT'} . " -t vob -x mpeg2 | "
          . "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_TCREQUANT'} . " -f $factor > /tmp/ldvd_" . $i . "_video.m2v &");
        }
        else
        { push (@buffer, "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_BUFFER'} . " -s 64k -m 16m -i /tmp/ldvd_" . $i . "_video.vob | "
           . "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_TCEXTRACT'} . " -t vob -x mpeg2 > /tmp/ldvd_" . $i . "_video.m2v &");
        }

        #### DVD rippen ####
        COMMAND ("mkfifo /tmp/ldvd_" . $i . "_movie.mpeg");

        COMMAND ("mkdir -p " . $SETTINGS{'PATH'} . "/" . $DVD_INFO{'DISC_TITLE'});

        CHECK_PROGRAM ($SETTINGS{'P_MPLEX'});
        CHECK_PROGRAM ($SETTINGS{'P_TCCAT'});
        CHECK_PROGRAM ($SETTINGS{'P_TCEXTRACT'});
        CHECK_PROGRAM ($SETTINGS{'P_TCREQUANT'});
        CHECK_PROGRAM ($SETTINGS{'P_DVDAUTHOR'});

        my $vidopts = $DVD_INFO{'VIDOPTS'}->[$i];

        if ($sub_rip == 0)
        { COMMAND ("nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_MPLEX'} . " -f 8 -S 0 -o /tmp/ldvd_" . $i . "_movie.mpeg $mplex &");
          sleep (2);
          foreach my $p (@buffer)
          { COMMAND($p);
            sleep (2);
          }
          COMMAND ("nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_TCCAT'} . " -i " . $SETTINGS{'DVD_PATH'} . " -T $i -L | tee $tee > /dev/null &");
          sleep (2);
          COMMAND ("nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_DVDAUTHOR'} . " -t" . $audio_opts . " -c $chapters -v $vidopts -o " . $SETTINGS{'PATH'} . "/" 
           . $DVD_INFO{'DISC_TITLE'} . "/dvd/ /tmp/ldvd_" . $i . "_movie.mpeg");
        }
        else
        { CHECK_PROGRAM ($SETTINGS{'P_SPUMUX'});
          CHECK_PROGRAM ($SETTINGS{'P_SPUUNMUX'});
          
          push (@pids, fork());
          if ($pids[(@pids+0)-1] == 0)
          { exec ("nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_MPLEX'} . " -f 8 -S 0 -o " . $SETTINGS{'PATH'} . "/" . $DVD_INFO{'DISC_TITLE'} 
             . "/movie_" . $i . ".mpg $mplex");
            exit;
          }

          my @palette = split(/\ /, $DVD_INFO{'PALETTE'}->[$i]);
          open(DATEI, ">/tmp/palette_$i");
          for (my $h = 1; $h < @palette+0; ++$h)
          { print DATEI $palette[$h] . "\n";
          }
          close(DATEI);


          sleep (2);

          foreach my $ps (@buffer_sub)
          { push (@pids, fork());
            if ($pids[(@pids+0)-1] == 0)
            { exec ($ps);
              exit;
            }
          }

          foreach my $p (@buffer)
          { COMMAND($p);
            sleep (2);
          }

          COMMAND ("nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_TCCAT'} . " -i " . $SETTINGS{'DVD_PATH'} . " -T $i -L | tee $tee > /dev/null &");
          sleep (2);

          foreach my $pid (@pids)
          { waitpid ($pid, 0);
          }
          
          my $sub_com = "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_SPUMUX'} . " -m dvd -s 0 " . $subs[0] . ".xml < " . $SETTINGS{'PATH'} . "/" 
           . $DVD_INFO{'DISC_TITLE'} . "/movie_" . $i . ".mpg";
          for (my $g = 1; $g < @subs+0; ++$g)
          { $sub_com .= " > /dev/stdout | " . "nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_SPUMUX'} . " -m dvd -s $g " . $subs[$g] . ".xml < /dev/stdin";
          }

          $sub_com .= " > /tmp/ldvd_" . $i . "_movie.mpeg &";
          COMMAND($sub_com);
          sleep (2);
          COMMAND ("nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_DVDAUTHOR'} . " -t" . $audio_opts . $sub_opts . " -c $chapters -v $vidopts -o " . $SETTINGS{'PATH'} 
           . "/" . $DVD_INFO{'DISC_TITLE'} . "/dvd/ /tmp/ldvd_" . $i . "_movie.mpeg");

          COMMAND ("rm -rf " . $SETTINGS{'PATH'} . "/" . $DVD_INFO{'DISC_TITLE'} . "/sub*");
          COMMAND ("rm -rf " . $SETTINGS{'PATH'} . "/" . $DVD_INFO{'DISC_TITLE'} . "/movie_$i.mpg");
          COMMAND ("rm -rf /tmp/palette_$i");
        }

        COMMAND ("rm -f /tmp/ldvd_$i*");

        COMMAND ("nice -n " . $SETTINGS{'NICE'} . " " . $SETTINGS{'P_DVDAUTHOR'} . " -T -o " . $SETTINGS{'PATH'} . "/" . $DVD_INFO{'DISC_TITLE'} . "/dvd/");
      }
    }
   
  NEEDED_TIME ($time);
  POSIX::_exit(0);
  }
  else
  { $toolbar->set_sensitive(0);
    chomp ($DVD_INFO{'SUB_RIP'} = <READHANDLE>);
    if ($DVD_INFO{'SUB_RIP'})
    { $pbar->configure(0, 0, ($DVD_INFO{'END_SIZE'}*2));
    }
    else
    { $pbar->configure(0, 0, $DVD_INFO{'END_SIZE'});
    }
  }
}

sub ende ()
{ $window->destroy;

  print "\tThank you for using $name - $version\n"
   . "\tCopyright by HdR <hdr1\@users.sourceforge.net>\n";
  exit (0);
}

sub STD_SEK ($)
{ my $time = shift;

  my ($h, $min, $sec) = (split /:/, $time);

  $sec += ($h*3600) + ($min*60);

  return($sec);
}

sub SEK_STD ($)
{ my $sec = shift;
  my $h = int ($sec/3600);
  $sec -= $h*3600;
  my $min = int ($sec/60);
  $sec -= $min*60;

  my $return = sprintf("%02d:%02d:%02d", $h, $min, $sec);
  return ($return);
}

sub COMMAND ($)
{ my $command = shift;
  print "$command\n";
  # $SETTINGS{'NICE'} = $spin->get_value_as_int();
  # print "nice -n " . $SETTINGS{'NICE'} . " " . $command . "\n";
  # system ("nice -n " . $SETTINGS{'NICE'} . " " . $command);
  system ($command);
}

sub BR_MODE ($)
{ shift;
  my $mode = shift;

  if ($mode == 1)
  { $br_label_image->set_sensitive(1);
    $br_entry->set_sensitive(1);
    $br_button->set_sensitive(1);

    $br_label_brenner->set_sensitive(0);
    $brenner_entry->set_sensitive(0);
    $br_dvd_compat->set_sensitive(0);
    $br_label_speed->set_sensitive(0);
    $br_opt_speed->set_sensitive(0);

    $SETTINGS{'BURN_MODE'} = 1;
  }
  elsif ($mode == 2)
  { $br_label_image->set_sensitive(0);
    $br_entry->set_sensitive(0);
    $br_button->set_sensitive(0);

    $br_label_brenner->set_sensitive(1);
    $brenner_entry->set_sensitive(1);
    $br_dvd_compat->set_sensitive(1);
    $br_label_speed->set_sensitive(1);
    $br_opt_speed->set_sensitive(1);

    $SETTINGS{'BURN_MODE'} = 2;
  }
  elsif ($mode == 3)
  { $br_label_image->set_sensitive(1);
    $br_entry->set_sensitive(1);
    $br_button->set_sensitive(1);

    $br_label_brenner->set_sensitive(1);
    $brenner_entry->set_sensitive(1);
    $br_dvd_compat->set_sensitive(1);
    $br_label_speed->set_sensitive(1);
    $br_opt_speed->set_sensitive(1);

    $SETTINGS{'BURN_MODE'} = 3;
  }
}

sub BR_SELECTION ($)
{ shift;
  my $act = shift;
  
  if ($act == 1)
  { $file_dialog->show;
  }
  else
  { $file_dialog->hide;
  }
}

sub BR_SELECT_IMAGE ()
{ my $file = $file_dialog->get_filename();
  $br_entry->set_text ($file);
  print "$file\n";
  $file_dialog->hide;
}

sub BR_COMPAT ()
{ if ($SETTINGS{'DVD_COMPAT'} == 0)
  { $SETTINGS{'DVD_COMPAT'} = 1;
  }
  else
  { $SETTINGS{'DVD_COMPAT'} = 0;
  }
}

sub SET_BRUN_SPEED ($)
{ shift;
  $SETTINGS{'BURN_SPEED'} = shift;
}

sub BURN_DVD ()
{ $FORK2 = fork();
  if ($FORK2 == 0) {
  my $time = time();
  
  if ($SETTINGS{'BURN_MODE'} == 1) ## Image erstellen
  { my $file = $br_entry->get_text ();
    if ($file ne "" && -d $SETTINGS{'PATH'} . "/" . $DVD_INFO{'DISC_TITLE'} . "/dvd")
    { CHECK_PROGRAM ($SETTINGS{'P_MKISOFS'});
      COMMAND ($SETTINGS{'P_MKISOFS'} . " -V \'" . $entry_title->get_text () . "\' -dvd-video -udf -o $file " . $SETTINGS{'PATH'} . "/" 
       . $DVD_INFO{'DISC_TITLE'} . "/dvd");
    }
    else
    { print $LANG{'ERROR_ISO'} . "\n";
    }
  }
  elsif ($SETTINGS{'BURN_MODE'} == 2) ## DVD brennen
  { my $dvd_device = $brenner_entry->get_text ();
    if ($dvd_device ne "" && -d $SETTINGS{'PATH'} . "/" . $DVD_INFO{'DISC_TITLE'} . "/dvd")
    { my $extra_opts = " -V \'" . $entry_title->get_text () . "\' -dvd-video -udf";
      if ($SETTINGS{'DVD_COMPAT'} == 1)
      { $extra_opts .= " -dvd-compat";
      }
      if ($SETTINGS{'BURN_SPEED'} != 0)
      { $extra_opts .= " -speed=" . $SETTINGS{'BURN_SPEED'};
      }

      CHECK_PROGRAM ($SETTINGS{'P_GROWISOFS'});
      COMMAND ($SETTINGS{'P_GROWISOFS'} . "$extra_opts -Z $dvd_device " . $SETTINGS{'PATH'} . "/" . $DVD_INFO{'DISC_TITLE'} . "/dvd");
    }
    else
    { print $LANG{'ERROR_BURN'} . "\n";
    }
  }
  elsif ($SETTINGS{'BURN_MODE'} == 3) ## Image -> DVD
  { my $file = $br_entry->get_text ();
    my $dvd_device = $brenner_entry->get_text ();

    if ($dvd_device ne "" && -s $file)
    { my $extra_opts = "";
      if ($SETTINGS{'DVD_COMPAT'} == 1)
      { $extra_opts .= " -dvd-compat";
      }
      if ($SETTINGS{'BURN_SPEED'} != 0)
      { $extra_opts .= " -speed=" . $SETTINGS{'BURN_SPEED'};
      }
      
      CHECK_PROGRAM ($SETTINGS{'P_GROWISOFS'});
      COMMAND ($SETTINGS{'P_GROWISOFS'} . " -Z $dvd_device=$file" . $extra_opts);
    }
  }
  
  NEEDED_TIME ($time);
  POSIX::_exit(0);
  }
  else
  { $br_window->set_sensitive(0);
  }
}

sub SAVE_SETTINGS ()
{ if (-d $ENV{'HOME'} . "/.ldvd")
  {
  }
  else
  { system ("mkdir -p " . $ENV{'HOME'} . "/.ldvd"); 
  }

  $SETTINGS{'DVD_PATH'} = $se_entry_dvd->get_text ();
  $SETTINGS{'DVD_BURN_DEVICE'} = $se_entry_dvd_device->get_text ();
  $SETTINGS{'PATH'} = $se_entry_path->get_text ();
  $SETTINGS{'DVD_SIZE'} = $se_entry_size->get_text ();
  $SETTINGS{'NICE'} = $spin->get_value_as_int();

  open (CONF, ">" . $ENV{'HOME'} . "/.ldvd/ldvd.conf");
  
  print CONF "LANG=" . $SETTINGS{'LANG'} . "\n";
  print CONF "DVD_PATH=" . $SETTINGS{'DVD_PATH'} . "\n";
  print CONF "DVD_BURN_DEVICE=" . $SETTINGS{'DVD_BURN_DEVICE'} . "\n";
  print CONF "PATH=" . $SETTINGS{'PATH'} . "\n";
  print CONF "DVD_SIZE=" . $SETTINGS{'DVD_SIZE'} . "\n";
  print CONF "P_LDVD_LS=" . $SETTINGS{'P_LDVD_LS'} . "\n";
  print CONF "P_MPLEX=" . $SETTINGS{'P_MPLEX'} . "\n";
  print CONF "P_BUFFER=" . $SETTINGS{'P_BUFFER'} . "\n";
  print CONF "P_TCEXTRACT=" . $SETTINGS{'P_TCEXTRACT'} . "\n";
  print CONF "P_TCREQUANT=" . $SETTINGS{'P_TCREQUANT'} . "\n";
  print CONF "P_TCCAT=" . $SETTINGS{'P_TCCAT'} . "\n";
  print CONF "P_DVDAUTHOR=" . $SETTINGS{'P_DVDAUTHOR'} . "\n";
  print CONF "P_SPUUNMUX=" . $SETTINGS{'P_SPUUNMUX'} . "\n";
  print CONF "P_SPUMUX=" . $SETTINGS{'P_SPUMUX'} . "\n";
  print CONF "P_MKISOFS=" . $SETTINGS{'P_MKISOFS'} . "\n";
  print CONF "P_GROWISOFS=" . $SETTINGS{'P_GROWISOFS'} . "\n";
  print CONF "NICE=" . $SETTINGS{'NICE'} . "\n";
  print CONF "TEST_RIP=" . $SETTINGS{'TEST_RIP'} . "\n";

  close (CONF);
}

sub CHECK_PROGRAM ($)
{ my $prog = shift;

  print "Checking for $prog: ";

  my $path_list = $ENV{'PATH'};
  my @pathes = split(/:/, $path_list);

  foreach my $path (@pathes)
  { my $prog_path = $path . "/" . $prog;

    if (-e $prog_path && -X $prog_path)
    { print "OK\n";
      return (1);
    }
  }

  print "FAILED please make sure $prog is installed, executable and in your PATH\n";
  return (0);
}

sub NEEDED_TIME ($)
{ my $time = shift;
  
  $time = (time()) - $time;
  my $gmin = int ($time/60);
  my $gsek = $time - ($gmin*60);
  my $gstd = int ($gmin/60);
  $gmin = $gmin - ($gstd*60);

  printf ($LANG{'NEEDED_TIME'} . " %02d:%02d:%02d\n", $gstd, $gmin, $gsek);
}

sub STATUS ()
{ if (defined $FORK && $FORK > 0)
  { if (waitpid ($FORK, 1))
    { $toolbar->set_sensitive(1);

      my $du = (DIR_SIZE($SETTINGS{'PATH'} . "/" . $DVD_INFO{'DISC_TITLE'}))/(1024*1024);
      #$adj = $pbar->adjustment;
      $pbar->configure($du, 0, $du);
    }
    else
    { my $du = (DIR_SIZE($SETTINGS{'PATH'} . "/" . $DVD_INFO{'DISC_TITLE'}))/(1024*1024);
        #$adj = $pbar->adjustment;
      $pbar->set_value($du);
    }
  }

  if (defined $FORK2 && $FORK2 > 0)
  { if (waitpid ($FORK2, 1))
    { $br_window->set_sensitive(1);
    }
  }

  return (1);
}

sub DIR_SIZE ($)
{ my $dir = shift;
  my $return_size = 0;
  
  if (-d $dir)
  { opendir(DIR, $dir);
    my @daten = readdir(DIR);
    closedir(DIR);
  
    for (@daten)
    { my $dat = $_;
      if ($dat ne ".." && $dat ne ".")
      { my $datei = $dir . "/" . $dat;
        if (-d $datei)
        { $return_size += DIR_SIZE ($datei);
        }
        else
        { $return_size += (stat $datei)[7];
        }
      }
    }
  }

  return ($return_size);
}

sub SE_TEST_RIP ()
{ if ($SETTINGS{'TEST_RIP'})
  { $SETTINGS{'TEST_RIP'} = 0;
    print "Testrip deactivated\n";
  }
  else
  { $SETTINGS{'TEST_RIP'} = 1;
    print "Testrip activated\n";
  }
}
