#
# class for configuration stuff of vdr2iso and jobeditor
# 
# COPYRIGHT:   (c) 2005-2006 Creative Commons by-nc-sa
#               some rights reserved. For details on copyright see:
#               http://creativecommons.org/licenses/by-nc-sa
#
# DISCLAIMER:   NO WARANTY AT ALL. Use at your own risk.
#
# vi: ts=3
#      
package V2I::Config;

use strict;
use Data::Dumper;
use File::Basename;
use Carp qw(carp croak);
use Storable qw(dclone);
use V2I::ThemeManager;
use V2I::Theme;
use V2I::Job;
use V2I::utils;

my $debug = 0;

sub initFromSysConfig {
   my $self = shift;     
   my @INC = ( '/etc/conf.d/', '/etc/', '/usr/local/etc/', './etc/' );
   my $fp;
   
   print('no user config. Read system settings ...'."\n");
   foreach (@INC) {
           if(-s $_.'vdr2iso' or -l $_.'vdr2iso'){
              open($fp, $_.'vdr2iso') or die('invalid config-file: '.$!);     
              print('gonna use config file ['.$_.'vdr2iso].'."\n");
              last;
              }
           }
   die('Sorry, no config-file in system found.'
       ."\n\t".'searched for vdr2iso in: '.join(':',@INC)
      ."\n".'Please check YOUR installation!'."\n") if not $fp;     
   while(my $line = <$fp>){
         next if $line =~ /^\s*\#/;     
         next if $line =~ /^$/;
         if($line =~ /^([^=]+)\=\"([^"]+)\"/){
            my $key = $1;
            my $val = $2;
   
            print('got from system config: ['.$key.'] = <|'.$val."|>\n") if $debug;
            SWITCH: for($key){
                  /^VIDEO_ROOT$/          and do { $self->{'user'}{'recBase'} = $val; last; };
                  /^WORK_DIR$/            and do { $self->{'user'}{'temp'} = $val; last; };
                  /^ISO_DIR$/             and do { $self->{'user'}{'iso'} = $val; last; };
                  /^PERL_ADDONS_DIR$/     and do { $self->{'user'}{'plugindir'} = $val; last; };
                  /^LOG_FILE$/            and do { $self->{'user'}{'logFN'} = $val; last; };
                  /^XCOLORS$/             and do { $self->{'user'}{'colorFN'} = $val; last; };
                  /^ADDON_DIR$/           and do { $self->{'user'}{'addons'} = $val; last; };
                  /^DEFAULT_THEME$/       and do { $self->{'user'}{'theme'} = $val; last; };
                  /^CATEGORY$/            and do { $self->{'user'}{'header'} = $val; last; };
                  /^DVDSIZE$/             and do { $self->{'user'}{'dvdSize'} = $val; last; };
                  /^BURNER$/              and do { $self->{'user'}{'dvdBurner'} = $val; last; };
                  /^DISC_TITLE$/          and do { $self->{'user'}{'disktmpl'} = $val; last; };
                  /^NICE_LEVEL$/          and do { $self->{'user'}{'niceLevel'} = $val; last; };
                  /^APP_LANG$/            and do { $self->{'user'}{'appLang'} = $val; last; };
                  /^PREFERRED_AUDIO$/     and do { $self->{'user'}{'language'} = $val; last; };
                  /^BACKGROUND_IMAGE$/    and do { $self->{'user'}{'bgimage'} = $val; last; };
                  /^BACKGROUND_ANCHOR$/   and do { $self->{'user'}{'anchor'} = $val; last; };
                  /^BACKGROUND_COLOR$/    and do { $self->{'user'}{'bgcolor'} = $val; last; };
                  /^HEADER_FONT$/         and do { my @parts = split(/;/, $val);
      
                                                   $self->{'user'}{'headerfont'} = $parts[0];
                                                   $self->{'user'}{'headerfontsize'} = $parts[1];
                                                   $self->{'user'}{'headercolor'} = $parts[2];
                                                   last; 
                                                   };
                  /^TITLE_FONT$/          and do { my @parts = split(/;/, $val);
         
                                                   $self->{'user'}{'titlefont'} = $parts[0];
                                                   $self->{'user'}{'titlefontsize'} = $parts[1];
                                                   $self->{'user'}{'titlecolor'} = $parts[2];
                                                   last; 
                                                   };
                  /^ITEM_FONT$/           and do { my @parts = split(/;/, $val);
         
                                                   $self->{'user'}{'itemfont'} = $parts[0];
                                                   $self->{'user'}{'itemfontsize'} = $parts[1];
                                                   $self->{'user'}{'itemcolor'} = $parts[2];
                                                   last;
                                                   };
                  /^SUMMARY_FONT$/        and do { my @parts = split(/;/, $val);
         
                                                   $self->{'user'}{'summaryfont'} = $parts[0];
                                                   $self->{'user'}{'summaryfontsize'} = $parts[1];
                                                   $self->{'user'}{'summarycolor'} = $parts[2];
                                                   last;
                                                   };
                  /^CMD_(.+)$/            and do { $self->{'user'}{'commands'}{lc($1)} = $val if not $1 eq 'PROJECTX'; 
                                                   $self->{'user'}{'commands'}{'projectX'} = $val if $1 eq 'PROJECTX'; 
                                                   last; 
                                                   };
                  }
            }
         }
   close($fp);

   return $self;
}

sub initFromUserConfig {
   my $self = shift;     
   my $userCfg = V2I::utils::fromXmlFile($self->{'_'}{'iniFN'}, 'Config');

   print('gonna read saved user config...'."\n");
   foreach (keys(%$userCfg)) {
           if(ref($userCfg->{$_})){ $self->{'user'}{$_} = dclone($userCfg->{$_}); }
           else                   { $self->{'user'}{$_} = $userCfg->{$_}; }
           }
}

sub populate {
   my $self = shift;
   my $scratch;

   while(my $vn = shift){
         $scratch = shift;     
         print('gonna process param <'.$vn.'> with value ['.$scratch."]\n") if $debug;     
         if($vn eq '-appBase'){
            system('mkdir -p \''.$scratch.'\' 2> /dev/null') if not -d $scratch;
            croak('invalid appBase parameter ['.$scratch.']. '.$!."\n") if not -d $scratch;
            $self->{'_'}{substr($vn,1)} = $scratch;
            }
         elsif($vn eq '-recBase'){
            croak('invalid recording base specified!') if not -d $scratch;     
            $self->{'user'}{substr($vn, 1)} = $scratch; 
            }
         elsif($vn eq '-jobFN'
         or $vn eq '-recCache'
         or $vn eq '-epgCache'
         or $vn eq '-iniFN'){
            my $sd = dirname($scratch);

            if(not $scratch){
               print('set '.$vn.' to nothing. BYE!'."\n");     
               if($vn eq '-jobFN' or $vn eq '-iniFN'){ $self->{'_'}{substr($vn, 1)} = $scratch; }
               else{ $self->{'user'}{substr($vn, 1)} = $scratch; }
               next;
               }
            system('mkdir -p \''.$sd.'\' 2> /dev/null') if not -d $sd;
            croak('invalid '.$vn.' parameter ['.$scratch.']. '.$!."\n") if not -d $sd;
            if($vn eq '-jobFN' or $vn eq '-iniFN'){ $self->{'_'}{substr($vn, 1)} = $scratch; }
            else{ $self->{'user'}{substr($vn, 1)} = $scratch; }
            }
         else{ croak('unknown parameter <'.$vn.'>'); }
         }
}

sub setupLanguage {
   my $self = shift;
   my $newLang = shift;

   $newLang = $self->getAppLang if not $newLang;
   $self->setAppLang($newLang);

   return if(scalar(keys(%{$self->{'_'}{'appText'}})) and $self->{'_'}{'appText'}{'__langid__'} eq $self->getAppLang);
   my $langDir = $self->getAppAddonsDir();
   my $fp;

   $langDir .= '/' if not $langDir =~ /\/$/;
   $langDir .= 'lang/';

   my $fnAppText = $langDir.'appText.'.$self->getAppLang;
   
   if(open($fp, $fnAppText)){
      print('gonna process properties from ['.$fnAppText."]\n") if $debug;     
      while(my $line = <$fp>){
            if($line =~ /\s*([^\s=]+)\s*=\s*(.+?)\s*$/){
               my $key  = $1;
               my $text = $2;

               $text =~ s/\\n/\n/g;
               $text =~ s/\\t/\t/g;
               if($key eq 'days' or $key eq 'months'){
                  my @parts = split(/ /,$text);
   
                  $text = \@parts if @parts;
                  }
               $self->{'_'}{'appText'}{$key} = $text;
               }   
            }
      $self->{'_'}{'appText'}{'__langid__'} = $self->getAppLang;
      close($fp);     
      }
}

sub new {
   my $class = shift;     
   my @all = getpwuid($<);
   my $myBase  = $all[7];

   $myBase .= '/' if not $myBase =~ /\/$/;
   my $appBase = $myBase.'.vdr2iso/';
   my $self = { '_' => {     
      'jobFN' => $myBase.'new.xml'
    , 'appBase' => $appBase
    , 'iniFN' => $appBase.'.vdr2iso.config'
    , 'fcFN' => $appBase.'.fonts.cache'
    , 'tmgr' => undef
   }, 'user' => {
      'theme' => 'Default'
    , 'recBase' => '/video0/'
    , 'temp' => '/video0/.vdr2iso/'
    , 'iso' => '/pub/export/'
    , 'plugindir' => '/etc/perl'
    , 'logFN' => '/var/log/vdr2iso.log'
    , 'colorFN' => '/usr/X11R6/lib/X11/rgb.txt' 
    , 'addons' => '/usr/share/vdr2iso'
    , 'recCache' => $appBase.'.cache.vri'
    , 'epgCache' => $appBase.'.cache.epg'
    , 'language' => 0
    , 'appLang' => 'en'
    , 'demux' => 'vdrsync'
    , 'chapLen' => 5
    , 'niceLevel' => 5
    , 'channel' => 'ZDF'
    , 'cutmarks' => ''
    , 'dvdSize' => 4700000000
    , 'dvdBurner' => '/dev/dvd'
    , 'themes' => {}
    , 'vdrproxy' => {'host' => 'vdr', 'port' => '7936', 'isOffline' => 1}
    , 'vdr2iso' => {'host' => 'worker', 'port' => '7938', 'isOffline' => 1}
    , 'jobedit' => {'host' => 'localhost', 'port' => '7937', 'isOffline' => 0}
    , 'commands' => {
      vdrsync => '/usr/bin/vdrsync.pl'
    , java => '/usr/bin/java'
    , projectX => '/usr/local/src/ProjectX/ProjectX.jar'
    , mplex => '/usr/bin/mplex' 
    , convert => '/usr/bin/convert'
    , ppmtoy4m => '/usr/bin/ppmtoy4m'
    , mpeg2enc => '/usr/bin/mpeg2enc'
    , spumux => '/usr/bin/spumux' 
    , pngquant => '/usr/bin/pngquant'  
    , growisofs => '/usr/bin/growisofs'
    , checkmedia => '/usr/bin/dvd+rw-mediainfo'  
    , genindex => '/usr/bin/genindex'
    , dvdauthor => '/usr/bin/dvdauthor'
    , mkisofs => '/usr/bin/mkisofs'
    }
    , 'fontDirs' => [qw(/usr /etc /var /home)]
    , 'ttfSample' => 'Übung macht den Meister.'
   }};
   bless($self, $class);
   $self->populate(@_);
   $self->{'_'}{'base'} = $appBase;
   system('mkdir -p \''.$self->{'_'}{'appBase'}.'\' 2>/dev/null') if not -d $self->{'_'}{'appBase'};
   print('user-config is <'.$self->{'_'}{'iniFN'}.">\n") if $debug;
   if(-s $self->{'_'}{'iniFN'}){ $self->initFromUserConfig; }
   else{ $self->initFromSysConfig; }
   $self->setupLanguage($self->getAppLang);
   $self->{'_'}{'tmgr'} = V2I::ThemeManager->new(-plugindir=>$self->getPluginDir
                                               , -themeconfig=>$self->{'user'}
                                               , -appconfig=>$self->{'user'}{'themes'});
   $self->{'_'}{'eCmds'}{'vdrsync'}    = \$self->{'user'}{'commands'}{'vdrsync'};
   $self->{'_'}{'eCmds'}{'java'}       = \$self->{'user'}{'commands'}{'java'};
   $self->{'_'}{'eCmds'}{'projectX'}   = \$self->{'user'}{'commands'}{'projectX'};
   $self->{'_'}{'eCmds'}{'convert'}    = \$self->{'user'}{'commands'}{'convert'};
   $self->{'_'}{'eCmds'}{'genindex'}   = \$self->{'user'}{'commands'}{'genindex'};
 
   $self->{'_'}{'wCmds'}{'vdrsync'}    = \$self->{'user'}{'commands'}{'vdrsync'};
   $self->{'_'}{'wCmds'}{'java'}       = \$self->{'user'}{'commands'}{'java'};
   $self->{'_'}{'wCmds'}{'projectX'}   = \$self->{'user'}{'commands'}{'projectX'};
   $self->{'_'}{'wCmds'}{'convert'}    = \$self->{'user'}{'commands'}{'convert'};
   $self->{'_'}{'wCmds'}{'mplex'}      = \$self->{'user'}{'commands'}{'mplex'};
   $self->{'_'}{'wCmds'}{'ppmtoy4m'}   = \$self->{'user'}{'commands'}{'ppmtoy4m'};
   $self->{'_'}{'wCmds'}{'mpeg2enc'}   = \$self->{'user'}{'commands'}{'mpeg2enc'};
   $self->{'_'}{'wCmds'}{'spumux'}     = \$self->{'user'}{'commands'}{'spumux'};
   $self->{'_'}{'wCmds'}{'pngquant'}   = \$self->{'user'}{'commands'}{'pngquant'};
   $self->{'_'}{'wCmds'}{'growisofs'}  = \$self->{'user'}{'commands'}{'growisofs'};
   $self->{'_'}{'wCmds'}{'checkmedia'} = \$self->{'user'}{'commands'}{'checkmedia'};
   $self->{'_'}{'wCmds'}{'dvdauthor'}  = \$self->{'user'}{'commands'}{'dvdauthor'};
   $self->{'_'}{'wCmds'}{'mkisofs'}    = \$self->{'user'}{'commands'}{'mkisofs'};

   return $self;
}

sub dump {
   my $self = shift;
   my $debug = shift;

   print(ref($self).' as xml (internal) ...:'."\n".V2I::utils::toXml($self->{'_'}, 'Config-Internal')."\n");
   print(ref($self).' as xml (user) ...:'."\n".V2I::utils::toXml($self->{'user'}, 'Config')."\n");
}

sub usedTools {
   my $self = shift;
   my %curVersion;
   my($fp,$dp);
   my $xToolz = [ 
     { cmd=>'vdrsync', param=>'--version', mask=>qw/^\s+VDRsync\s+Version\s(.+)$/ }
   , { cmd=>'java', param=>'-showversion', mask=>qw/^java\s+version\s+\"([^"]+)\"$/ }  
   , { cmd=>'convert', param=>'-version', mask=>qw/^Version:\s+ImageMagick\s+(\S+)/ }
   , { cmd=>'mplex', param=>'-version', mask=>qw/^mjpegtools(?:.+?)version\s(.+)$/ }
   , { cmd=>'spumux', param=>'-version', mask=>qw/^DVDAuthor::spumux,\s+version\s+(.+)$/ }
   , { cmd=>'pngquant', param=>'-version', mask=>qw/^pngquant,\s+version\s+([^,]+)/ }
   , { cmd=>'growisofs', param=>'-version', mask=>qw/growisofs.+?,\s+version\s+(.+)$/ }
   , { cmd=>'dvdauthor', param=>'-version', mask=>qw/^DVDAuthor::dvdauthor,\s+version\s+(.+)$/ }
   , { cmd=>'mkisofs', param=>'-version', mask=>qw/^mkisofs\s+(.+)$/ }   
   ];

   if(opendir($dp, dirname($self->{'user'}{'commands'}{'projectX'}))){
      while(my $entry = readdir($dp)){
            if($entry =~ /^ReleaseNotes_(.+?)\.txt$/){
               $curVersion{'projectX'} = $1;
               last;
               }
            }
      closedir($dp);
      }
   foreach my $tool (@$xToolz){
           if(open($fp, $self->{'user'}{'commands'}{$tool->{'cmd'}}.' '.$tool->{'param'}.' 2>&1 |')){
              while(my $line = <$fp>){
                    my $mask = $tool->{'mask'};
                    
                    if($line =~ /$mask/){
                       $curVersion{$tool->{'cmd'}} = $1;
                       last;
                       }
                    }
              close($fp);
              }
           } 
   return \%curVersion;   
}

sub printToolsUsed {
   my $self = shift;
   my $tvu = $self->usedTools;
   
   print("\n".'These are the external tools used:'."\n");
   foreach (keys(%$tvu)){ print(sprintf('%12.12s', $_).' ['.sprintf('%-40.40s',$self->{'user'}{'commands'}{$_}).']: version '.$tvu->{$_}."\n"); }
   print("\n");
}

sub hexColor {
   my $color = shift;
   my $rv = '#';
   my @hex = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
   
   foreach my $part (@$color){
           my $high = sprintf("%d", $part / 16);
           my $low  = sprintf("%d", $part % 16);

           $rv .= $hex[$high].$hex[$low];
           }
   print('hexColor created '.$rv."\n") if $debug;   

   return $rv;   
}

sub searchTTF {
   my $self = shift;
   my $dir = shift;
   my $dp;
   my @rv;
   
   print('searchTTF() ... search dir ['.$dir."]\n");
   if(opendir($dp, $dir)){
      $dir .= '/' if not $dir =~ /\/$/;
      while(my $entry = readdir($dp)){
            next if $entry =~ /^\.\.?$/;
            push(@rv, $self->searchTTF($dir.$entry)) if -d $dir.$entry;
            next if -l $dir.$entry;
            if($entry =~ /\.ttf$/){
               print('found TTF : '.$entry."\n");
               my $target = $self->{'_'}{'appBase'}.'/'.$entry;

               $target =~ s/.ttf$/.gif/;
               system($self->editorCommand('convert').' -background white -fill black -font \''
                      .$dir.$entry.'\' -size 400x50 '
                      .'label:\''.$self->getTTFSample.'\' \''.$target.'\'');
               push(@rv, {value=>$dir.$entry,bmp=>$target});
               }      
            }
      closedir($dp);
      }
   return @rv;
}

sub fontSample {
   my $self = shift;
   my $w = shift;
   my $id = shift;
   my $size = shift;
   my $cfg = shift;
   my $dst = $self->getAppBaseDir.$id.'.gif';

   my $cmd = $self->editorCommand('convert').' -background \'#EFEFEF\' -fill \''.$self->getHexColor4($cfg->{'color'})
            .'\' -size '.$size.'x'.int($size * 0.1).' -font \''.$cfg->{'value'}.'\' label:\''
            .$self->getLangToken($id).'\' \''.$dst.'\'';
   print('fontSample: <|'.$cmd."|>\n") if $debug;
   system($cmd);

   return $w->Photo(-format=>'gif', -file=>$dst);      
}

sub loadTTF {
   my $self = shift;
   my $fp;

   if(-s $self->{'_'}{'fcFN'}){ $self->{'_'}{'ttfList'} = V2I::utils::fromXmlFile($self->{'_'}{'fcFN'}, 'TruetypeFonts'); }
   else{
      print('Oups, no font cache found.'."\n\t".'Have to scan for ttf-fonts. Please be patient :)'."\n");
      my @fonts;

      print('loadTTF() ... fontDirs: '.Dumper($self->getFontDirs)."\n");
      for (@{$self->getFontDirs}){ push(@fonts, $self->searchTTF($_)); }
      my $xmlList = V2I::utils::toXml(\@fonts, 'TruetypeFonts');
   
      if(open($fp, '> '.$self->{'_'}{'fcFN'})){
         print($fp $xmlList);
         close($fp);
         }
      $self->{'_'}{'ttfList'} = \@fonts;
      }
}

sub checkMedia {
   my $self = shift;
   my $drive = shift;
   my $fp;
   my $de = 0;
   my $b  = 0;
   my $bs = 1;
   my $nm = 0;
   my $nd = 0;

   if(open($fp, $self->workerCommand('checkmedia').' '.$drive.' 2>&1 |')){
      while(my $line = <$fp>){
            print('check line: ['.$line."]\n") if $debug;
            for($line){
                /non-DVD/                          and do { $nd = 1; last; };
                /Disc status:\s+blank/             and do { $de = 1; last; };
                /Free Blocks:\s+(\d+)\*(\d+)KB/    and do { $b = $1; $bs = $2; last; };
                /no media mounted/                 and do { $nm = 1; last; };
                }
            }
      close($fp);
      }
   return ($nm, $nd, $de, $b, $bs);
}

sub loadColors {
   my $self = shift;
   my $fp;

   if(open($fp, $self->getColorFilename)){
      print('found color-list and gonna process it ...'."\n") if $debug;     
      while(my $line = <$fp>){
            if($line =~ /(\d+) (\d+) (\d+)\s+(.+)/){
               my $red   = $1;
               my $green = $2;
               my $blue  = $3;
               my $name  = uc($4);
   
               print('save color <'.$name.'> as ('.$red.' / '.$green.' / '.$blue.")\n") if $debug;
               $self->{'_'}{'CT'}{byName}{$name} = [($red, $green, $blue)];
               $self->{'_'}{'CT'}{byValue}{hexColor([$red, $green, $blue])} = $name;
               push(@{$self->{'_'}{'colors'}}, $name);
               }
            }
      close($fp);     
      }
}

sub save {
   my $self = shift;
   my $xmlData = V2I::utils::toXml($self->{'user'}, 'Config');
   my $fp;

   if(open($fp, '> '.$self->{'_'}{'iniFN'})){
      print($fp $xmlData);
      close($fp);
      }
}

sub getHexColor4 {
   my $self = shift;
   my $rawColor = shift;

   return hexColor($self->getColor4($rawColor));
}

sub getColor4 {
   my $self = shift;
   my $rawColor = uc(shift);
   my $red   = 0;
   my $green = 0;
   my $blue  = 0;

   print(ref($self).'::getColor4: <'.$rawColor.">\n") if $debug;
   if($rawColor =~ /^0X/ or $rawColor =~ /^#/){
      $rawColor =~ s/^0X//;
      $rawColor =~ s/^#//;
      print('color seems to be hex-value: '.$rawColor."\n") if $debug;
      $red    = hex(substr($rawColor,0,2));
      $green = hex(substr($rawColor,2,2));
      $blue  = hex(substr($rawColor,4,2));
      }
   elsif($rawColor =~ /(\d+),(\d+),(\d+)/){
      $red   = $1;
      $green = $2;
      $blue  = $3;
      }
   else{
      my $color = $self->{'_'}{'CT'}{byName}{$rawColor};

      $red    = $$color[0];
      $green = $$color[1];
      $blue  = $$color[2];
      }
   print(ref($self).'::getColor4() ... result=('.$red.','.$green.','.$blue.")\n") if $debug;

   return [$red,$green,$blue];
}

sub nice                { return 'nice -n '.$_[0]->{'user'}{'niceLevel'}.' '; }
sub getConfig           { return $_[0]->{'user'}; }
sub getAppBaseDir       { return $_[0]->{'_'}{'appBase'}; }
sub getJobFilename      { return $_[0]->{'_'}{'jobFN'}; }
sub getFontCacheFN      { return $_[0]->{'_'}{'fcFN'}; }
sub getThemeManager     { return $_[0]->{'_'}{'tmgr'}; }
sub getColorTable       { return $_[0]->{'_'}{'CT'}; }
sub getColorList        { return $_[0]->{'_'}{'colors'}; }
sub getTTFList          { return $_[0]->{'_'}{'ttfList'}; }
sub getRecCache         { return $_[0]->{'user'}{'recCache'}; }
sub getEpgCache         { return $_[0]->{'user'}{'epgCache'}; }
sub getProxy            { return $_[0]->{'user'}{'vdrproxy'}; }
sub getWorker           { return $_[0]->{'user'}{'vdr2iso'}; }
sub currentChannel      { return $_[0]->{'user'}{'channel'}; }
sub getAppAddonsDir     { return $_[0]->{'user'}{'addons'}; }
sub getAppLang          { return $_[0]->{'user'}{'appLang'}; }
sub getPluginDir        { return $_[0]->{'user'}{'plugindir'}; }
sub getColorFilename    { return $_[0]->{'user'}{'colorFN'}; }
sub getRecBase          { return $_[0]->{'user'}{'recBase'}; }
sub getLangIdx          { return $_[0]->{'user'}{'language'}; }
sub getDemuxer          { return $_[0]->{'user'}{'demux'}; }
sub getBurnDev          { return $_[0]->{'user'}{'dvdBurner'}; }
sub getChapterLength    { return $_[0]->{'user'}{'chapLen'}; }
sub getCutmarksFilename { return $_[0]->{'user'}{'cutmarks'}; }
sub getTheme            { return $_[0]->{'user'}{'theme'}; }
sub getHeader           { return $_[0]->{'user'}{'header'}; }
sub getWorkDir          { return $_[0]->{'user'}{'temp'}; }
sub getIsoDir           { return $_[0]->{'user'}{'iso'}; }
sub getLogFilename      { return $_[0]->{'user'}{'logFN'}; }
sub getFontDirs         { return $_[0]->{'user'}{'fontDirs'}; }
sub getTTFSample        { return $_[0]->{'user'}{'ttfSample'}; }

sub setCurrentChannel {
   my $self = shift;
   my $cn = shift;

   $self->{'user'}{'channel'} = $cn;
}

sub getLangToken {
   my $self = shift;
   my $token = shift;
   
   return $self->{'_'}{'appText'}{$token} if(exists($self->{'_'}{'appText'}{$token}));   
   return $token;
}

sub editorCommand {
   my $self = shift;
   my $uc = shift;

   print('look for editor-command <'.$uc.'> ...'."\n") if $debug;
   print('our command looks like: '.Dumper($self->{'_'}{'eCmds'}{$uc})."\n") if $debug;

   return ${$self->{'_'}{'eCmds'}{$uc}} if(exists($self->{'_'}{'eCmds'}{$uc}));
   return undef;
}

sub workerCommand {
   my $self = shift;
   my $uc = shift;

   return ${$self->{'_'}{'wCmds'}{$uc}} if(exists($self->{'_'}{'wCmds'}{$uc}));
   return undef;
}

sub setAppLang {
   my $self = shift;
   my $newLang = shift;
   my $langDir = $self->getAppAddonsDir();
   my $oldLang = $self->getAppLang;
   my $dp;

   $langDir .= '/' if not $langDir =~ /\/$/;
   $langDir .= 'lang/';
   print('language-support-dir: ['.$langDir."]\n") if $debug;
   if(-s $langDir.'appText.'.$newLang){ $self->{'user'}{'appLang'} = $newLang; }
   elsif($oldLang and -s $langDir.'appText.'.$oldLang) {
      $self->{'user'}{'appLang'} = $oldLang;     
      }
   else {
      if(-s $langDir.'appText.de'){ $self->{'user'}{'appLang'} = 'de'; }
      elsif(-s $langDir.'appText.en'){ $self->{'user'}{'appLang'} = 'en'; }
      else {
         print(STDERR 'Oups, I\'m not able to setup language. Please check YOUR installation!'."\n");
         exit;
         }
      }

   return $oldLang;
}

sub getDiskTitle {
   my $self = shift;
   my $number = shift;
   my $title = $self->{'user'}{'disktmpl'};
   
   $title =~ s/\$1/$number/;

   return $title;
}

sub supportedLanguages {
   my $self = shift;     
   my $langDir = $self->getAppAddonsDir();
   my($dp, @rv);

   $langDir .= '/' if not $langDir =~ /\/$/;
   $langDir .= 'lang/';
   print('language-support-dir: ['.$langDir."]\n") if $debug;
   opendir($dp, $langDir) or die('can\'t read my language-support dir!'."\n");
   while(my $entry = readdir($dp)){
         if($entry =~ /^appText\.(.+)$/ and -s $langDir.$entry){
            push(@rv, $1);
            }
         }
   closedir($dp);

   return @rv;
}

sub currentTheme {
   my $self = shift;

   return $self->{'_'}{'tmgr'}->getTheme($self->{'user'}{'theme'});
}

sub setJobFilename {
   my $self = shift;
   my $jFN = shift;
   my $jd = dirname($jFN);
   my $fn = basename($jFN);

   $jd = $self->{'_'}{'base'} if not $jd or $jd =~ /^$/;
   $self->{'_'}{'jobFN'} = $jd.$fn;

   print('set jobfilename to <'.$self->{'_'}{'jobFN'}.">\n");
}

sub setTheme {
   my $self = shift;
   my $nt = shift;
   
   if($self->getThemeManager->isActiveTheme($nt)){
      $self->{'user'}{'theme'} = $nt;     
      }
}

1;
