diff --git a/SyncPOD b/SyncPOD new file mode 100755 index 0000000..49352b5 --- /dev/null +++ b/SyncPOD @@ -0,0 +1,862 @@ +#!/usr/bin/perl -w + +# (c) 2002 Armin Obersteiner +# License: GPL v2 + +use MP3::Info; +use Unicode::String qw( latin1 utf16 ); +use Shell qw ( find gzip ); +use Getopt::Std; +use File::Copy; +use Filesys::DiskFree; + +use Data::Dumper qw (Dumper); + +use strict; + +my $version="0.68"; + +# +# options & config +# + +my %opt; +getopts("fcnh",\%opt); + +if($opt{h}) { + print <<"EOF"; +$0 [-c] [-f] [Search Pattern 1] [Search Pattern 2] ... + + -c create: create directory structure on plain ipod before syncing + (default: you get a warning if there is no ipod structure) + + -f force: rename ipod and use it with $0 before syncing + (default: an unknown ipod stays untouched) + + -n name check: checks mp3 names for possible illegal characters + + Search Patterns: for each search pattern a playlist is created + (case insensitive) +EOF + exit; +} + +my $buffer = 5*1024*1024; # leave some MB free for iTunesDB + +my @required = qw ( SYNCMODE PLAYLISTDIR IPODDIR BACKUPDIR ); + +my $rc=readrc("$ENV{HOME}/.ipod/config",\@required); + +#print Dumper($rc); + + +# +# check ipod name +# + +my ($ipod_name, $real_name, $computer_name)=get_ipodname($rc->{IPODDIR}); +unless($ipod_name) { + die "IPOD dir not found: $rc->{IPODDIR}" unless $opt{c}; +} + +# +# check ipod dirs (recreate them if necessary) +# + +mkdir "$rc->{IPODDIR}/iPod_Control",0755 unless(-d "$rc->{IPODDIR}/iPod_Control"); +mkdir "$rc->{IPODDIR}/iPod_Control/Music",0755 unless(-d "$rc->{IPODDIR}/iPod_Control/Music"); +mkdir "$rc->{IPODDIR}/iPod_Control/iTunes",0755 unless(-d "$rc->{IPODDIR}/iPod_Control/iTunes"); +mkdir "$rc->{IPODDIR}/iPod_Control/Device",0755 unless(-d "$rc->{IPODDIR}/iPod_Control/Device"); +for(0..19) { + my $d=sprintf "%.2d",$_; + mkdir "$rc->{IPODDIR}/iPod_Control/Music/F$d",0755 unless(-d "$rc->{IPODDIR}/iPod_Control/Music/F$d"); +} + +unless($opt{c}) { + print STDERR "IPOD name: $ipod_name\n"; + print STDERR "Synced by: $real_name\n"; + print STDERR "Synced on: $computer_name\n"; + + if($rc->{WRITEDEVICEINFO} && !$opt{f}) { + my $exit=0; + unless($rc->{IPODNAME} eq $ipod_name) { + $exit=1; + print STDERR "Your IPOD name: $rc->{IPODNAME}\n"; + } + unless($rc->{REALNAME} eq $real_name) { + $exit=1; + print STDERR "Your real name: $rc->{REALNAME}\n"; + } + unless($rc->{COMPUTERNAME} eq $computer_name) { + $exit=1; + print STDERR "Your computer: $rc->{COMPUTERNAME}\n"; + } + die "names mismatch, use -f to override" if $exit; + } + print STDERR "\n"; +} + +# +# write ipod name +# + +if($rc->{WRITEDEVICEINFO}) { + set_ipodname( + $rc->{IPODDIR},$rc->{BACKUPDIR}, + $rc->{IPODNAME},$rc->{REALNAME},$rc->{COMPUTERNAME} + ); + $ipod_name=$rc->{IPODNAME}; +} + +# +# check for songs +# + +my %songs; +my %check; + +my $dir; +$dir=$rc->{IPODDIR}."/iPod_Control/Music"; +$dir=$rc->{SYNCDIR} if($rc->{SYNCMODE} >= 2); + +my %tosync; +if(($rc->{SYNCLIST}) && ($rc->{SYNCMODE} == 2)) { + open IN,$rc->{SYNCLIST} or die "all-playlist: $rc->{SYNCLIST} not found"; + while() { + chomp; + $tosync{$_}=1; + } + close IN; +} + +my @mp3s; +if(($rc->{SYNCMODE} == 3)) { + my @pl=find("$rc->{PLAYLISTDIR}/* 2>/dev/null"); + my %test; + + for my $p (@pl) { + chomp $p; + my ($n) = $p =~ /.*\/(.*?)$/; + open IN,$p or die "playlist: $p could not be opened"; + while() { + unless($test{$_}) { + push @mp3s,$_; + $test{$_}=1; + } + } + } +} else { + @mp3s=find($dir); +} + +for(@mp3s) { + chomp $_; + next unless(/\.(m|M)(p|P)3$/); + my $name=$_; + + if(keys %tosync) { + next unless($tosync{$name}); + } + + if($opt{n}) { + die "illegal character in filename [$name]\n" unless ($name =~ /^[A-Za-z0-9\.\-_\/\,]+$/); + } + + s/\://g; + s/.*\///g; + $songs{$name}{name}=$_; + if($rc->{SYNCMODE} >= 2) { + $songs{$name}{dir}="F".hash($_); + } else { + ($songs{$name}{dir}) = $name =~ /\/(F\d\d)\//; + } + + { + my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, + $atime,$mtime,$ctime,$blksize,$blocks) = stat($name); + $songs{$name}{size}=$size; + $songs{$name}{date}=$mtime; + } + + my $tag; + $tag = get_mp3tag($name) unless($rc->{ALWAYSTEMPLATES}); + + my ($artist,$album,$title,$order,$_dummy_); + + if($tag) { + # print Dumper($tag); + # YEAR ARTIST COMMENT TRACKNUM TITLE ALBUM GENRE + $artist=$tag->{ARTIST}; + $album=$tag->{ALBUM}; + $title=$tag->{TITLE}; + $order=$tag->{TRACKNUM}; + $order=$1 if($order =~ /(\d+)\s*\//); + + } else { + for(sort {length($b) <=> length($a)} keys %{$rc->{FILETEMPLATES}}) { + if(my @x = $name =~ /$_/) { + my $c=0; + for my $x (@x) { + #print "\$$rc->{FILETEMPLATES}->{$_}->[$c]=\"$x\";\n"; + eval "\$$rc->{FILETEMPLATES}->{$_}->[$c]=\"$x\";"; + die "eval error: $@" if($@); + $c++; + } + last; + } + } + } + + unless($title) { + die "no title found in: $name"; + } + + $title =~ s/_/ /g; + $artist =~ s/_/ /g; + $album =~ s/_/ /g; + + $songs{$name}{title}=$title; + $songs{$name}{artist}=""; + $songs{$name}{album}=""; + $songs{$name}{order}=0; + $songs{$name}{artist}=$artist if $artist; + $songs{$name}{album}=$album if $album; + $songs{$name}{order}=$order if $order; + + my $info = get_mp3info ($name); + + $songs{$name}{size}=$info->{SIZE}; + $songs{$name}{bitrate}=$info->{BITRATE}; + $songs{$name}{duration}=int($info->{SECS}*1000); + $songs{$name}{vbr}=$info->{VBR}; + + #print Dumper($info); + + my $n=$songs{$name}{dir}."/".$songs{$name}{name}; + unless($check{$n}) { + $check{$n}=1; + } else { + die "songname: $songs{$name}{name} not unique"; + } +} + +# +# deleting unwanted songs +# + +my %known; +for(keys %songs) { + $known{$songs{$_}{name}}=1; +} + +#print Dumper(\%known); + +my @ipod = find ("$rc->{IPODDIR}/iPod_Control/Music"); +my @todel; +for(@ipod) { + next unless (/\.mp3$/i); + chomp; + + my ($name) = $_ =~ /\/([^\/]+\.mp3)$/i; + unless($known{$name}) { + push @todel,$_; + } +} + +my $del; +if($rc->{DELETEASK} && @todel) { + for(@todel) { + print "del: $_\n"; + } + print "Do you really want to delete this songs? (y/N) "; + my $in=; + chomp $in; + $del=1 if($in =~ /^y$/i); +} else { + $del=1; +} + +if($del) { + for(@todel) { + print STDERR "deleting: $_\n"; + unlink($_); + } +} + +# +# copy songs +# + +my $main_sl=""; +my $main_pl=""; +my $index=500; + +#print Dumper(\%songs); + +my $df = new Filesys::DiskFree; + +SONGS: for my $song (keys %songs) { + my $attr; + my $out=""; + my $attr_c=3; + + if($rc->{SYNCMODE} >= 2) { + my $to = "$rc->{IPODDIR}/iPod_Control/Music/$songs{$song}{dir}/$songs{$song}{name}"; + #my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, + # $atime,$mtime,$ctime,$blksize,$blocks) = stat($to); + #$size=0 unless $size; + #print "checking: $song [$songs{$song}{size}] -> $to [$size]\n"; + #if($size != $songs{$song}{size}) { + + unless(-e $to) { + print STDERR "syncing: $songs{$song}{name}\n"; + # cp "\"$song\" \"$to\""; + + $df->df(); + my $free=$df->avail($rc->{IPODDIR}); + + if($free-$songs{$song}{size}-$buffer>0) { + copy($song,$to); + } else { + print STDERR "no space availiable for: $songs{$song}{name} [$songs{$song}{size}]\n"; + delete $songs{$song}; + next SONGS; + } + } + } + + $songs{$song}{index}=$index; + + $out.=create_mhod($songs{$song}{title},1); + + if($songs{$song}{artist}) { + $attr_c++; + $out.=create_mhod($songs{$song}{artist},4); + } + if($songs{$song}{album}) { + $attr_c++; + $out.=create_mhod($songs{$song}{album},3); + } + + $out.=create_mhod("MPEG audio file",6); + $out.=create_mhod(":iPod_Control:Music:".$songs{$song}{dir}.":".$songs{$song}{name},2); + + $out=create_mhit( + $attr_c,length($out),$index,$songs{$song}{vbr}, + $songs{$song}{date},$songs{$song}{size}, + $songs{$song}{duration},$songs{$song}{order}, + $songs{$song}{bitrate} + ).$out; + + $main_sl.=$out; + + $main_pl.=create_mhod_mhip($songs{$song}{index}); + + $index++; +} + +#print Dumper(\%songs); + +my %playlists; +my @pl=find("$rc->{PLAYLISTDIR}/* 2>/dev/null"); + +for my $p (@pl) { + chomp $p; + my ($n) = $p =~ /.*\/(.*?)$/; + open IN,$p or die "playlist: $p could not be opened"; + while() { + my $song=$_; + chomp $song; + + unless($songs{$song}) { + print STDERR "ignoring song in playlist [$p], [$song] does not exist in syncdir or ipod full\n"; + } else { + $playlists{$n}{raw}.=create_mhod_mhip($songs{$song}{index}); + $playlists{$n}{count}++; + } + } + close IN; +} + +# +# creating search pattern playlists +# + +for my $pattern (@ARGV) { + my @list; + for(keys %songs) { + push @list,$songs{$_}{index} if($_ =~ /$pattern/i); + } + unless(@list) { + print STDERR "nothing for searchpattern: $pattern found\n"; + } else { + my ($name)=$pattern=~/(\S\S\S+)/; + unless(length($name)>=3) { + $name=$pattern; + $name =~ s/[^A-Za-z0-9]//g; + } + for(@list) { + $playlists{$name}{raw}.=create_mhod_mhip($_); + $playlists{$name}{count}++; + } + print STDERR @list." songs for searchpattern: $pattern found\n"; + } +} + +#print Dumper(\%playlists); + +# +# build the pieces together +# + +my $output; + +my $song_c=keys %songs; + +print STDERR "\nFound songs: $song_c\n"; + +my $tmp=create_mhlt($song_c).$main_sl; +$main_sl=create_mhsd(96+length($tmp),1).$tmp; + +print STDERR "Songlist created\n"; + +my $pl_c=keys %playlists; + +print STDERR "\nFound additional playlists: $pl_c\n"; + +$tmp=create_mhlp($pl_c+1).create_playlist_main($ipod_name,$song_c).$main_pl; +print STDERR "\nMain playlist created: $song_c songs\n\n"; + +for(keys %playlists) { + $tmp.=create_playlist($_,$playlists{$_}{count}).$playlists{$_}{raw}; + print STDERR "Playlist \"$_\" created: $playlists{$_}{count} songs\n"; +} + +$main_pl=create_mhsd(96+length($tmp),2).$tmp; + + +$output=create_mhbd(104+length($main_sl.$main_pl)).$main_sl.$main_pl; + +# backup old iTunesDB +if(-e "$rc->{IPODDIR}/iPod_Control/iTunes/iTunesDB") { + my $t=time(); + copy("$rc->{IPODDIR}/iPod_Control/iTunes/iTunesDB","$rc->{BACKUPDIR}/iTunesDB_$t"); + gzip("$rc->{BACKUPDIR}/iTunesDB_$t"); +} + +open OUT,">".$rc->{IPODDIR}."/iPod_Control/iTunes/iTunesDB" or die "cannot write iTunesDB"; +print OUT $output; +close OUT; + +print STDERR "\niTunesDB created.\n"; +exit; +# END + + +# +# internal subroutines +# + +sub create_mhbd { + my ($size) = @_; + + my $r= "mhbd"; + $r.= pack "V",104; + $r.= pack "V",$size; + $r.= pack "V",1; + $r.= pack "V",1; + $r.= pack "V",2; + for(1..20) { + $r.= pack "V",0; + } + + return $r; +} + +sub create_mhlp { + my ($count) = @_; + + my $r= "mhlp"; + $r.= pack "V",92; + $r.= pack "V",$count; + for(1..20) { + $r.= pack "V",0; + } + + return $r; +} + +sub create_playlist { + my ($name,$anz) = @_; + + my $ipod_name=create_mhod($name,1); + + my $r= "mhyp"; + $r.= pack "V",108; + $r.= pack "V",108+648+length($ipod_name)+$anz*(76+44); + $r.= pack "V",2; + $r.= pack "V",$anz; + $r.= pack "V",0; + $r.= pack "V",3088620292; + $r.= pack "V",2317718671; + $r.= pack "V",3655876446; + for(1..18) { + $r.= pack "V",0; + } + + $r.= "mhod"; + $r.= pack "V",24; + $r.= pack "V",648; + $r.= pack "V",100; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",12714187; # ?? 12714187 + $r.= pack "V",26215000; + $r.= pack "V",0; + $r.= pack "V",65736; + $r.= pack "V",1; # ?? 1 + $r.= pack "V",6; # ?? 6 + $r.= pack "V",0; # ?? 0 + $r.= pack "V",2555905; # ?? 2555905 + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",13107202; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",3276813; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",8192004; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",8192003; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",5242888; + for(1..107) { + $r.= pack "V",0; + } + $r.= pack "V",140; + for(1..19) { + $r.= pack "V",0; + } + + return $r.$ipod_name; +} + +sub create_playlist_main { + my ($name,$anz) = @_; + + my $ipod_name=create_mhod($name,1); + + my $r= "mhyp"; + $r.= pack "V",108; + $r.= pack "V",108+648+length($ipod_name)+$anz*(76+44); + $r.= pack "V",2; + $r.= pack "V",$anz; + $r.= pack "V",1; + $r.= pack "V",3087491191; + $r.= pack "V",837788566; + $r.= pack "V",62365; + for(1..18) { + $r.= pack "V",0; + } + + $r.= "mhod"; + $r.= pack "V",24; + $r.= pack "V",648; + $r.= pack "V",100; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",13172927; # ?? 12714187 + $r.= pack "V",26215000; + $r.= pack "V",0; + $r.= pack "V",65736; + $r.= pack "V",5; # ?? 1 + $r.= pack "V",6; # ?? 6 + $r.= pack "V",3; # ?? 0 + $r.= pack "V",1179649; # ?? 2555905 + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",13107202; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",3276813; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",8192004; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",8192003; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",5242888; + for(1..107) { + $r.= pack "V",0; + } + $r.= pack "V",140; + for(1..19) { + $r.= pack "V",0; + } + + return $r.$ipod_name; +} + +sub create_mhod_mhip { + my ($ref) = @_; + + my $r= "mhip"; + $r.= pack "V",76; + $r.= pack "V",76; + $r.= pack "V",1; + $r.= pack "V",0; + $r.= pack "V",$ref-1; + $r.= pack "V",$ref; + $r.= pack "V",3088619525; + for(1..11) { + $r.= pack "V",0; + } + + $r.="mhod"; + $r.= pack "V",24; + $r.= pack "V",44; + $r.= pack "V",100; + $r.= pack "V",0; + $r.= pack "V",0; + $r.= pack "V",$ref-1; + for(1..4) { + $r.= pack "V",0; + } + + return $r; +} + +sub create_mhsd { + my ($size,$type) = @_; + + my $r="mhsd"; + $r.= pack "V",96; + $r.= pack "V",$size; + $r.= pack "V",$type; + for(1..20) { + $r.= pack "V",0; + } + + return $r; +} + +sub create_mhlt { + my ($count) = @_; + + my $r="mhlt"; + $r.= pack "V",92; + $r.= pack "V",$count; + for(1..20) { + $r.= pack "V",0; + } + + return $r; +} + +sub create_mhit { + my ($arttr_c,$attr_s,$index,$vbr,$date,$size,$dur,$order,$bitrate) = @_; + + my $r="mhit"; + $r.= pack "V",156; + $r.= pack "V",156+$attr_s; + $r.= pack "V",$arttr_c; + $r.= pack "V",$index; + $r.= pack "V",1; + $r.= pack "V",0; + my $type=256; + $type+=1 if($vbr); + $r.= pack "V",$type; + $r.= pack "V",$date+2082844800; + $r.= pack "V",$size; + $r.= pack "V",$dur; + $r.= pack "V",$order; + $r.= pack "V",0; + $r.= pack "V",0; + $r.= pack "V",$bitrate; + $r.= pack "V",2890137600; + for(1..23) { + $r.= pack "V",0; + } + + return $r; +} + +sub create_mhod { + my ($string,$type) = @_; + my $len=length($string); + + my $r="mhod"; + $r.= pack "V",24; + $r.= pack "V",(40+2*$len); + $r.= pack "V",$type; + $r.= pack "V2",0; + $r.= pack "V",1; + $r.= pack "V",(2*$len); + $r.= pack "V2",0; + + my $u=latin1($string); + $u->byteswap; + $r.= $u->utf16; + + return $r; +} + +sub set_ipodname { + my ($dev,$backup,$name,$real,$cpu)=@_; + $dev.="/iPod_Control/iTunes/DeviceInfo"; + + my $file; + + for(1..384) { + $file.=pack "V",0; + } + + my $l=length($name); + substr($file,0,2)=pack "v",$l; + my $u=latin1($name); + $u->byteswap; + substr($file,2,$l*2)=$u->utf16; + + $l=length($real); + substr($file,512,2)=pack "v",$l; + $u=latin1($real); + $u->byteswap; + substr($file,514,$l*2)=$u->utf16; + + $l=length($cpu); + substr($file,1024,2)=pack "v",$l; + $u=latin1($cpu); + $u->byteswap; + substr($file,1026,$l*2)=$u->utf16; + + if(-e $dev) { + my $t=time(); + copy($dev,"$backup/DeviceInfo_$t"); + gzip("$backup/DeviceInfo_$t"); + } + open IPOD,">$dev" or die "cannot write DeviceInfo"; + print IPOD $file; + close IPOD; +} + +sub get_ipodname { + my $dev=shift; + $dev.="/iPod_Control/iTunes/DeviceInfo"; + my $file; + my $buff; + + open IPOD,$dev or return undef; + while (read(IPOD, $buff, 8 * 2**10)) { + $file.=$buff; + } + close IPOD; + + my $l=unpack "v",substr($file,0,2); + my $s=substr($file,2,$l*2); + my $u=utf16($s); + $u->byteswap; + my $name=$u->latin1; + + $l=unpack "v",substr($file,512,2); + $s=substr($file,514,$l*2); + $u=utf16($s); + $u->byteswap; + my $realname=$u->latin1; + + $l=unpack "v",substr($file,1024,2); + $s=substr($file,1026,$l*2); + $u=utf16($s); + $u->byteswap; + my $computername=$u->latin1; + + return ($name,$realname,$computername); +} + +sub hash { + my $string=shift; + my $key; + + my $len=length($string); + + for(my $j=$len-1 ; $j>1 ; $j--) { + $key+=ord(substr($string,$j,1)); + } + + return sprintf "%.2d",(substr($key,length($key)-2,2) % 20); +} + +sub readrc { + my $file = shift; + my $req = shift; + my $rc; + + my $sub; + + open IN,$file or die "cannot open rc file: $file"; + while() { + next if /^\s*$/; + next if /^\s*#/; + + if(/^\s*(\S+)\s*=\s*(.*?)\s*$/) { + my $k=$1; + my $n=$2; + ($n) = $n =~ /^\"(.*?)\"$/ if($n =~ /\"/); + unless($sub) { + $rc->{$k}=$n; + } else { + ($k) = $k =~ /^\"(.*?)\"$/ if($k =~ /\"/); + my @n=split /,/,$n; + for(@n) { + s/^\s+//g; + s/\s+$//g; + s/^\"//; + s/\"$//; + } + $rc->{$sub}->{$k}=\@n; + } + } elsif (/^\s*(\S+)\s*\{/) { + $sub=$1; + } elsif (/^\s*}/) { + $sub=undef; + } + } + + if($rc->{SYNCMODE} == 2) { + push @$req,"SYNCDIR"; + } + if($rc->{WRITEDEVICEINFO} == 1) { + push @$req,("IPODNAME","REALNAME","COMPUTERNAME"); + } + if($rc->{ALWAYSTEMPLATES} == 1) { + push @$req,"FILETEMPLATES"; + } + + for my $d (keys %$rc) { + if($d =~ /DIR$/) { + $rc->{$d} =~ s/\~/$ENV{HOME}/; + } + } + $rc->{SYNCLIST} =~ s/\~/$ENV{HOME}/ if $rc->{SYNCLIST}; + + for(@$req) { + die "RC PARAMETER: $_ not found" unless($rc->{$_}); + } + return $rc; +} diff --git a/cd-blank b/cd-blank new file mode 100755 index 0000000..8541a72 --- /dev/null +++ b/cd-blank @@ -0,0 +1,18 @@ +#!/bin/sh + +set -x + +echo +echo "Löschen einer CD-RW" +echo + +. /etc/dvd-scripts.env +if [ "$1" == "all" ] +then + echo "Die CD-RW wird gründlich gelöscht..." + cdrecord -v dev="$CD_DEVICE" -blank=all +else + echo "Die CD-RW wird schnell gelöscht..." + cdrecord -v dev="$CD_DEVICE" -blank=fast + +fi diff --git a/cd-burn-files b/cd-burn-files new file mode 100755 index 0000000..ad1eaa1 --- /dev/null +++ b/cd-burn-files @@ -0,0 +1,25 @@ +#!/bin/sh + +set -x + +echo +echo "Brennen eins Verzeichnisses" +echo + +. /etc/dvd-scripts.env + +CD_IMAGE=$CD_IMAGE_TEMP +DATA_DIR=$1 + +label=`date '+%Y-%m-%d'` + +echo "Das Image für das Verzeichnis $DATA_DIR wird erzeugt..." +mkisofs -D -J -L -r -v -V "$label" -o "$CD_IMAGE" "$DATA_DIR" + +if [ $? -eq 0 ] +then + cd-burn-image "$CD_IMAGE" + rm "$CD_IMAGE" +else + echo "Fehler beim erzeugen des Image." +fi diff --git a/cd-burn-image b/cd-burn-image new file mode 100755 index 0000000..71c597d --- /dev/null +++ b/cd-burn-image @@ -0,0 +1,25 @@ +#!/bin/sh + +#set -x + +echo +echo "Brennen eines CD-Images" +echo + +. /etc/dvd-scripts.env + +CD_IMAGE=$1 + +hdparm -u1 -d1 $CD_DEVICE_SCSI +if [ "$CD_IMAGE" == "" ] +then + echo "Usage: $0 image-file-to-burn" +elif [ -s "$CD_IMAGE" ] +then + echo "Das Image $CD_IMAGE wird gebrannt..." + cdrecord -v -eject dev="$CD_DEVICE_SCSI" -data "$CD_IMAGE" + +else + echo "Das Image $CD_IMAGE existiert nicht !" +fi +echo diff --git a/cd2mp3 b/cd2mp3 new file mode 100755 index 0000000..2e39700 --- /dev/null +++ b/cd2mp3 @@ -0,0 +1,97 @@ +#!/bin/bash +# +# /usr/local/bin/cdtomp3 -- CD rippen +# +#set -x + +[ -f ~/.cd2mp3.conf ] && . ~/.cd2mp3.conf + +[ -z $cdreader ] && cdreader="/dev/cdrom" +[ -z $bitrate ] && bitrate=192 +[ -z $cddbdata ] && cddbdata=/tmp/cdtomp3.cddb +[ -z $grabber ] && grabber='cdparanoia -q -w $(expr $i + 1) -d $cdreader -' +[ -z $destdir ] && destdir=/dat/mp3Neu +[ -z $prio ] && prio=10 +[ -z $SVDSVDRPSEND ] && SVDRPSEND=svdrpsend.pl +[ -z $LOGFILE ] && LOGFILE=/tmp/cd2mp3.log + +if test -f $LOGFILE; then + rm $LOGFILE +fi +if test -s $cddbdata; then + rm $cddbdata +fi + +#internetverbindung in de gänge bringen +#ping -c 2 www.heise.de +#sleep 15 + +cddb=$(echo $(disc-cover -t cddb -D $cdreader -o "$cddbdata") | awk -F'"' '{print $2}') +if test -s "$cddbdata"; then + subdir=$(grep "DTITLE" "$cddbdata" | awk -F= '{print $2}' | sed "s/ /_/g" | sed "s/[^[:alnum:]_-]//g") + echo "CDDB Eintrag gefunden: $subdir" + $SVDRPSEND MESG "CDDB Eintrag gefunden: $subdir" +else + subdir="UnbekannteCd" +fi + +if ! test -d "$destdir/$subdir"; then + mkdir $destdir/$subdir +fi +cd $destdir/$subdir + +if ! test -a fifo; then + mkfifo fifo +fi +## Jetzt geht's los, maximal 100 Titel auf einer CD + +for(( i=0; i<=99; i++)) +do + ## Erst den Dateinamen des Tracks ermitteln + if test -s "$cddbdata"; then + trackname=$(grep "TITLE$(echo $(expr $i + 0))=" $cddbdata | awk -F= '{print $2}' | sed "s/ /_/g" | sed "s/[^[:alnum:]_-]//g") + if ! test "$trackname"; then + trackname="track" + fi + else + trackname="track" + fi + ## Index hinzu; moegliche Namensgleichheiten beseitigen + let "i2 = $i + 1" + if [ $i2 -le 9 ] ; then + index=0$i2 + else + index=$i2 + fi + trackname=$index"-$trackname" + echo $trackname + + ## Get names for ID-Tags ################# + titlename=$(grep "TITLE$(echo $(expr $i + 0))=" $cddbdata | awk -F= '{print $2}') + year=$(grep "DYEAR=" $cddbdata | awk -F= '{print $2}') + disktitle=$(grep "DTITLE=" $cddbdata | awk -F[=/] '{print $3}' | sed "s/^ *//") + diskartist=$(grep "DTITLE=" $cddbdata | awk -F[=/] '{print $2}') + #echo Jahr:$year + #echo Titel:$titlename + #echo Album:$disktitle + #echo Interpret:$diskartist + $SVDRPSEND MESG "'$trackname' wird gerippt" + ## Grabber und Kodierer anwerfen ############ + # Codieren beginnt sobald das erste Byte eintrifft ... + nice -n $prio lame --quiet --tt "$titlename" --ta "$diskartist" --tl "$disktitle" --ty "$year" --tn "$i2" --disptime 2 -b $bitrate -m s -h fifo "$trackname".mp3 > $LOGFILE & + eval "nice -n $prio $grabber" > fifo + + # das ist der Fall, wenn der angegebene Track existiert ... + if test "$?" -ne 0; then + sleep 5 + # Fehlercode des Grabbers -> reale Trackzahl ueberschritten + # oder Fehler des CD Laufwerks + #echo "FEHLER" + #echo "$trackname".mp3 + rm "$trackname".mp3 + break + fi +done +rm fifo +$SVDRPSEND MESG "Rippen fertig" +echo "Fertig !" \ No newline at end of file diff --git a/cda2hd b/cda2hd new file mode 100755 index 0000000..7db21e4 --- /dev/null +++ b/cda2hd @@ -0,0 +1,24 @@ +#!/bin/sh +# +# +set -x + +#scsidev="0,0,0" +cdreader="/dev/cdrom" +destdir=/dat/tmp/audio +driver=generic-mmc +logfile=/tmp/cda2hd.log +nicelevel=15 + +[ -d $destdir ] || mkdir -p $destdir +cd $destdir + + +# Datei cd.toc erzeugen +[ -f cd.toc ] && rm cd.toc +nice -n $nicelevel cdrdao read-toc --with-cddb --datafile data.raw --device $cdreader --driver $driver cd.toc > $logfile +# Grabben (cdparanoia hat eine bessere Kratzererkennung) +[ -f data.raw ] && rm data.raw +nice -n $nicelevel cdparanoia -v 1- -p data.raw -d $cdreader > $logfile +#cdrdao write --eject --speed $speed --device $scsidev --driver $driver cd.toc +eject $cdreader diff --git a/convnow.sh b/convnow.sh new file mode 100755 index 0000000..963ab89 --- /dev/null +++ b/convnow.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +log=/tmp/convnow.log +#echo 0:$0 >> $log +#echo 1:$1 >> $log +#echo 2:$2 >> $log + +viddir=\\/var\\/lib\\/video.00\\/ +recdir=$2 + +recpath=$(echo $recdir | sed "s/$viddir//g") +#echo recpath: $recpath >> $log +#echo "2" >> $log + +function cmd2nas { + local cmd=$1 + local nasaddr=nas@nas + local naskey=nas + + echo ssh -i ~/.ssh/$naskey $nasaddr "$cmd" >> $log + ssh -i ~/.ssh/$naskey $nasaddr "$cmd" +} + +#echo recpath2: $recpath >> $log + +for par in "$@"; do + #echo "xxx:$par" >> $log + case $par in + vdr2mp3) + #echo "vdr2mp3" >> $log + cmd2nas "nohup ruby ~/bin/vdr2mp3.rb '$recpath' >/tmp/test.log 2>&1 & " + + ;; + *) + ;; + esac +done + +#1:vdr2mp3dd +#2:/var/lib/video.00/%Dok_5_-_Das_Feature/2012-08-05.11.00.124-0.rec +exit + + +ssh -i /home/marc/.ssh/nas nas@nas "nohup ruby ~/bin/vdr2mp3.rb '%Dok_5_-_Das_Feature/2012-08-05.11.00.124-0.rec' > /tmp/test.log 2>&1 &" + +set -x + +. /etc/vdr/vdrconvert.env + +if [ ! -z "$SERVER" ] +then + ssh $SERVER $0 $1 "'$2'" +else + printf "%s\n" "$2" >> $VCOQUEUEDIR/$1 +fi + diff --git a/cp_packages.sh b/cp_packages.sh new file mode 100644 index 0000000..372d64a --- /dev/null +++ b/cp_packages.sh @@ -0,0 +1,28 @@ + +#scripts/feeds update +#make + +cd ../ipk/ar71xx + + +#cp ../../base/bin/ar71xx/packages/fhem-enocean_eo_ar71xx.ipk . +#cp ../../base/bin/ar71xx/packages/fhem-trunk_trunk_ar71xx.ipk . +#cp ../../base/bin/ar71xx/packages/fhem-trunk_trunk_ar71xx.ipk . +cp ../../base/bin/ar71xx/packages/fhem*.ipk . + +#perl-device-serialport_1.04-2_ar71xx.ipk +cp ../../base/bin/ar71xx/packages/perl-device-serialport_*.ipk . +#perl-weather_0.5.5-1_ar71xx.ipk +cp ../../base/bin/ar71xx/packages/perl-weather_*.ipk . +cp ../../base/bin/ar71xx/packages/eibd*.ipk . +cp ../../base/bin/ar71xx/packages/linknx*.ipk . + +cp ../../base/bin/ar71xx/*.bin /home/marc/Dropbox-ipad/Public/ +cp ../../base/bin/ar71xx/md5sums /home/marc/Dropbox-ipad/Public/ + + +../../base/scripts/ipkg-make-index.sh . > Packages ; gzip -c Packages > Packages.gz +cp *.ipk /home/marc/Dropbox-ipad/Public/ipk/ar71xx/ +cp Packages.gz /home/marc/Dropbox-ipad/Public/ipk/ar71xx/ + +cd - diff --git a/create_omtb_garmin_img.sh b/create_omtb_garmin_img.sh new file mode 100755 index 0000000..70ca0c7 --- /dev/null +++ b/create_omtb_garmin_img.sh @@ -0,0 +1,140 @@ +#!/bin/zsh +# License: Creative Commons Share Alive 3.0 +# Copyright: 2012, Bernhard Tittelbach +# Thanks to malenki on #osm-de@oftc.net for constructive input and nagging me into making this thing useable in the first place + +# Required software: +# - zsh (obviously) +# - 7z +# - mkgmap (preferred) [http://www.mkgmap.org.uk/snapshots/] OR wine +# - gmt linux version [ http://www.anpo.republika.pl/download.html ] OR wine +# + +setopt extendedglob +setopt cshnullglob +SCRIPT_NAME=${0:t} +usage() +{ + print "\nUsage: $SCRIPT_NAME [options] " > /dev/stderr + print " as TYP-style you can choose:" > /dev/stderr + print " clas: classic layout - optimized for Vista/Legend series" > /dev/stderr + print " thin: thinner tracks and pathes - optimized for Gpsmap60/76 series" > /dev/stderr + print " wide: high contrast layout, like classic but with white forest - optimized for Oregon/Colorado dull displays" > /dev/stderr + print " hike: like classic layout - but optimized for hiking (does not show mtb/bicycle informations)" > /dev/stderr + print " easy: similar to classic layout - but focussed on easy readability hence not showing mtb/bicycle information except routes" > /dev/stderr + print " velo: (comes with velomap files) Layout optimized for small GPS screen" > /dev/stderr + print " or give the path to your own .TYP style file" > /dev/stderr + print "\nOptions:" > /dev/stderr + print " -m " > /dev/stderr + print " -o \n" > /dev/stderr + exit 1 + # descriptions taken from openmtbmap.org batch files +} + +zparseopts -A ARGS_A -D -E -- "m:" "o:" +OMTB_EXE="$1" +TYPFILE="$2" +GMT_CMD==gmt +MKGMAP=( ${ARGS_A[-m]}(.N,@-.) /usr/share/mkgmap/mkgmap.jar(.N,@-.) /usr/local/share/mkgmap/mkgmap.jar(.N,@-.) ${^path}/mkgmap.jar(.N,@-.) ) +MKGMAP="${MKGMAP[1]}" + +if ! [[ -x $GMT_CMD ]] ; then + if ! [[ -x =wine ]] ; then + print "ERROR: You need to either install wine or the gmt linux binary !" > /dev/stderr + exit 3 + fi + # use supplied gmt.exe with wine + GMT_CMD="wine ./gmt.exe" +fi + +if ! [[ -x =7z ]]; then + print "\nERROR: 7z is not installed, but needed to extract openmtbmap downloads !" + exit 3 +fi + +[[ -z $TYPFILE || ! -f $OMTB_EXE ]] && usage + +if [[ ${OMTB_EXE:t} == mtb* ]]; then + OMTBORVELO=openmtbmap + OMTB_NAME="${OMTB_EXE:t:r:s/mtb/}" +elif [[ ${OMTB_EXE:t} == velo* ]]; then + OMTBORVELO=openvelomap + OMTB_NAME="${OMTB_EXE:t:r:s/velo/}" +else + print "\nERROR: not a openmtbmap.org or openvelomap.org file ?" + usage +fi +DESC="${OMTBORVELO}_${OMTB_NAME}" +if [[ -d ${ARGS_A[-o]} ]]; then + DSTFILENAME="${ARGS_A[-o]:A}/${DESC}.img" + TMPDIR=${ARGS_A[-o]:A}/OMTB_tmp +else + DSTFILENAME="${OMTB_EXE:A:h}/${DESC}.img" + TMPDIR=${OMTB_EXE:A:h}/OMTB_tmp + [[ -n $ARGS_A[-o] ]] && {print "\nWarning: -o given but ${ARGS_A[-o]} is not a directory.\n Using ${OMTB_EXE:A:h} instead..\n"} +fi + +if [[ -e $DSTFILENAME ]]; then + print "\nWarning: the script will create (overwrite) $DSTFILENAME" + print " but $DSTFILENAME already exists." + read -q "?Continue and overwrite ? [y/N] " || exit 0 + print "" +fi + +if [[ -e $TMPDIR ]] ; then + print "\nWarning: the script want's to create directory $TMPDIR, but it already exists." + if [[ -d $TMPDIR ]] ; then + print " If you press [y], $OMTB_EXE will be extracted" + print " to $TMPDIR regardless of it's contents." + print " That's fine if it was created during a previous abortet run of this script." + print " Otherwise you should say [n] and move $OMTB_EXE into a clean directory." + read -q "?Continue ? [y/N] " || exit 0 + print "" + else + print " Please use another output directory and try again." + exit 1 + fi +else + mkdir $TMPDIR || exit 1 +fi + +FIMG_a=(${TMPDIR}/6<000-999>0000.img(N)) +if [[ -z $FIMG_a ]] ; then + print "Extracting $OMTB_EXE ..." + 7z x -y -o$TMPDIR ${OMTB_EXE} &>/dev/null || exit 1 + FIMG_a=(${TMPDIR}/6<000-999>0000.img(N[1])) + [[ -z $FIMG_a ]] && {print "\nERROR, could not find 6*.img file after extracting $OMTB_EXE" >/dev/stderr ; exit 1} +fi +if [[ -f $TYPFILE ]] ; then + TYPFILE="${TYPFILE:A}" +else + TYPFILE=( "${TMPDIR}/"(#i)${TYPFILE}*.typ(.N:A)) + TYPFILE="${TYPFILE[1]}" +fi + +trap "cd '$PWD'" EXIT +cd $TMPDIR || exit 5 + +if [[ -z $TYPFILE ]] ; then + print "\nERROR: TYP-file or -style not found" > /dev/stderr + print " please choose your own file or one of these styles: " *.(#l)TYP(.N:r) > /dev/stderr + exit 2 +fi + +print "using display-TYP-file: $TYPFILE" +cp $TYPFILE 01002468.TYP || exit 4 +FID=${${FIMG_a:t}[1][1,4]} +print using FID $FID + +$GMT_CMD -wy $FID 01002468.TYP +if [[ -n $MKGMAP ]]; then + print "using mkgmap, building address search index..." + #java -Xmx1000M -jar mkgmap.jar --family-id=$FID --index --description="$DESC" --series-name="$DESC" --family-name="$DESC" --show-profiles=1 --product-id=1 --gmapsupp 6*.img 7*.img 01002468.TYP + java -Xmx3000M -jar "$MKGMAP" --family-id=$FID --index --description="$DESC" --series-name="$DESC" --family-name="$DESC" --show-profiles=1 --product-id=1 --gmapsupp [67]*.img 01002468.TYP || exit 7 + mv (#i)gmapsupp.img "${DSTFILENAME}" || exit 7 +else + print "mkgmap not found, using gmt..." + $GMT_CMD -j -o "${DSTFILENAME}" -f $FID -m "$DESC" 6*.img 7*.img 01002468.TYP || exit 7 +fi +rm -R "$TMPDIR" +print "\nSuccessfully created ${DSTFILENAME}" diff --git a/create_opkg_index.sh b/create_opkg_index.sh new file mode 100644 index 0000000..f3efea6 --- /dev/null +++ b/create_opkg_index.sh @@ -0,0 +1 @@ +../../base/scripts/ipkg-make-index.sh . > Packages ; gzip -c Packages > Packages.gz diff --git a/createhdextlinks.sh b/createhdextlinks.sh new file mode 100644 index 0000000..4e3e8fb --- /dev/null +++ b/createhdextlinks.sh @@ -0,0 +1,9 @@ + + +#dirs=$(find .. -maxdepth 1 -type d ! -name "*.rec" -exec find {} -maxdepth 1 -name "*.rec" \;) +dirs=$(find .. -maxdepth 1 -type d -name "*.rec") +for i in $dirs; do + ln -s $i + echo $i +done + \ No newline at end of file diff --git a/createhdextlinks.sh~ b/createhdextlinks.sh~ new file mode 100644 index 0000000..a4d571f --- /dev/null +++ b/createhdextlinks.sh~ @@ -0,0 +1,7 @@ + + +dirs=§(find .. -type d -maxdepth 1 ! -name "*.rec" -exec find {} -maxdepth 1 -name "*.rec"} +for i in $dirs do + echo $i +done + \ No newline at end of file diff --git a/dropbox.py b/dropbox.py new file mode 100755 index 0000000..bd4ead5 --- /dev/null +++ b/dropbox.py @@ -0,0 +1,821 @@ +#!/usr/bin/python +# +# Copyright 2008 Evenflow, Inc. +# +# dropbox.py +# Dropbox frontend script +# +# dropbox.py is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# dropbox.py is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with dropbox.py. If not, see . +# + +from __future__ import with_statement + +import sys +import optparse +import socket +import os +import time +import platform +import tarfile +import threading +import urllib +import subprocess +import fcntl +import errno +import locale +from contextlib import closing + +INFO = u"Dropbox is the easiest way to share and store your files online. Want to learn more? Head to" +LINK = u"http://www.getdropbox.com/" +WARNING = u"In order to use Dropbox, you must download the proprietary daemon." + +DOWNLOADING = u"Downloading Dropbox... %d%%" +UNPACKING = u"Unpacking Dropbox... %d%%" + +PARENT_DIR = os.path.expanduser("~") +DROPBOXD_PATH = "%s/.dropbox-dist/dropboxd" % PARENT_DIR + +enc = locale.getpreferredencoding() +def console_print(st=u"", f=sys.stdout, linebreak=True): + global enc + assert type(st) is unicode + f.write(st.encode(enc)) + if linebreak: f.write(os.linesep) + +def console_flush(f=sys.stdout): + f.flush() + +def yes_no_question(question): + while True: + console_print(question, linebreak=False) + console_print(u" [y/n] ", linebreak=False) + console_flush() + text = raw_input() + if text.lower().startswith("y"): + return True + elif text.lower().startswith("n"): + return False + else: + console_print(u"Sorry, I didn't understand that. Please type yes or no.") + +def plat(): + if sys.platform.lower().startswith('linux'): + arch = platform.machine() + if (arch[0] == 'i' and + arch[1].isdigit() and + arch[2:4] == '86'): + plat = "x86" + elif arch == 'x86_64': + plat = arch + else: + FatalVisibleError("Platform not supported") + return "lnx.%s" % plat + else: + FatalVisibleError("Platform not supported") + +def is_dropbox_running(): + pidfile = os.path.expanduser("~/.dropbox/dropbox.pid") + + try: + with open(pidfile, "r") as f: + pid = int(f.read()) + with open("/proc/%d/cmdline" % pid, "r") as f: + cmdline = f.read().lower() + except: + cmdline = "" + + return "dropbox" in cmdline + +def unicode_abspath(path): + global enc + assert type(path) is unicode + # shouldn't pass unicode to this craphead, it appends with os.getcwd() which is always a str + return os.path.abspath(path.encode(sys.getfilesystemencoding())).decode(sys.getfilesystemencoding()) + +# This sets a custom User-Agent +class DropboxURLopener(urllib.FancyURLopener): + version = "DropboxLinuxDownloader/0.6.1" +urllib._urlopener = DropboxURLopener() + +class DownloadState(object): + def __init__(self): + try: + self.file = urllib.urlopen("http://www.getdropbox.com/download?plat=%s" % plat()) + except IOError: + FatalVisibleError("Trouble connecting to Dropbox servers. Maybe your internet connection is down, or you need to set your http_proxy environment variable.") + + fcntl.fcntl(self.file, fcntl.F_SETFL, os.O_NONBLOCK) + + self.size = int(self.file.info()['content-length']) + self.progress = 0 + + self.local_path = "%s/dropbox.tar.gz" % PARENT_DIR + self.local_file = open(self.local_path, 'wb') + + def copy_data(self): + while True: + try: + chunk = os.read(self.file.fileno(), 4096) + self.progress += len(chunk) + self.local_file.write(chunk) + yield True + if self.progress == self.size: + break + except OSError, e: + if hasattr(e, 'errno') and e.errno == errno.EAGAIN: + # nothing left to read + yield False + else: + raise + + self.file.close() + + def unpack(self): + self.local_file.close() + archive = tarfile.open(self.local_path, 'r:gz') + total_members = len(archive.getmembers()) + for i, member in enumerate(archive.getmembers()): + archive.extract(member, PARENT_DIR) + yield member.name, i, total_members + archive.close() + os.remove(self.local_path) + + def cancel(self): + if not self.local_file.closed: + self.local_file.close() + if os.path.exists(self.local_path): + os.remove(self.local_path) + +def load_serialized_images(): + global box_logo_pixbuf, window_icon + import gtk + box_logo_pixbuf = gtk.gdk.pixbuf_new_from_data('\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x08\x00\\\x9ef\x00\\\x9ej\x00\\\x9e\x04\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9eZ\x00[\x9er\x00\\\x9e\x14\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e8\x00Y\x9c\xc2\x00X\x9b\xff\x00X\x9b\xff\x00[\x9d\xaa\x00\\\x9e\r\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x02\x00\\\x9e\x8e\x00Y\x9b\xff\x00Y\x9b\xff\x00Y\x9b\xd5\x00\\\x9eM\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x12\x00[\x9d\x8b\x00U\x99\xfa\x0fe\xa5\xff]\xa2\xd3\xffM\x95\xc9\xff\x00X\x9b\xff\x00Y\x9c\xc9\x00\\\x9e\x1e\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x0f\x00[\x9d\xb1\x00V\x99\xff4\x85\xc1\xffZ\xa3\xda\xff\x17m\xab\xff\x00V\x99\xff\x00Z\x9d\xa2\x00\\\x9e \x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\\\x00W\x9a\xde\x00Y\x9c\xff:\x87\xbf\xff\x83\xbf\xeb\xff\x98\xce\xf6\xff\x9b\xd0\xf6\xffa\xa3\xd3\xff\x05]\x9e\xff\x00X\x9b\xda\x00\\\x9e/\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x1c\x00Z\x9c\xc5\x01Y\x9b\xff?\x90\xca\xff|\xc1\xf4\xff\x82\xc4\xf6\xff}\xbf\xf0\xffD\x90\xc8\xff\x05]\x9e\xff\x00V\x9a\xed\x00\\\x9es\x00\\\x9e\x07\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e4\x00Z\x9c\xba\x00V\x99\xff\x1dq\xae\xffd\xaa\xdd\xff\x8e\xc9\xf5\xff\x8e\xc7\xf3\xff\x8f\xc7\xf1\xff\x92\xc9\xf1\xff\xa1\xd2\xf6\xffw\xb3\xde\xff\x0fd\xa3\xff\x00V\x9a\xed\x00\\\x9eL\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e4\x00X\x9b\xdd\x05^\x9f\xffM\x9d\xd6\xffy\xc1\xf6\xffw\xbe\xf2\xffz\xbe\xf1\xff\x80\xc1\xf2\xff\x89\xc8\xf6\xffq\xb3\xe3\xff*z\xb5\xff\x00W\x9a\xff\x00X\x9b\xcd\x00\\\x9eG\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x0e\x00[\x9d\x86\x00V\x99\xfa\x0cc\xa4\xffK\x96\xce\xff\x81\xc2\xf2\xff\x89\xc7\xf5\xff\x87\xc4\xf1\xff\x8b\xc5\xf1\xff\x8f\xc7\xf1\xff\x92\xc9\xf1\xff\x97\xcb\xf1\xff\xa4\xd3\xf6\xff\x85\xbb\xe4\xff\x18k\xa8\xff\x00U\x99\xfc\x00\\\x9en\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9eS\x00W\x9a\xf1\x0bb\xa3\xffT\xa3\xdd\xffv\xc0\xf7\xffr\xbb\xf1\xffv\xbd\xf1\xffz\xbe\xf1\xff~\xc0\xf1\xff\x81\xc2\xf1\xff\x8a\xc7\xf4\xff\x8f\xc9\xf4\xff`\xa3\xd5\xff\x15i\xa8\xff\x00U\x98\xff\x00[\x9d\x9c\x00\\\x9e\x1a\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9eU\x00X\x9b\xd9\x00Z\x9c\xff1\x83\xbf\xffp\xb6\xea\xff\x84\xc5\xf6\xff\x80\xc2\xf2\xff\x83\xc2\xf1\xff\x87\xc4\xf1\xff\x8b\xc5\xf1\xff\x8f\xc7\xf1\xff\x92\xc9\xf1\xff\x97\xcb\xf1\xff\x9b\xcc\xf1\xff\xa6\xd3\xf5\xff\x96\xc7\xeb\xff*y\xb2\xff\x00T\x98\xff\x00\\\x9e\x90\x00\\\x9e\x02\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9eu\x00V\x99\xfe\x14k\xac\xff\\\xac\xe6\xffr\xbd\xf6\xffo\xba\xf1\xffr\xbb\xf1\xffv\xbd\xf1\xffz\xbe\xf1\xff~\xc0\xf1\xff\x81\xc2\xf1\xff\x85\xc3\xf1\xff\x8b\xc5\xf1\xff\x95\xcc\xf6\xff\x8c\xc5\xee\xffH\x90\xc5\xff\x04]\x9e\xff\x00V\x9a\xe7\x00\\\x9ej\x00\\\x9e\x03\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e.\x00Z\x9c\xb3\x00V\x99\xff\x17m\xad\xffV\xa3\xdc\xff{\xc2\xf6\xff|\xbf\xf3\xff|\xbf\xf1\xff\x7f\xc1\xf1\xff\x83\xc2\xf1\xff\x87\xc4\xf1\xff\x8b\xc5\xf1\xff\x8f\xc7\xf1\xff\x92\xc9\xf1\xff\x97\xcb\xf1\xff\x9b\xcc\xf1\xff\x9e\xcd\xf1\xff\xa6\xd3\xf4\xff\xa4\xd1\xf1\xff@\x88\xbd\xff\x00U\x99\xff\x00[\x9d\xb0\x00\\\x9e\x0c\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x02\x00[\x9d\x97\x00V\x98\xff\x1fv\xb6\xffa\xb1\xed\xffl\xbb\xf4\xffl\xb8\xf1\xffo\xba\xf1\xffr\xbb\xf1\xffv\xbd\xf1\xffz\xbe\xf1\xff~\xc0\xf1\xff\x81\xc2\xf1\xff\x85\xc3\xf1\xff\x8a\xc5\xf1\xff\x8d\xc6\xf1\xff\x93\xcb\xf2\xff\x9e\xd1\xf6\xff|\xb7\xe1\xff(w\xb2\xff\x00U\x99\xff\x00Y\x9c\xc6\x00\\\x9e?\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x0b\x00[\x9e\x86\x00V\x99\xf6\ta\xa2\xff=\x8f\xcc\xffm\xb9\xf1\xffu\xbf\xf5\xfft\xbc\xf1\xffy\xbd\xf1\xff|\xbf\xf1\xff\x7f\xc1\xf1\xff\x83\xc2\xf1\xff\x87\xc4\xf1\xff\x8b\xc5\xf1\xff\x8f\xc7\xf1\xff\x92\xc9\xf1\xff\x97\xcb\xf1\xff\x9b\xcc\xf1\xff\x9e\xcd\xf1\xff\xa1\xcf\xf1\xff\xa8\xd3\xf3\xff\xae\xd8\xf4\xffX\x99\xc9\xff\x00X\x9b\xff\x00Y\x9c\xc2\x00\\\x9e\x1b\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\r\x00[\x9d\xab\x00W\x99\xff,\x82\xc1\xffe\xb5\xf2\xffh\xb7\xf3\xffh\xb7\xf1\xffl\xb8\xf1\xffo\xba\xf1\xffr\xbb\xf1\xffv\xbd\xf1\xffz\xbe\xf1\xff~\xc0\xf1\xff\x81\xc2\xf1\xff\x85\xc3\xf1\xff\x8a\xc5\xf1\xff\x8d\xc6\xf1\xff\x90\xc9\xf1\xff\x95\xca\xf1\xff\x9f\xd1\xf5\xff\xa0\xcf\xf3\xffe\xa3\xd1\xff\x12f\xa5\xff\x00U\x98\xff\x00[\x9d\x9b\x00\\\x9e\x16\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9eN\x00Y\x9b\xd3\x00Y\x9c\xff\'}\xbc\xff]\xad\xe8\xffp\xbe\xf6\xffn\xba\xf2\xffp\xba\xf1\xfft\xbc\xf1\xffy\xbd\xf1\xff|\xbf\xf1\xff\x7f\xc1\xf1\xff\x83\xc2\xf1\xff\x87\xc4\xf1\xff\x8b\xc5\xf1\xff\x8f\xc7\xf1\xff\x92\xc9\xf1\xff\x97\xcb\xf1\xff\x9b\xcc\xf1\xff\x9e\xcd\xf1\xff\xa1\xcf\xf1\xff\xa5\xd1\xf1\xff\xa9\xd4\xf2\xff\xb5\xdb\xf6\xffq\xaa\xd4\xff\x04[\x9e\xff\x00X\x9b\xdc\x00\\\x9e>\x00\\\x9e0\x00Z\x9c\xc9\x00Z\x9b\xff8\x8d\xcd\xffe\xb7\xf5\xffc\xb4\xf2\xffe\xb5\xf1\xffh\xb7\xf1\xffl\xb8\xf1\xffo\xba\xf1\xffr\xbb\xf1\xffv\xbd\xf1\xffz\xbe\xf1\xff~\xc0\xf1\xff\x81\xc2\xf1\xff\x85\xc3\xf1\xff\x8a\xc5\xf1\xff\x8d\xc6\xf1\xff\x90\xc9\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9d\xce\xf2\xff\xa9\xd5\xf6\xff\x99\xc9\xec\xffI\x8e\xc1\xff\x03[\x9d\xff\x00V\x9a\xe1\x00\\\x9ea\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e(\x00[\x9d\xab\x00V\x98\xff\x13j\xab\xffK\x9e\xdc\xffi\xb9\xf6\xffj\xb8\xf3\xffj\xb8\xf1\xffm\xb9\xf1\xffp\xba\xf1\xfft\xbc\xf1\xffy\xbd\xf1\xff|\xbf\xf1\xff\x7f\xc1\xf1\xff\x83\xc2\xf1\xff\x87\xc4\xf1\xff\x8b\xc5\xf1\xff\x8f\xc7\xf1\xff\x92\xc9\xf1\xff\x97\xcb\xf1\xff\x9b\xcc\xf1\xff\x9e\xcd\xf1\xff\xa1\xcf\xf1\xff\xa5\xd1\xf1\xff\xa7\xd3\xf1\xff\xaa\xd4\xf1\xff\xb9\xdc\xf6\xff\x80\xb5\xda\xff\rb\xa2\xff\x00W\x9a\xff\x00Y\x9b\xfe\x04]\x9f\xff>\x94\xd4\xffd\xb6\xf6\xff`\xb3\xf1\xffb\xb3\xf1\xffe\xb5\xf1\xffh\xb7\xf1\xffl\xb8\xf1\xffo\xba\xf1\xffr\xbb\xf1\xffv\xbd\xf1\xffz\xbe\xf1\xff~\xc0\xf1\xff\x81\xc2\xf1\xff\x85\xc3\xf1\xff\x8a\xc5\xf1\xff\x8d\xc6\xf1\xff\x90\xc9\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9c\xcd\xf1\xff\x9f\xce\xf1\xff\xa6\xd2\xf3\xff\xb0\xd9\xf6\xff\x87\xbb\xe0\xff\'u\xaf\xff\x00T\x98\xff\x00Y\x9c\xbd\x00\\\x9e7\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x08\x00\\\x9e~\x00W\x99\xf2\x05^\x9f\xff3\x89\xc9\xff^\xb1\xf0\xffe\xb7\xf5\xffd\xb4\xf1\xffg\xb6\xf1\xffj\xb8\xf1\xffm\xb9\xf1\xffp\xba\xf1\xfft\xbc\xf1\xffy\xbd\xf1\xff|\xbf\xf1\xff\x7f\xc1\xf1\xff\x83\xc2\xf1\xff\x87\xc4\xf1\xff\x8b\xc5\xf1\xff\x8f\xc7\xf1\xff\x92\xc9\xf1\xff\x97\xcb\xf1\xff\x9b\xcc\xf1\xff\x9e\xcd\xf1\xff\xa1\xcf\xf1\xff\xa5\xd1\xf1\xff\xa7\xd3\xf1\xff\xaa\xd4\xf1\xff\xad\xd4\xf1\xff\xbb\xdd\xf6\xff\x96\xc3\xe4\xff\x18i\xa7\xff\x01]\xa2\xffH\x9e\xde\xffa\xb6\xf6\xff^\xb1\xf1\xff`\xb3\xf1\xffb\xb3\xf1\xffe\xb5\xf1\xffh\xb7\xf1\xffl\xb8\xf1\xffo\xba\xf1\xffr\xbb\xf1\xffv\xbd\xf1\xffz\xbe\xf1\xff~\xc0\xf1\xff\x81\xc2\xf1\xff\x85\xc3\xf1\xff\x8a\xc5\xf1\xff\x8d\xc6\xf1\xff\x90\xc9\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9c\xcd\xf1\xff\x9f\xce\xf1\xff\xa3\xd0\xf1\xff\xa6\xd2\xf1\xff\xb0\xd8\xf5\xff\xad\xd5\xf1\xfff\xa2\xce\xff\rb\xa2\xff\x00U\x99\xfb\x00\\\x9e\x92\x00\\\x9e\x11\x00\\\x9e\x9b\x02\\\x9e\xff\x1ct\xb5\xffM\xa3\xe3\xffb\xb7\xf6\xff`\xb3\xf2\xffa\xb3\xf1\xffd\xb4\xf1\xffg\xb6\xf1\xffj\xb8\xf1\xffm\xb9\xf1\xffp\xba\xf1\xfft\xbc\xf1\xffy\xbd\xf1\xff|\xbf\xf1\xff\x7f\xc1\xf1\xff\x83\xc2\xf1\xff\x87\xc4\xf1\xff\x8b\xc5\xf1\xff\x8f\xc7\xf1\xff\x92\xc9\xf1\xff\x97\xcb\xf1\xff\x9b\xcc\xf1\xff\x9e\xcd\xf1\xff\xa1\xcf\xf1\xff\xa5\xd1\xf1\xff\xa7\xd3\xf1\xff\xaa\xd4\xf1\xff\xad\xd4\xf1\xff\xae\xd5\xf1\xff\xb7\xdb\xf4\xff\xaa\xcf\xe8\xffm\xb3\xe6\xffX\xb2\xf4\xffX\xae\xf1\xff^\xb1\xf1\xff`\xb3\xf1\xffb\xb3\xf1\xffe\xb5\xf1\xffh\xb7\xf1\xffl\xb8\xf1\xffo\xba\xf1\xffr\xbb\xf1\xffv\xbd\xf1\xffz\xbe\xf1\xff~\xc0\xf1\xff\x81\xc2\xf1\xff\x85\xc3\xf1\xff\x8a\xc5\xf1\xff\x8d\xc6\xf1\xff\x90\xc9\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9c\xcd\xf1\xff\x9f\xce\xf1\xff\xa3\xd0\xf1\xff\xa6\xd2\xf1\xff\xa9\xd3\xf1\xff\xae\xd5\xf2\xff\xba\xdd\xf7\xff\x9b\xc7\xe6\xff<\x83\xb8\xff\x06^\x9f\xff\x00[\x9d\xb6\x00Z\x9c\xdd\x0cd\xa6\xffR\xa9\xe9\xffb\xb7\xf8\xff\\\xb1\xf1\xff_\xb2\xf1\xffa\xb3\xf1\xffd\xb4\xf1\xffg\xb6\xf1\xffj\xb8\xf1\xffm\xb9\xf1\xffp\xba\xf1\xfft\xbc\xf1\xffy\xbd\xf1\xff|\xbf\xf1\xff\x7f\xc1\xf1\xff\x83\xc2\xf1\xff\x87\xc4\xf1\xff\x8b\xc5\xf1\xff\x8f\xc7\xf1\xff\x92\xc9\xf1\xff\x97\xcb\xf1\xff\x9b\xcc\xf1\xff\x9e\xcd\xf1\xff\xa1\xcf\xf1\xff\xa5\xd1\xf1\xff\xa7\xd3\xf1\xff\xaa\xd4\xf1\xff\xaa\xd2\xf0\xff\xb2\xd7\xf1\xff\xce\xe5\xf6\xff\xe9\xf5\xfd\xff\xd0\xeb\xfe\xff\xa1\xd2\xf7\xffg\xb6\xf2\xffW\xad\xf0\xff_\xb2\xf1\xffb\xb3\xf1\xffe\xb5\xf1\xffh\xb7\xf1\xffl\xb8\xf1\xffo\xba\xf1\xffr\xbb\xf1\xffv\xbd\xf1\xffz\xbe\xf1\xff~\xc0\xf1\xff\x81\xc2\xf1\xff\x85\xc3\xf1\xff\x8a\xc5\xf1\xff\x8d\xc6\xf1\xff\x90\xc9\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9c\xcd\xf1\xff\x9f\xce\xf1\xff\xa3\xd0\xf1\xff\xa6\xd2\xf1\xff\xa9\xd3\xf1\xff\xac\xd4\xf1\xff\xae\xd4\xf1\xff\xbf\xe0\xf7\xff\xac\xd2\xee\xff\x1eo\xaa\xff\x00X\x9b\xeb\x00\\\x9eR\x00Y\x9b\xf6\x0ce\xa6\xffH\x9e\xde\xffb\xb6\xf6\xff_\xb2\xf1\xffa\xb3\xf1\xffd\xb4\xf1\xffg\xb6\xf1\xffj\xb8\xf1\xffm\xb9\xf1\xffp\xba\xf1\xfft\xbc\xf1\xffy\xbd\xf1\xff|\xbf\xf1\xff\x7f\xc1\xf1\xff\x83\xc2\xf1\xff\x87\xc4\xf1\xff\x8b\xc5\xf1\xff\x8f\xc7\xf1\xff\x92\xc9\xf1\xff\x97\xcb\xf1\xff\x9b\xcc\xf1\xff\x9e\xcd\xf1\xff\xa1\xcf\xf1\xff\xa5\xd1\xf1\xff\xa5\xd2\xf1\xff\xa8\xd2\xf0\xff\xbe\xdd\xf4\xff\xdd\xee\xfa\xff\xe9\xf3\xfc\xff\xe4\xf2\xfb\xff\xca\xe7\xfb\xff\xce\xe8\xfb\xff\xc3\xe2\xfa\xff\x89\xc6\xf5\xff]\xb1\xf1\xff]\xb1\xf0\xffe\xb5\xf1\xffh\xb7\xf1\xffl\xb8\xf1\xffo\xba\xf1\xffr\xbb\xf1\xffv\xbd\xf1\xffz\xbe\xf1\xff~\xc0\xf1\xff\x81\xc2\xf1\xff\x85\xc3\xf1\xff\x8a\xc5\xf1\xff\x8d\xc6\xf1\xff\x90\xc9\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9c\xcd\xf1\xff\x9f\xce\xf1\xff\xa3\xd0\xf1\xff\xa6\xd2\xf1\xff\xa9\xd3\xf1\xff\xac\xd4\xf1\xff\xba\xdd\xf6\xff\x93\xc1\xe3\xff\x1fo\xaa\xff\x00W\x9b\xff\x00\\\x9eo\x00\\\x9e\x00\x00\\\x9e;\x00Y\x9b\xdf\x03\\\x9e\xff;\x90\xd0\xffd\xb6\xf5\xffb\xb4\xf2\xffd\xb4\xf1\xffg\xb6\xf1\xffj\xb8\xf1\xffm\xb9\xf1\xffp\xba\xf1\xfft\xbc\xf1\xffy\xbd\xf1\xff|\xbf\xf1\xff\x7f\xc1\xf1\xff\x83\xc2\xf1\xff\x87\xc4\xf1\xff\x8b\xc5\xf1\xff\x8f\xc7\xf1\xff\x92\xc9\xf1\xff\x97\xcb\xf1\xff\x9b\xcc\xf1\xff\x9e\xcd\xf1\xff\xa0\xcf\xf1\xff\xa1\xcf\xf0\xff\xae\xd6\xf2\xff\xcf\xe6\xf8\xff\xe4\xf2\xfb\xff\xe5\xf2\xfb\xff\xe5\xf1\xfb\xff\xe4\xf2\xfb\xff\xca\xe7\xfb\xff\xc8\xe5\xfb\xff\xcb\xe7\xfb\xff\xd1\xe9\xfb\xff\xb3\xda\xf9\xffx\xbe\xf3\xff^\xb1\xf0\xfff\xb6\xf1\xffl\xb8\xf1\xffo\xba\xf1\xffr\xbb\xf1\xffv\xbd\xf1\xffz\xbe\xf1\xff~\xc0\xf1\xff\x81\xc2\xf1\xff\x85\xc3\xf1\xff\x8a\xc5\xf1\xff\x8d\xc6\xf1\xff\x90\xc9\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9c\xcd\xf1\xff\x9f\xce\xf1\xff\xa3\xd0\xf1\xff\xa6\xd2\xf1\xff\xaa\xd4\xf2\xff\xb7\xdb\xf6\xffx\xaf\xd6\xff\x0b`\xa1\xff\x00V\x9a\xed\x00\\\x9eR\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x1c\x00Z\x9c\xbe\x00X\x99\xff-\x83\xc2\xffe\xb6\xf3\xfff\xb6\xf3\xffg\xb6\xf1\xffj\xb8\xf1\xffm\xb9\xf1\xffp\xba\xf1\xfft\xbc\xf1\xffy\xbd\xf1\xff|\xbf\xf1\xff\x7f\xc1\xf1\xff\x83\xc2\xf1\xff\x87\xc4\xf1\xff\x8b\xc5\xf1\xff\x8f\xc7\xf1\xff\x92\xc9\xf1\xff\x97\xcb\xf1\xff\x9b\xcc\xf1\xff\x9b\xcc\xf0\xff\xa1\xcf\xf1\xff\xbf\xde\xf6\xff\xdc\xee\xfa\xff\xe3\xf1\xfb\xff\xe2\xf1\xfb\xff\xe3\xf1\xfb\xff\xe5\xf1\xfb\xff\xe4\xf2\xfb\xff\xca\xe7\xfb\xff\xc8\xe5\xfb\xff\xc9\xe6\xfb\xff\xcb\xe6\xfb\xff\xd2\xe8\xfb\xff\xd0\xe9\xfb\xff\xa2\xd2\xf7\xffm\xb9\xf1\xffe\xb5\xf0\xffo\xba\xf1\xffr\xbb\xf1\xffv\xbd\xf1\xffz\xbe\xf1\xff~\xc0\xf1\xff\x81\xc2\xf1\xff\x85\xc3\xf1\xff\x8a\xc5\xf1\xff\x8d\xc6\xf1\xff\x90\xc9\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9c\xcd\xf1\xff\x9f\xce\xf1\xff\xa3\xd0\xf1\xff\xa9\xd4\xf2\xff\xb1\xd9\xf5\xff[\x9b\xc9\xff\x00X\x9b\xff\x00Y\x9c\xd3\x00\\\x9e-\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x06\x00[\x9d\x96\x00V\x99\xff"x\xb8\xffa\xb1\xee\xffk\xba\xf4\xffj\xb8\xf1\xffm\xb9\xf1\xffp\xba\xf1\xfft\xbc\xf1\xffy\xbd\xf1\xff|\xbf\xf1\xff\x7f\xc1\xf1\xff\x83\xc2\xf1\xff\x87\xc4\xf1\xff\x8b\xc5\xf1\xff\x8f\xc7\xf1\xff\x92\xc9\xf1\xff\x96\xca\xf1\xff\x97\xca\xf0\xff\xac\xd5\xf3\xff\xd0\xe7\xf9\xff\xe0\xef\xfb\xff\xdf\xef\xfb\xff\xe0\xf0\xfb\xff\xe2\xf1\xfb\xff\xe3\xf1\xfb\xff\xe5\xf1\xfb\xff\xe4\xf2\xfb\xff\xca\xe7\xfb\xff\xc8\xe5\xfb\xff\xc9\xe6\xfb\xff\xcb\xe6\xfb\xff\xcd\xe6\xfb\xff\xd0\xea\xfb\xff\xd8\xec\xfb\xff\xc8\xe5\xfa\xff\x8f\xc9\xf4\xffi\xb7\xf0\xffo\xb9\xf1\xffv\xbd\xf1\xffz\xbe\xf1\xff~\xc0\xf1\xff\x81\xc2\xf1\xff\x85\xc3\xf1\xff\x8a\xc5\xf1\xff\x8d\xc6\xf1\xff\x90\xc9\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9c\xcd\xf1\xff\x9f\xce\xf1\xff\xa8\xd4\xf4\xff\xa6\xd2\xf1\xffE\x8c\xbf\xff\x00U\x99\xff\x00Z\x9d\xaf\x00\\\x9e\x12\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9en\x00V\x98\xfe\x14k\xac\xffY\xaa\xe5\xffp\xbd\xf6\xffm\xb9\xf1\xffp\xba\xf1\xfft\xbc\xf1\xffy\xbd\xf1\xff|\xbf\xf1\xff\x7f\xc1\xf1\xff\x83\xc2\xf1\xff\x87\xc4\xf1\xff\x8b\xc5\xf1\xff\x8f\xc7\xf1\xff\x8e\xc7\xf0\xff\x9a\xcc\xf1\xff\xbd\xde\xf7\xff\xd8\xec\xfb\xff\xdc\xed\xfb\xff\xdc\xed\xfb\xff\xde\xef\xfb\xff\xe0\xf0\xfb\xff\xe2\xf1\xfb\xff\xe3\xf1\xfb\xff\xe5\xf1\xfb\xff\xe4\xf2\xfb\xff\xca\xe7\xfb\xff\xc8\xe5\xfb\xff\xc9\xe6\xfb\xff\xcb\xe6\xfb\xff\xcd\xe6\xfb\xff\xcf\xe9\xfb\xff\xd1\xe9\xfb\xff\xd6\xec\xfb\xff\xda\xed\xfb\xff\xb6\xdc\xf8\xff\x80\xc1\xf2\xffo\xb9\xf0\xffy\xbd\xf1\xff~\xc0\xf1\xff\x81\xc2\xf1\xff\x85\xc3\xf1\xff\x8a\xc5\xf1\xff\x8d\xc6\xf1\xff\x90\xc9\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9c\xcd\xf1\xff\xa7\xd4\xf5\xff\x95\xc7\xea\xff+y\xb2\xff\x00T\x98\xff\x00[\x9e\x88\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9eQ\x00W\x9a\xee\x08a\xa2\xffL\x9d\xd8\xfft\xbf\xf6\xffq\xbb\xf2\xfft\xbc\xf1\xffy\xbd\xf1\xff|\xbf\xf1\xff\x7f\xc1\xf1\xff\x83\xc2\xf1\xff\x87\xc4\xf1\xff\x88\xc4\xf1\xff\x8d\xc6\xf0\xff\xaa\xd5\xf4\xff\xcd\xe7\xfa\xff\xd8\xed\xfb\xff\xd7\xec\xfb\xff\xda\xec\xfb\xff\xdc\xed\xfb\xff\xde\xef\xfb\xff\xe0\xf0\xfb\xff\xe2\xf1\xfb\xff\xe3\xf1\xfb\xff\xe5\xf1\xfb\xff\xe4\xf2\xfb\xff\xca\xe7\xfb\xff\xc8\xe5\xfb\xff\xc9\xe6\xfb\xff\xcb\xe6\xfb\xff\xcd\xe6\xfb\xff\xcf\xe9\xfb\xff\xd1\xe9\xfb\xff\xd3\xea\xfb\xff\xd5\xeb\xfb\xff\xdd\xef\xfc\xff\xd7\xeb\xfb\xff\xa6\xd4\xf5\xff{\xbe\xf1\xffy\xbd\xf1\xff\x81\xc2\xf1\xff\x85\xc3\xf1\xff\x8a\xc5\xf1\xff\x8d\xc6\xf1\xff\x90\xc9\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\xa6\xd4\xf6\xff~\xb6\xdf\xff\x15h\xa7\xff\x00U\x99\xf9\x00\\\x9ek\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e-\x00Y\x9c\xd2\x01Y\x9c\xff<\x8e\xca\xffu\xbe\xf4\xffv\xbe\xf2\xffy\xbd\xf1\xff|\xbf\xf1\xff\x7f\xc1\xf1\xff\x82\xc1\xf1\xff\x83\xc1\xf0\xff\x97\xcb\xf3\xff\xbe\xe0\xf8\xff\xd4\xeb\xfb\xff\xd5\xeb\xfb\xff\xd5\xeb\xfb\xff\xd7\xec\xfb\xff\xda\xec\xfb\xff\xdc\xed\xfb\xff\xde\xef\xfb\xff\xe0\xf0\xfb\xff\xe2\xf1\xfb\xff\xe3\xf1\xfb\xff\xe5\xf1\xfb\xff\xe4\xf2\xfb\xff\xca\xe7\xfb\xff\xc8\xe5\xfb\xff\xc9\xe6\xfb\xff\xcb\xe6\xfb\xff\xcd\xe6\xfb\xff\xcf\xe9\xfb\xff\xd1\xe9\xfb\xff\xd3\xea\xfb\xff\xd5\xeb\xfb\xff\xd7\xec\xfb\xff\xdc\xee\xfb\xff\xe3\xf0\xfc\xff\xcd\xe7\xf9\xff\x98\xcc\xf3\xff|\xbf\xf0\xff\x82\xc2\xf1\xff\x8a\xc5\xf1\xff\x8d\xc6\xf1\xff\x90\xc9\xf1\xff\x96\xcb\xf2\xff\xa1\xd2\xf5\xffc\xa3\xd2\xff\x06]\x9f\xff\x00W\x9b\xe5\x00\\\x9eC\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x12\x00[\x9d\xaf\x00V\x98\xff.\x81\xbe\xffv\xbd\xf2\xff|\xc0\xf4\xff|\xbf\xf1\xff{\xbf\xf0\xff\x83\xc2\xf1\xff\xaa\xd5\xf6\xff\xcc\xe6\xfb\xff\xd1\xea\xfb\xff\xd1\xe9\xfb\xff\xd3\xea\xfb\xff\xd5\xeb\xfb\xff\xd7\xec\xfb\xff\xda\xec\xfb\xff\xdc\xed\xfb\xff\xde\xef\xfb\xff\xe0\xf0\xfb\xff\xe2\xf1\xfb\xff\xe3\xf1\xfb\xff\xe5\xf1\xfb\xff\xe4\xf2\xfb\xff\xca\xe7\xfb\xff\xc8\xe5\xfb\xff\xc9\xe6\xfb\xff\xcb\xe6\xfb\xff\xcd\xe6\xfb\xff\xcf\xe9\xfb\xff\xd1\xe9\xfb\xff\xd3\xea\xfb\xff\xd5\xeb\xfb\xff\xd7\xec\xfb\xff\xda\xed\xfb\xff\xdc\xed\xfb\xff\xe2\xf1\xfb\xff\xe3\xf2\xfb\xff\xbe\xdf\xf7\xff\x8b\xc6\xf1\xff\x84\xc2\xf0\xff\x8c\xc5\xf1\xff\x94\xcb\xf3\xff\x9b\xcf\xf4\xffK\x92\xc6\xff\x00W\x9a\xff\x00Y\x9c\xc7\x00\\\x9e#\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x8c\x00V\x98\xfd u\xb3\xffn\xb4\xe8\xff~\xc0\xf3\xff\x94\xca\xf4\xff\xbe\xe0\xf9\xff\xcf\xe8\xfb\xff\xcd\xe6\xfb\xff\xce\xe9\xfb\xff\xd1\xe9\xfb\xff\xd3\xea\xfb\xff\xd5\xeb\xfb\xff\xd7\xec\xfb\xff\xda\xec\xfb\xff\xdc\xed\xfb\xff\xde\xef\xfb\xff\xe0\xf0\xfb\xff\xe2\xf1\xfb\xff\xe3\xf1\xfb\xff\xe5\xf1\xfb\xff\xe4\xf2\xfb\xff\xca\xe7\xfb\xff\xc8\xe5\xfb\xff\xc9\xe6\xfb\xff\xcb\xe6\xfb\xff\xcd\xe6\xfb\xff\xcf\xe9\xfb\xff\xd1\xe9\xfb\xff\xd3\xea\xfb\xff\xd5\xeb\xfb\xff\xd7\xec\xfb\xff\xda\xed\xfb\xff\xdc\xed\xfb\xff\xde\xef\xfb\xff\xe1\xf0\xfb\xff\xe8\xf3\xfb\xff\xdb\xed\xfa\xff\xac\xd5\xf4\xff\x8f\xc7\xf2\xff\x89\xc3\xed\xff6\x83\xbb\xff\x00U\x99\xff\x00[\x9d\xa9\x00\\\x9e\n\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x07\x00\\\x9e\xf1\x00Q\x95\xff\x18p\xb0\xff\x98\xcd\xf5\xff\xd4\xeb\xfd\xff\xce\xe8\xfb\xff\xcb\xe6\xfb\xff\xcc\xe6\xfb\xff\xce\xe9\xfb\xff\xd1\xe9\xfb\xff\xd3\xea\xfb\xff\xd5\xeb\xfb\xff\xd7\xec\xfb\xff\xda\xec\xfb\xff\xdc\xed\xfb\xff\xde\xef\xfb\xff\xe0\xf0\xfb\xff\xe2\xf1\xfb\xff\xe3\xf1\xfb\xff\xe5\xf1\xfb\xff\xe4\xf2\xfb\xff\xca\xe7\xfb\xff\xc8\xe5\xfb\xff\xc9\xe6\xfb\xff\xcb\xe6\xfb\xff\xcd\xe6\xfb\xff\xcf\xe9\xfb\xff\xd1\xe9\xfb\xff\xd3\xea\xfb\xff\xd5\xeb\xfb\xff\xd7\xec\xfb\xff\xda\xed\xfb\xff\xdc\xed\xfb\xff\xde\xef\xfb\xff\xe0\xf0\xfb\xff\xe2\xf1\xfb\xff\xe6\xf3\xfb\xff\xf2\xf8\xfd\xff\xc9\xe5\xf9\xff1\x81\xba\xff\x00O\x94\xff\x00\\\x9e\xff\x00\\\x9e\'\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e}\x00V\x99\xfc\x1ap\xae\xffc\xad\xe4\xffM\xa8\xef\xff\x83\xc2\xf3\xff\xc6\xe4\xfb\xff\xd1\xe9\xfc\xff\xcc\xe6\xfb\xff\xce\xe9\xfb\xff\xd1\xe9\xfb\xff\xd3\xea\xfb\xff\xd5\xeb\xfb\xff\xd7\xec\xfb\xff\xda\xec\xfb\xff\xdc\xed\xfb\xff\xde\xef\xfb\xff\xe0\xf0\xfb\xff\xe2\xf1\xfb\xff\xe3\xf1\xfb\xff\xe5\xf1\xfb\xff\xe4\xf2\xfb\xff\xca\xe7\xfb\xff\xc8\xe5\xfb\xff\xc9\xe6\xfb\xff\xcb\xe6\xfb\xff\xcd\xe6\xfb\xff\xcf\xe9\xfb\xff\xd1\xe9\xfb\xff\xd3\xea\xfb\xff\xd5\xeb\xfb\xff\xd7\xec\xfb\xff\xda\xed\xfb\xff\xdc\xed\xfb\xff\xde\xef\xfb\xff\xe0\xf0\xfb\xff\xe7\xf4\xfc\xff\xe7\xf3\xfb\xff\xb6\xd8\xf4\xff{\xbc\xee\xff\x7f\xbd\xe9\xff/}\xb7\xff\x00U\x99\xff\x00[\x9d\x9d\x00\\\x9e\x06\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x0b\x00[\x9d\xa2\x00U\x98\xff\'{\xb9\xffs\xbb\xef\xff{\xc0\xf4\xff@\xa1\xed\xff3\x99\xeb\xffW\xac\xee\xff\xa7\xd4\xf7\xff\xd3\xe9\xfc\xff\xd1\xeb\xfb\xff\xd1\xe9\xfb\xff\xd3\xea\xfb\xff\xd5\xeb\xfb\xff\xd7\xec\xfb\xff\xda\xec\xfb\xff\xdc\xed\xfb\xff\xde\xef\xfb\xff\xe0\xf0\xfb\xff\xe2\xf1\xfb\xff\xe3\xf1\xfb\xff\xe5\xf1\xfb\xff\xe4\xf2\xfb\xff\xca\xe7\xfb\xff\xc8\xe5\xfb\xff\xc9\xe6\xfb\xff\xcb\xe6\xfb\xff\xcd\xe6\xfb\xff\xcf\xe9\xfb\xff\xd1\xe9\xfb\xff\xd3\xea\xfb\xff\xd5\xeb\xfb\xff\xd7\xec\xfb\xff\xda\xed\xfb\xff\xdc\xed\xfb\xff\xe0\xf0\xfb\xff\xea\xf5\xfc\xff\xcc\xe5\xf8\xff~\xbe\xee\xffX\xaa\xe9\xffc\xb0\xe9\xff\x92\xca\xf3\xff\x9a\xcd\xf3\xffC\x8d\xc2\xff\x00U\x99\xff\x00Z\x9c\xbd\x00\\\x9e\x1c\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e%\x00Z\x9c\xc9\x00X\x9b\xff6\x8a\xc6\xffs\xbd\xf3\xffw\xbe\xf3\xffv\xbc\xf1\xffC\xa2\xed\xff<\x9e\xec\xff>\x9f\xeb\xffE\xa2\xeb\xff}\xbf\xf1\xff\xc3\xe3\xfa\xff\xd8\xed\xfc\xff\xd4\xeb\xfb\xff\xd5\xeb\xfb\xff\xd7\xec\xfb\xff\xda\xec\xfb\xff\xdc\xed\xfb\xff\xde\xef\xfb\xff\xe0\xf0\xfb\xff\xe2\xf1\xfb\xff\xe3\xf1\xfb\xff\xe5\xf1\xfb\xff\xe4\xf2\xfb\xff\xca\xe7\xfb\xff\xc8\xe5\xfb\xff\xc9\xe6\xfb\xff\xcb\xe6\xfb\xff\xcd\xe6\xfb\xff\xcf\xe9\xfb\xff\xd1\xe9\xfb\xff\xd3\xea\xfb\xff\xd5\xeb\xfb\xff\xd7\xec\xfb\xff\xdb\xed\xfb\xff\xe4\xf1\xfc\xff\xda\xed\xfb\xff\x97\xca\xf2\xffV\xa9\xea\xffS\xa7\xe9\xff_\xad\xea\xffg\xb2\xea\xff\x8d\xc7\xf1\xff\x97\xcc\xf2\xff\xa1\xd1\xf5\xff\\\x9e\xcf\xff\x03[\x9d\xff\x00X\x9b\xdf\x00\\\x9e<\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9eH\x00X\x9a\xe8\x06_\xa0\xffH\x99\xd5\xffs\xbf\xf6\xffq\xbb\xf2\xffu\xbc\xf1\xffv\xbc\xf1\xffC\xa2\xed\xff<\x9e\xec\xffC\xa2\xec\xffH\xa4\xec\xffG\xa4\xeb\xff\\\xad\xed\xff\x9e\xcf\xf5\xff\xd4\xea\xfb\xff\xda\xee\xfc\xff\xd7\xec\xfb\xff\xda\xec\xfb\xff\xdc\xed\xfb\xff\xde\xef\xfb\xff\xe0\xf0\xfb\xff\xe2\xf1\xfb\xff\xe3\xf1\xfb\xff\xe5\xf1\xfb\xff\xe4\xf2\xfb\xff\xca\xe7\xfb\xff\xc8\xe5\xfb\xff\xc9\xe6\xfb\xff\xcb\xe6\xfb\xff\xcd\xe6\xfb\xff\xcf\xe9\xfb\xff\xd1\xe9\xfb\xff\xd3\xea\xfb\xff\xd5\xeb\xfb\xff\xdd\xef\xfc\xff\xe1\xf0\xfc\xff\xac\xd5\xf5\xff\\\xad\xec\xffB\xa0\xe9\xffQ\xa7\xea\xffZ\xab\xea\xff_\xad\xea\xffg\xb2\xea\xff\x8d\xc7\xf1\xff\x95\xca\xf1\xff\x9a\xcc\xf1\xff\xa6\xd4\xf6\xffy\xb2\xdd\xff\x11f\xa5\xff\x00V\x99\xf6\x00\\\x9ed\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9ef\x00V\x99\xfc\x11h\xa9\xffV\xa7\xe2\xffp\xbd\xf6\xffl\xb9\xf1\xffp\xba\xf1\xffu\xbc\xf1\xffv\xbc\xf1\xffC\xa2\xed\xff<\x9e\xec\xffC\xa2\xec\xffI\xa4\xec\xffO\xa8\xec\xffR\xa9\xec\xffS\xa9\xeb\xffx\xbb\xef\xff\xba\xdd\xf7\xff\xdd\xef\xfc\xff\xdc\xed\xfb\xff\xdc\xed\xfb\xff\xde\xef\xfb\xff\xe0\xf0\xfb\xff\xe2\xf1\xfb\xff\xe3\xf1\xfb\xff\xe5\xf1\xfb\xff\xe4\xf2\xfb\xff\xca\xe7\xfb\xff\xc8\xe5\xfb\xff\xc9\xe6\xfb\xff\xcb\xe6\xfb\xff\xcd\xe6\xfb\xff\xcf\xe9\xfb\xff\xd1\xe9\xfb\xff\xd5\xeb\xfb\xff\xdf\xf0\xfc\xff\xc1\xe1\xf9\xffk\xb5\xef\xff8\x9b\xe9\xff@\xa0\xe9\xffL\xa5\xea\xffS\xa8\xea\xffZ\xab\xea\xff_\xad\xea\xffg\xb2\xea\xff\x8d\xc7\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9c\xcd\xf1\xff\xa8\xd5\xf5\xff\x91\xc4\xe8\xff\'u\xb0\xff\x00T\x98\xff\x00\\\x9e\x83\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x04\x00[\x9d\x90\x00W\x98\xff\x1fv\xb6\xff_\xaf\xec\xffk\xba\xf5\xffi\xb8\xf1\xffl\xb9\xf1\xffp\xba\xf1\xffu\xbc\xf1\xffv\xbc\xf1\xffC\xa2\xed\xff<\x9e\xec\xffC\xa2\xec\xffI\xa4\xec\xffO\xa8\xec\xffU\xaa\xec\xff[\xad\xec\xff\\\xad\xeb\xffc\xb1\xeb\xff\x99\xcc\xf2\xff\xd4\xe9\xfa\xff\xe2\xf0\xfc\xff\xdf\xef\xfb\xff\xe0\xf0\xfb\xff\xe2\xf1\xfb\xff\xe3\xf1\xfb\xff\xe5\xf1\xfb\xff\xe4\xf2\xfb\xff\xca\xe7\xfb\xff\xc8\xe5\xfb\xff\xc9\xe6\xfb\xff\xcb\xe6\xfb\xff\xcd\xe6\xfb\xff\xcf\xe9\xfb\xff\xd9\xed\xfc\xff\xd4\xea\xfb\xff\x87\xc4\xf3\xff6\x9b\xea\xff/\x98\xe9\xff>\x9f\xea\xffF\xa3\xea\xffL\xa5\xea\xffS\xa8\xea\xffZ\xab\xea\xff_\xad\xea\xffg\xb2\xea\xff\x8d\xc7\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9c\xcd\xf1\xff\x9f\xce\xf1\xff\xa9\xd4\xf4\xff\xa5\xd1\xf0\xffB\x89\xbd\xff\x00U\x99\xff\x00[\x9d\xab\x00\\\x9e\x10\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x19\x00Z\x9d\xb9\x00W\x99\xff*\x81\xc0\xffc\xb5\xf2\xfff\xb6\xf3\xfff\xb6\xf1\xffi\xb8\xf1\xffl\xb9\xf1\xffp\xba\xf1\xffu\xbc\xf1\xffv\xbc\xf1\xffC\xa2\xed\xff<\x9e\xec\xffC\xa2\xec\xffI\xa4\xec\xffO\xa8\xec\xffU\xaa\xec\xff[\xad\xec\xffa\xb0\xec\xffe\xb2\xec\xfff\xb2\xeb\xff}\xbd\xed\xff\xb8\xda\xf5\xff\xe1\xf0\xfb\xff\xe4\xf2\xfc\xff\xe2\xf1\xfb\xff\xe3\xf1\xfb\xff\xe5\xf1\xfb\xff\xe3\xf2\xfb\xff\xc8\xe6\xfb\xff\xc8\xe5\xfb\xff\xc9\xe6\xfb\xff\xcb\xe6\xfb\xff\xd2\xe8\xfb\xff\xd8\xee\xfc\xff\xa5\xd2\xf7\xffG\xa2\xed\xff!\x90\xe9\xff0\x98\xea\xff9\x9d\xea\xff?\x9f\xea\xffF\xa3\xea\xffL\xa5\xea\xffS\xa8\xea\xffZ\xab\xea\xff_\xad\xea\xffg\xb2\xea\xff\x8d\xc7\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9c\xcd\xf1\xff\x9f\xce\xf1\xff\xa3\xd0\xf1\xff\xa9\xd4\xf2\xff\xb0\xd9\xf5\xffX\x99\xc8\xff\x00W\x9b\xff\x00Y\x9c\xd1\x00\\\x9e,\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e9\x00Y\x9b\xdc\x03\\\x9d\xff9\x8f\xce\xffd\xb6\xf5\xffb\xb4\xf2\xffc\xb4\xf1\xfff\xb6\xf1\xffi\xb8\xf1\xffl\xb9\xf1\xffp\xba\xf1\xffu\xbc\xf1\xffv\xbc\xf1\xffC\xa2\xed\xff<\x9e\xec\xffC\xa2\xec\xffI\xa4\xec\xffO\xa8\xec\xffU\xaa\xec\xff[\xad\xec\xffa\xb0\xec\xfff\xb2\xec\xffm\xb5\xec\xffp\xb7\xeb\xfft\xb7\xeb\xff\x97\xc9\xf0\xff\xcf\xe7\xf8\xff\xe7\xf4\xfc\xff\xe4\xf2\xfb\xff\xe3\xf0\xfb\xff\xe9\xf4\xfb\xff\xd6\xec\xfc\xff\xc5\xe3\xfb\xff\xca\xe6\xfb\xff\xd7\xec\xfc\xff\xbb\xdd\xf9\xff]\xaf\xf0\xff\x1b\x8d\xe9\xff\x1f\x8e\xe9\xff,\x96\xea\xff3\x99\xea\xff9\x9d\xea\xff?\x9f\xea\xffF\xa3\xea\xffL\xa5\xea\xffS\xa8\xea\xffZ\xab\xea\xff_\xad\xea\xffg\xb2\xea\xff\x8d\xc7\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9c\xcd\xf1\xff\x9f\xce\xf1\xff\xa3\xd0\xf1\xff\xa6\xd2\xf1\xff\xaa\xd4\xf2\xff\xb7\xdb\xf6\xffv\xae\xd6\xff\n`\xa0\xff\x00W\x9a\xed\x00\\\x9eQ\x00\\\x9e\x00\x00\\\x9eP\x00Y\x9b\xf5\x0cd\xa6\xffF\x9c\xdc\xffb\xb6\xf6\xff_\xb2\xf1\xffa\xb3\xf1\xffc\xb4\xf1\xfff\xb6\xf1\xffi\xb8\xf1\xffl\xb9\xf1\xffp\xba\xf1\xffu\xbc\xf1\xffv\xbc\xf1\xffC\xa2\xed\xff<\x9e\xec\xffC\xa2\xec\xffI\xa4\xec\xffO\xa8\xec\xffU\xaa\xec\xff[\xad\xec\xffa\xb0\xec\xfff\xb2\xec\xffm\xb5\xec\xffs\xb8\xec\xffy\xba\xec\xffy\xba\xeb\xff\x83\xbf\xec\xff\xb0\xd6\xf2\xff\xe1\xf0\xfa\xff\xf5\xfa\xfe\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xf1\xf8\xfe\xff\xd2\xe9\xfb\xffz\xbd\xf4\xff \x90\xeb\xff\x10\x87\xe9\xff \x8e\xea\xff&\x92\xea\xff,\x96\xea\xff3\x99\xea\xff9\x9d\xea\xff?\x9f\xea\xffF\xa3\xea\xffL\xa5\xea\xffS\xa8\xea\xffZ\xab\xea\xff_\xad\xea\xffg\xb2\xea\xff\x8d\xc7\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9c\xcd\xf1\xff\x9f\xce\xf1\xff\xa3\xd0\xf1\xff\xa6\xd2\xf1\xff\xa9\xd3\xf1\xff\xac\xd4\xf1\xff\xba\xdd\xf6\xff\x93\xc1\xe3\xff\x1eo\xaa\xff\x00X\x9b\xff\x00\\\x9ep\x00Z\x9c\xd6\x0bc\xa4\xffQ\xa7\xe7\xffb\xb8\xf9\xff\\\xb1\xf1\xff_\xb2\xf1\xffa\xb3\xf1\xffc\xb4\xf1\xfff\xb6\xf1\xffi\xb8\xf1\xffl\xb9\xf1\xffp\xba\xf1\xffu\xbc\xf1\xffv\xbc\xf1\xffC\xa2\xed\xff<\x9e\xec\xffC\xa2\xec\xffI\xa4\xec\xffO\xa8\xec\xffU\xaa\xec\xff[\xad\xec\xffa\xb0\xec\xfff\xb2\xec\xffm\xb5\xec\xffs\xb8\xec\xffy\xba\xec\xff~\xbd\xec\xff\x82\xbe\xec\xff\x84\xbf\xeb\xff\xa1\xce\xef\xff\xdf\xee\xf9\xff\xff\xff\xff\xff\xff\xff\xff\xff\xce\xe7\xfb\xffJ\xa5\xee\xff\x08\x83\xe9\xff\x12\x89\xea\xff\x1b\x8d\xea\xff!\x8f\xea\xff&\x92\xea\xff,\x96\xea\xff3\x99\xea\xff9\x9d\xea\xff?\x9f\xea\xffF\xa3\xea\xffL\xa5\xea\xffS\xa8\xea\xffZ\xab\xea\xff_\xad\xea\xffg\xb2\xea\xff\x8d\xc7\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9c\xcd\xf1\xff\x9f\xce\xf1\xff\xa3\xd0\xf1\xff\xa6\xd2\xf1\xff\xa9\xd3\xf1\xff\xac\xd4\xf1\xff\xae\xd5\xf1\xff\xbf\xe0\xf7\xff\xab\xd2\xed\xff\x1en\xaa\xff\x00X\x9b\xeb\x00[\x9d\x90\x02\\\x9e\xff\x1bs\xb4\xffM\xa2\xe2\xffb\xb7\xf6\xff`\xb3\xf2\xffa\xb3\xf1\xffc\xb4\xf1\xfff\xb6\xf1\xffi\xb8\xf1\xffl\xb9\xf1\xffp\xba\xf1\xffu\xbc\xf1\xffv\xbc\xf1\xffC\xa2\xed\xff<\x9e\xec\xffC\xa2\xec\xffI\xa4\xec\xffO\xa8\xec\xffU\xaa\xec\xff[\xad\xec\xffa\xb0\xec\xfff\xb2\xec\xffm\xb5\xec\xffs\xb8\xec\xffy\xba\xec\xff\x7f\xbd\xec\xff\x89\xc1\xed\xff\x92\xc6\xed\xff\x93\xc7\xed\xff\x95\xc7\xec\xff\xc0\xde\xf3\xff\x7f\xbf\xf4\xff\x0f\x87\xe9\xff\r\x87\xe9\xff\x1c\x8e\xea\xff\x1d\x8e\xea\xff\x1d\x8e\xea\xff \x8f\xea\xff&\x92\xea\xff,\x96\xea\xff3\x99\xea\xff9\x9d\xea\xff?\x9f\xea\xffF\xa3\xea\xffL\xa5\xea\xffS\xa8\xea\xffZ\xab\xea\xff_\xad\xea\xffg\xb2\xea\xff\x8d\xc7\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9c\xcd\xf1\xff\x9f\xce\xf1\xff\xa3\xd0\xf1\xff\xa6\xd2\xf1\xff\xa9\xd3\xf1\xff\xad\xd5\xf2\xff\xba\xdd\xf6\xff\x9b\xc7\xe7\xff=\x84\xb9\xff\x05]\x9f\xff\x00[\x9d\xb1\x00\\\x9e\x03\x00\\\x9ey\x00X\x9a\xf3\x05^\x9f\xff6\x8c\xcc\xff`\xb3\xf2\xffe\xb7\xf5\xffc\xb4\xf1\xfff\xb6\xf1\xffi\xb8\xf1\xffl\xb9\xf1\xffp\xba\xf1\xffu\xbc\xf1\xffv\xbc\xf1\xffC\xa2\xed\xff<\x9e\xec\xffC\xa2\xec\xffI\xa4\xec\xffO\xa8\xec\xffU\xaa\xec\xff[\xad\xec\xffa\xb0\xec\xfff\xb2\xec\xffm\xb5\xec\xffr\xb8\xec\xff|\xbb\xec\xff\x87\xc1\xed\xff\x8e\xc4\xed\xff\x92\xc6\xed\xff\x94\xc7\xed\xff\x9d\xcb\xed\xff\xb7\xd9\xf3\xffP\xaa\xf0\xff\x18\x8c\xea\xff\x13\x89\xea\xff\x1b\x8e\xea\xff \x90\xea\xff$\x92\xea\xff$\x91\xea\xff&\x92\xea\xff,\x96\xea\xff3\x99\xea\xff9\x9d\xea\xff?\x9f\xea\xffF\xa3\xea\xffL\xa5\xea\xffS\xa8\xea\xffZ\xab\xea\xff_\xad\xea\xffg\xb2\xea\xff\x8d\xc7\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9c\xcd\xf1\xff\x9f\xce\xf1\xff\xa3\xd0\xf1\xff\xa6\xd2\xf1\xff\xaf\xd7\xf4\xff\xb1\xd8\xf4\xffn\xa8\xd2\xff\x0ec\xa2\xff\x00U\x99\xfd\x00\\\x9e\x91\x00\\\x9e\r\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e)\x00Z\x9c\xb2\x00V\x99\xff\x18o\xb0\xffR\xa4\xe2\xffj\xb9\xf6\xffg\xb7\xf2\xffi\xb8\xf1\xffl\xb9\xf1\xffp\xba\xf1\xffu\xbc\xf1\xffv\xbc\xf1\xffC\xa2\xed\xff<\x9e\xec\xffC\xa2\xec\xffI\xa4\xec\xffO\xa8\xec\xffU\xaa\xec\xff[\xad\xec\xffa\xb0\xec\xffe\xb2\xec\xffm\xb5\xec\xffz\xbb\xed\xff\x84\xc0\xed\xff\x89\xc2\xed\xff\x8d\xc4\xed\xff\x8f\xc4\xec\xff\x9c\xcc\xee\xff\xc5\xe1\xf5\xff\xca\xe4\xf7\xffi\xb7\xf2\xffS\xac\xf0\xff(\x94\xeb\xff\x16\x8b\xea\xff \x90\xea\xff$\x92\xea\xff*\x95\xea\xff,\x96\xea\xff-\x97\xea\xff2\x99\xea\xff9\x9d\xea\xff?\x9f\xea\xffF\xa3\xea\xffL\xa5\xea\xffS\xa8\xea\xffZ\xab\xea\xff_\xad\xea\xffg\xb2\xea\xff\x8d\xc7\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9c\xcd\xf1\xff\x9f\xce\xf1\xff\xa5\xd1\xf2\xff\xb1\xd9\xf6\xff\x94\xc4\xe7\xff2}\xb5\xff\x00U\x99\xff\x00Y\x9c\xc6\x00\\\x9e;\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e[\x00X\x9a\xe1\x04]\x9e\xff3\x87\xc5\xffd\xb4\xef\xffo\xbd\xf5\xffl\xb9\xf1\xffp\xba\xf1\xffu\xbc\xf1\xffv\xbc\xf1\xffC\xa2\xed\xff<\x9e\xec\xffC\xa2\xec\xffI\xa4\xec\xffO\xa8\xec\xffU\xaa\xec\xffZ\xad\xec\xff`\xaf\xec\xffj\xb5\xec\xffx\xba\xed\xff\x80\xbe\xed\xff\x83\xc0\xed\xff\x89\xc2\xed\xff\x8a\xc2\xec\xff\x9b\xcb\xef\xff\xc4\xe0\xf6\xff\xd0\xe7\xf7\xff\xc8\xe3\xf7\xffe\xb5\xf2\xff[\xb0\xf1\xff^\xb1\xf1\xff2\x9a\xec\xff\x1b\x8d\xea\xff#\x92\xea\xff)\x95\xea\xff/\x98\xea\xff4\x9a\xea\xff6\x9b\xea\xff9\x9c\xea\xff?\x9f\xea\xffF\xa3\xea\xffL\xa5\xea\xffS\xa8\xea\xffZ\xab\xea\xff_\xad\xea\xffg\xb2\xea\xff\x8d\xc7\xf1\xff\x95\xca\xf1\xff\x99\xcc\xf1\xff\x9c\xcd\xf1\xff\xa6\xd3\xf5\xff\xa4\xd1\xf2\xff^\x9e\xcc\xff\x0b`\xa1\xff\x00V\x99\xef\x00\\\x9er\x00\\\x9e\x04\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x17\x00[\x9d\xa0\x00V\x98\xff\x12i\xaa\xffM\x9e\xd9\xffr\xbe\xf5\xffs\xbc\xf3\xffu\xbc\xf1\xffv\xbc\xf1\xffC\xa2\xed\xff<\x9e\xec\xffC\xa2\xec\xffI\xa4\xec\xffO\xa8\xec\xffT\xa9\xec\xff\\\xad\xec\xffi\xb4\xed\xffs\xba\xed\xffy\xbb\xed\xff\x7f\xbe\xed\xff\x83\xc0\xed\xff\x85\xc0\xec\xff\x9e\xcd\xf0\xff\xc3\xe1\xf7\xff\xcb\xe4\xf7\xff\xcd\xe6\xf7\xff\xc8\xe3\xf7\xffe\xb5\xf2\xffY\xaf\xf1\xffa\xb3\xf1\xfff\xb5\xf1\xffA\xa2\xed\xff \x90\xea\xff(\x94\xea\xff.\x98\xea\xff4\x9a\xea\xff;\x9d\xea\xff?\x9f\xea\xffA\xa0\xea\xffE\xa2\xea\xffL\xa5\xea\xffS\xa8\xea\xffZ\xab\xea\xff_\xad\xea\xffg\xb2\xea\xff\x8d\xc7\xf1\xff\x95\xca\xf1\xff\x9c\xce\xf3\xff\xa5\xd4\xf6\xff~\xb6\xdf\xff%t\xaf\xff\x00U\x99\xff\x00Z\x9c\xb6\x00\\\x9e&\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9eI\x00X\x9b\xd3\x00X\x9b\xff)}\xbb\xffg\xb2\xea\xff|\xc2\xf6\xffv\xbc\xf1\xffC\xa2\xed\xff<\x9e\xec\xffC\xa2\xec\xffH\xa4\xec\xffO\xa7\xec\xff[\xae\xec\xffh\xb3\xed\xffn\xb7\xed\xffs\xba\xed\xffy\xbb\xed\xff~\xbd\xed\xff\x80\xbf\xec\xff\xa1\xcf\xf1\xff\xc3\xe1\xf7\xff\xc6\xe3\xf7\xff\xc9\xe3\xf7\xff\xcd\xe6\xf7\xff\xc8\xe3\xf7\xffe\xb5\xf2\xffY\xaf\xf1\xff_\xb2\xf1\xffe\xb5\xf1\xffm\xb9\xf1\xffQ\xaa\xee\xff)\x94\xea\xff,\x97\xea\xff4\x9a\xea\xff:\x9d\xea\xffA\xa0\xea\xffG\xa3\xea\xffJ\xa5\xea\xffM\xa5\xea\xffS\xa8\xea\xffZ\xab\xea\xff_\xad\xea\xffg\xb2\xea\xff\x8d\xc7\xf1\xff\x9d\xd0\xf6\xff\x93\xc7\xed\xffF\x8d\xc2\xff\x02Z\x9d\xff\x00W\x9a\xe4\x00\\\x9e`\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\n\x00\\\x9e\x81\x00V\x99\xf6\x0cc\xa4\xffM\x9a\xd3\xffz\xbf\xf3\xffD\xa3\xee\xff;\x9e\xec\xffB\xa2\xec\xffM\xa6\xec\xff[\xae\xed\xffd\xb2\xed\xffh\xb4\xed\xffm\xb6\xed\xffs\xba\xed\xffw\xba\xed\xff~\xbd\xed\xff\xa5\xd2\xf3\xff\xc1\xe0\xf7\xff\xc2\xe0\xf7\xff\xc5\xe2\xf7\xff\xc9\xe3\xf7\xff\xcd\xe6\xf7\xff\xc8\xe3\xf7\xffe\xb5\xf2\xffY\xaf\xf1\xff_\xb2\xf1\xffd\xb4\xf1\xffi\xb7\xf1\xffs\xbb\xf1\xffa\xb2\xef\xff3\x9a\xeb\xff0\x98\xea\xff:\x9d\xea\xffA\xa0\xea\xffG\xa3\xea\xffM\xa6\xea\xffR\xa8\xea\xffV\xa9\xea\xffZ\xab\xea\xff_\xad\xea\xffg\xb2\xeb\xff\x94\xcc\xf5\xffn\xad\xda\xff\x18k\xa9\xff\x00T\x98\xff\x00[\x9d\x9b\x00\\\x9e\x18\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e/\x00Y\x9c\xbd\x00W\x99\xff%z\xb7\xffB\xa0\xea\xff;\x9e\xec\xffK\xa6\xed\xffY\xad\xed\xff_\xaf\xed\xffc\xb2\xed\xffh\xb4\xed\xffm\xb6\xed\xffp\xb8\xec\xff}\xbd\xee\xff\xa8\xd4\xf4\xff\xbe\xdf\xf8\xff\xbd\xde\xf7\xff\xc2\xe0\xf7\xff\xc5\xe2\xf7\xff\xc9\xe3\xf7\xff\xcd\xe6\xf7\xff\xc8\xe3\xf7\xffe\xb5\xf2\xffY\xaf\xf1\xff_\xb2\xf1\xffd\xb4\xf1\xffi\xb7\xf1\xffn\xb9\xf1\xffx\xbe\xf1\xffq\xb9\xf0\xff@\xa0\xeb\xff5\x9b\xea\xffA\xa0\xea\xffG\xa3\xea\xffM\xa6\xea\xffS\xa9\xea\xffZ\xab\xea\xff]\xae\xea\xff]\xac\xea\xffk\xb3\xeb\xff:\x87\xbf\xff\x00X\x9a\xff\x00X\x9b\xd1\x00\\\x9eD\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x03\x00[\x9d\xb6\x00[\x9e\xffi\xb2\xe8\xffq\xbc\xf4\xffT\xaa\xed\xffV\xaa\xed\xff^\xaf\xed\xffc\xb2\xed\xffh\xb4\xed\xffj\xb5\xec\xffz\xbd\xee\xff\xa9\xd5\xf5\xff\xb9\xdd\xf8\xff\xba\xdd\xf7\xff\xbd\xde\xf7\xff\xc2\xe0\xf7\xff\xc5\xe2\xf7\xff\xc9\xe3\xf7\xff\xcd\xe6\xf7\xff\xc8\xe3\xf7\xffe\xb5\xf2\xffY\xaf\xf1\xff_\xb2\xf1\xffd\xb4\xf1\xffi\xb7\xf1\xffn\xb9\xf1\xfft\xbc\xf1\xff~\xbf\xf1\xff|\xbe\xf0\xffM\xa6\xeb\xff;\x9d\xea\xffG\xa3\xea\xffM\xa6\xea\xffS\xa9\xea\xffW\xaa\xea\xff]\xae\xea\xff\x84\xc1\xee\xff\x9c\xc9\xea\xff\ta\xa1\xff\x00Y\x9b\xcd\x00\\\x9e\x0e\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00[\x9d\x8c\x04_\xa1\xff~\xbc\xea\xff\x9c\xd2\xfa\xff\x8a\xc7\xf5\xffg\xb4\xef\xffY\xad\xec\xffa\xb1\xed\xffd\xb2\xec\xff|\xbe\xef\xff\xa9\xd4\xf6\xff\xb3\xda\xf7\xff\xb6\xdb\xf7\xff\xba\xdd\xf7\xff\xbd\xde\xf7\xff\xc2\xe0\xf7\xff\xc5\xe2\xf7\xff\xc9\xe3\xf7\xff\xcd\xe6\xf7\xff\xc8\xe3\xf7\xffe\xb5\xf2\xffY\xaf\xf1\xff_\xb2\xf1\xffd\xb4\xf1\xffi\xb7\xf1\xffn\xb9\xf1\xfft\xbc\xf1\xff{\xbe\xf1\xff\x83\xc2\xf1\xff\x88\xc4\xf1\xff^\xae\xed\xffB\xa0\xea\xffK\xa5\xea\xffN\xa6\xea\xffd\xb0\xeb\xff\x97\xca\xef\xff\xb7\xda\xf3\xff\xa9\xd0\xeb\xff\x0ef\xa4\xff\x00Z\x9c\xa7\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00[\x9d\x92\x04_\xa1\xff\x82\xbf\xee\xff\x98\xd0\xfb\xff\x99\xce\xf7\xff\x9a\xce\xf7\xff\x81\xc1\xf2\xffd\xb2\xed\xff~\xbf\xf0\xff\xa8\xd5\xf7\xff\xae\xd8\xf7\xff\xb1\xd9\xf7\xff\xb6\xdb\xf7\xff\xba\xdd\xf7\xff\xbd\xde\xf7\xff\xc2\xe0\xf7\xff\xc5\xe2\xf7\xff\xc9\xe3\xf7\xff\xcd\xe6\xf7\xff\xc8\xe3\xf7\xffe\xb5\xf2\xffY\xaf\xf1\xff_\xb2\xf1\xffd\xb4\xf1\xffi\xb7\xf1\xffn\xb9\xf1\xfft\xbc\xf1\xff{\xbe\xf1\xff\x81\xc1\xf1\xff\x89\xc5\xf1\xff\x91\xc9\xf1\xffo\xb7\xed\xffN\xa6\xea\xffu\xb9\xed\xff\xa3\xd0\xf0\xff\xaf\xd6\xf1\xff\xb5\xda\xf4\xff\xaf\xd5\xef\xff\x0ef\xa4\xff\x00Z\x9c\xaa\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9em\x01[\x9d\xffT\x9c\xd1\xff\x98\xd0\xfb\xff\x9b\xd1\xfa\xff\x99\xce\xf7\xff\x9f\xd2\xf7\xff\x9a\xcf\xf6\xff\xa4\xd4\xf7\xff\xa9\xd6\xf7\xff\xac\xd7\xf7\xff\xb1\xd9\xf7\xff\xb6\xdb\xf7\xff\xba\xdd\xf7\xff\xbd\xde\xf7\xff\xc2\xe0\xf7\xff\xc5\xe2\xf7\xff\xc9\xe3\xf7\xff\xcd\xe6\xf7\xff\xc8\xe3\xf7\xffe\xb5\xf2\xffY\xaf\xf1\xff_\xb2\xf1\xffd\xb4\xf1\xffi\xb7\xf1\xffn\xb9\xf1\xfft\xbc\xf1\xff{\xbe\xf1\xff\x81\xc1\xf1\xff\x88\xc4\xf1\xff\x8e\xc7\xf1\xff\x96\xcb\xf1\xff\x93\xc8\xf0\xff\xa3\xd0\xf1\xff\xa7\xd3\xf1\xff\xb3\xd9\xf5\xff\xae\xd4\xf0\xffZ\x98\xc7\xff\x03\\\x9d\xff\x00[\x9d{\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x16\x00[\x9d\xcd\x00W\x99\xff*z\xb6\xff\x85\xc0\xec\xff\xa3\xd6\xfd\xff\x9d\xd1\xf8\xff\xa0\xd3\xf7\xff\xa4\xd4\xf7\xff\xa8\xd5\xf7\xff\xac\xd7\xf7\xff\xb1\xd9\xf7\xff\xb6\xdb\xf7\xff\xba\xdd\xf7\xff\xbd\xde\xf7\xff\xc2\xe0\xf7\xff\xc5\xe2\xf7\xff\xc9\xe3\xf7\xff\xcd\xe6\xf7\xff\xc8\xe3\xf7\xffe\xb5\xf2\xffY\xaf\xf1\xff_\xb2\xf1\xffd\xb4\xf1\xffi\xb7\xf1\xffn\xb9\xf1\xfft\xbc\xf1\xff{\xbe\xf1\xff\x81\xc1\xf1\xff\x88\xc4\xf1\xff\x8e\xc7\xf1\xff\x94\xca\xf1\xff\x9c\xcd\xf1\xff\xa3\xd1\xf2\xff\xb1\xd9\xf6\xff\x87\xba\xdf\xff!p\xac\xff\x00T\x99\xff\x00[\x9e\xb9\x00\\\x9e\x13\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x0b\x00\\\x9e\x81\x00V\x99\xf5\na\xa2\xff\\\x9f\xd2\xff\xa0\xd3\xf9\xff\xa6\xd7\xfb\xff\xa4\xd4\xf7\xff\xa8\xd5\xf7\xff\xac\xd7\xf7\xff\xb1\xd9\xf7\xff\xb6\xdb\xf7\xff\xba\xdd\xf7\xff\xbd\xde\xf7\xff\xc2\xe0\xf7\xff\xc5\xe2\xf7\xff\xc9\xe3\xf7\xff\xcd\xe6\xf7\xff\xc8\xe3\xf7\xffe\xb5\xf2\xffY\xaf\xf1\xff_\xb2\xf1\xffd\xb4\xf1\xffi\xb7\xf1\xffn\xb9\xf1\xfft\xbc\xf1\xff{\xbe\xf1\xff\x81\xc1\xf1\xff\x88\xc4\xf1\xff\x8e\xc7\xf1\xff\x94\xca\xf1\xff\xa3\xd2\xf5\xff\x9e\xcd\xf0\xffQ\x95\xc6\xff\x03[\x9d\xff\x00W\x9a\xe9\x00\\\x9ei\x00\\\x9e\x01\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e.\x00Z\x9c\xb6\x00U\x99\xff(x\xb3\xff\x81\xbc\xe6\xff\xae\xdb\xfc\xff\xab\xd7\xf9\xff\xac\xd7\xf7\xff\xb1\xd9\xf7\xff\xb6\xdb\xf7\xff\xba\xdd\xf7\xff\xbd\xde\xf7\xff\xc2\xe0\xf7\xff\xc5\xe2\xf7\xff\xc9\xe3\xf7\xff\xcd\xe6\xf7\xff\xc8\xe3\xf7\xffe\xb5\xf2\xffY\xaf\xf1\xff_\xb2\xf1\xffd\xb4\xf1\xffi\xb7\xf1\xffn\xb9\xf1\xfft\xbc\xf1\xff{\xbe\xf1\xff\x81\xc1\xf1\xff\x88\xc4\xf1\xff\x92\xca\xf3\xff\x9c\xd0\xf5\xffr\xae\xda\xff\x1dn\xab\xff\x00U\x99\xff\x00[\x9d\x9f\x00\\\x9e\x1d\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9ed\x00V\x99\xe9\x03[\x9e\xffL\x92\xc6\xff\xa1\xd0\xf3\xff\xb6\xde\xfc\xff\xb2\xda\xf7\xff\xb6\xdb\xf7\xff\xba\xdd\xf7\xff\xbd\xde\xf7\xff\xc2\xe0\xf7\xff\xc5\xe2\xf7\xff\xc9\xe3\xf7\xff\xcd\xe6\xf7\xff\xc8\xe3\xf7\xffe\xb5\xf2\xffY\xaf\xf1\xff_\xb2\xf1\xffd\xb4\xf1\xffi\xb7\xf1\xffn\xb9\xf1\xfft\xbc\xf1\xff{\xbe\xf1\xff\x82\xc2\xf2\xff\x90\xca\xf6\xff\x82\xbe\xe9\xff8\x84\xbc\xff\x00X\x9b\xff\x00W\x9b\xd9\x00\\\x9eO\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x1c\x00[\x9d\x9f\x00T\x98\xff\x18j\xa8\xfft\xaf\xd9\xff\xb8\xde\xfa\xff\xbb\xdf\xfa\xff\xba\xdd\xf7\xff\xbd\xde\xf7\xff\xc2\xe0\xf7\xff\xc5\xe2\xf7\xff\xc9\xe3\xf7\xff\xcd\xe6\xf7\xff\xc8\xe3\xf7\xffe\xb5\xf2\xffY\xaf\xf1\xff_\xb2\xf1\xffd\xb4\xf1\xffi\xb7\xf1\xffn\xb9\xf1\xfft\xbc\xf1\xff\x80\xc2\xf4\xff\x85\xc4\xf3\xffR\x9a\xcf\xff\rc\xa3\xff\x00U\x99\xf9\x00[\x9e\x88\x00\\\x9e\x0f\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9eG\x00X\x9b\xd0\x00V\x9a\xff=\x85\xbb\xff\xa3\xce\xee\xff\xc6\xe5\xfd\xff\xbf\xdf\xf8\xff\xc2\xe0\xf7\xff\xc5\xe2\xf7\xff\xc9\xe3\xf7\xff\xcd\xe6\xf7\xff\xc8\xe3\xf7\xffe\xb5\xf2\xffY\xaf\xf1\xff_\xb2\xf1\xffd\xb4\xf1\xffi\xb7\xf1\xffo\xba\xf2\xff|\xc2\xf6\xffj\xb0\xe4\xff%w\xb4\xff\x00U\x99\xff\x00Z\x9c\xbc\x00\\\x9e3\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x08\x00\\\x9e{\x00T\x99\xf5\rb\xa2\xffk\xa5\xd0\xff\xbe\xdf\xf7\xff\xcb\xe6\xfb\xff\xc5\xe2\xf7\xff\xc9\xe3\xf7\xff\xcd\xe6\xf7\xff\xc8\xe3\xf7\xffe\xb5\xf2\xffY\xaf\xf1\xff_\xb2\xf1\xffd\xb4\xf1\xffn\xbc\xf5\xffm\xb8\xf0\xff=\x8d\xc8\xff\x06^\x9f\xff\x00W\x99\xe9\x00\\\x9ed\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e0\x00Y\x9c\xbc\x00T\x98\xff*v\xb0\xff\x95\xc2\xe2\xff\xd0\xea\xfc\xff\xcd\xe6\xf9\xff\xcd\xe6\xf7\xff\xc8\xe3\xf7\xffe\xb5\xf2\xffY\xaf\xf1\xffa\xb4\xf3\xffj\xb9\xf5\xffN\x9f\xda\xff\x15k\xab\xff\x00V\x98\xff\x00Z\x9d\xa7\x00\\\x9e \x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9ec\x00V\x9a\xe4\x01Y\x9c\xffS\x93\xc2\xff\xbf\xdd\xf2\xff\xd9\xee\xfc\xff\xc9\xe3\xf7\xffe\xb5\xf2\xff^\xb4\xf6\xffZ\xad\xeb\xff(}\xbc\xff\x00Y\x9b\xff\x00X\x9b\xd7\x00\\\x9eO\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x18\x00[\x9d\x9a\x00S\x98\xff\x1cl\xa8\xff\x8d\xb9\xda\xff\xd1\xe9\xfb\xffk\xba\xf5\xff;\x92\xd3\xff\x0cd\xa5\xff\x00V\x99\xf7\x00[\x9d\x85\x00\\\x9e\r\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9eA\x00X\x9b\xd2\x00V\x9a\xff?\x87\xbb\xff&z\xb8\xff\x00W\x99\xff\x00Y\x9c\xc3\x00\\\x9e1\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x0b\x00\\\x9e\x81\x00V\x9a\xf0\x00X\x9a\xf2\x00\\\x9eu\x00\\\x9e\x03\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x0f\x00[\x9et\x00\\\x9ex\x00\\\x9e\x0b\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff\x00', gtk.gdk.COLORSPACE_RGB, True, 8, 64, 64, 256) + window_icon = gtk.gdk.pixbuf_new_from_data('\x00\\\x9e\x00\x00\\\x9e\x00\x00^\xa0\x00\x00V\x99\x00\x00L\x91g\x00N\x93q\x00X\x9c\x00\x00^\x9f\x00\x00]\x9f\x00\x00Y\x9c\x00\x00P\x94o\x00M\x92i\x00V\x99\x00\x00^\xa0\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00^\xa0\x00\x00T\x97\x00\x00F\x8c_1\x81\xba\xff+|\xb6\xff\x00F\x8e?\x00\\\x9e\x00\x00\\\x9e\x00\x00J\x8e;$y\xb6\xff-\x7f\xbc\xff\x00E\x8cb\x00R\x97\x00\x00^\xa0\x00\x00\\\x9e\x00\x00[\x9d\x00\x00I\x8c*\x05X\x9b\xc0P\x9b\xd5\xff\xa7\xdd\xff\xff\xbb\xe5\xff\xff@\x86\xbb\xff\x00>\x89D\x00D\x89B\'{\xbb\xff\x89\xcf\xff\xff\xa2\xdb\xff\xffg\xa6\xd5\xff\x07Y\x9b\xc3\x00C\x8c,\x00[\x9d\x00\x05\\\x9e\x971\x84\xc5\xffk\xbb\xf6\xff\x8e\xd0\xff\xff\x86\xc3\xf0\xff\xa2\xd2\xf5\xff\xc4\xe7\xff\xffP\x90\xc0\xff\x15u\xbf\xfff\xbf\xff\xffx\xc1\xf6\xff\x80\xc0\xf0\xff\xb0\xdf\xff\xff\xa9\xd7\xf6\xff\\\x97\xc5\xff\x0b]\x9e\x98\x08[\x9e\xdcX\xb0\xf0\xff\x84\xd0\xff\xffx\xbc\xf0\xff\x83\xc2\xf0\xff\x88\xc3\xee\xff\xb1\xd7\xf3\xff\xf9\xff\xff\xff\xca\xec\xff\xffm\xba\xf3\xffX\xae\xee\xff{\xbe\xf0\xff\x91\xc7\xf0\xff\xd2\xf2\xff\xff\xa6\xd4\xf0\xff\x11]\x9e\xde\x00T\x96\x00\x00N\x91\x9eD\x98\xd5\xff\x84\xc9\xfc\xff\x85\xc3\xf1\xff\xb7\xdb\xf6\xff\xe9\xf4\xfc\xff\xe9\xf5\xfd\xff\xdb\xee\xfd\xff\xdf\xef\xfc\xff\xa8\xd5\xf6\xff|\xbf\xf1\xff\xa3\xd6\xfc\xffl\xaa\xd6\xff\x00J\x91\xa1\x00Q\x96\x00\x00^\xa0\x00\x00T\x97\x00\x008\x7f\x9eC\x94\xd1\xff\xde\xf6\xff\xff\xf5\xfc\xff\xff\xe0\xef\xfb\xff\xe0\xf0\xfb\xff\xc8\xe5\xfb\xff\xcf\xe7\xfb\xff\xff\xff\xff\xff\xfe\xff\xff\xffV\x9d\xd2\xff\x002\x80\xa2\x00Q\x96\x00\x00_\xa0\x00\x00W\x99\x00\x00I\x8cq9\x89\xc3\xf1Y\xb0\xf2\xffR\xaa\xef\xff\xbc\xde\xf7\xff\xf9\xfc\xfe\xff\xe3\xf2\xfb\xff\xd3\xea\xfc\xff\xf5\xfb\xff\xff\xb7\xdb\xf7\xffd\xb1\xed\xff\x86\xc3\xf2\xffR\x93\xc4\xf3\x00D\x8du\x00T\x99\x00\x06Z\x9d\xb3I\xa0\xe0\xff\x8a\xd2\xff\xffe\xb5\xf2\xff/\x97\xe8\xffK\xa4\xe9\xff\x9c\xcd\xf0\xff\xf6\xf9\xfc\xff\xd6\xec\xfc\xffX\xab\xf0\xff\x15\x8a\xe6\xff9\x9b\xe6\xff\x8c\xc6\xf1\xff\xd1\xf0\xff\xff\x8b\xbe\xe1\xff\x0e\\\x9d\xb6\x07]\x9f\xc1D\x98\xd9\xff\x85\xcd\xff\xffm\xbc\xf9\xff;\x9d\xe9\xff^\xae\xec\xffl\xb3\xe8\xff\xb7\xd9\xf2\xffC\xa2\xef\xff\x00s\xe5\xff3\x99\xea\xffL\xa3\xe7\xff\x96\xce\xf9\xff\xc7\xeb\xff\xff\x81\xb3\xd9\xff\x10_\x9f\xc4\x00X\x9a\x00\x00H\x8bU\x1eq\xad\xeeR\xa8\xe8\xffA\xa4\xf1\xff`\xae\xea\xff\xa9\xd3\xf2\xff\xc8\xe4\xf8\xffh\xb7\xf2\xff@\xa2\xed\xff,\x95\xe8\xffQ\xaa\xef\xff|\xba\xe9\xff*u\xae\xf1\x00A\x8bX\x00V\x9a\x00\x00\\\x9e\x00\x00]\x9f\x00\x00>\x84\x0c"v\xb3\xff\x9b\xdb\xff\xff\x97\xcf\xf8\xff\xce\xe6\xf8\xff\xc5\xe1\xf7\xffe\xb5\xf1\xfft\xbc\xf0\xffu\xbe\xf5\xff\xa9\xde\xff\xff0{\xb0\xff\x00:\x85\x0f\x00]\x9f\x00\x00]\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00Y\x9c\x00\x02S\x97zH\x89\xbf\xff\xb8\xe3\xfd\xff\xe8\xfb\xff\xff\xc2\xdf\xf7\xff`\xb3\xf1\xff\x82\xcb\xff\xff\xa1\xd3\xf7\xffJ\x88\xb8\xff\x00S\x96r\x00Z\x9d\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00]\x9f\x00\x00[\x9d\x00\x00C\x8b*\x08W\x9b\xc5\x8c\xb9\xda\xff\xea\xfd\xff\xff\x80\xcb\xff\xffG\x97\xd4\xff\x03W\x99\xbc\x00E\x8d"\x00[\x9e\x00\x00]\x9f\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00_\xa0\x00\x00Q\x96\x00\x00C\x8di>\x88\xbd\xff,\x7f\xbb\xff\x00G\x8c`\x00T\x98\x00\x00^\xa0\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00_\xa0\x00\x00R\x98\x00\x00I\x92r\x00P\x92n\x00V\x99\x00\x00^\xa0\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00\x00\\\x9e\x00', gtk.gdk.COLORSPACE_RGB, True, 8, 16, 16, 64) + +GUI_AVAILABLE = os.environ.get("DISPLAY", '') + +if GUI_AVAILABLE: + def download(): + import pygtk + pygtk.require("2.0") + import gtk + import gobject + import pango + import webbrowser + + load_serialized_images() + + global FatalVisibleError + def FatalVisibleError(s): + error = gtk.MessageDialog(parent = None, + flags = gtk.DIALOG_MODAL, + type = gtk.MESSAGE_ERROR, + buttons = gtk.BUTTONS_OK, + message_format = s) + error.set_title("Error") + error.run() + gtk.main_quit() + sys.exit(-1) + + def gtk_flush_events(): + while gtk.events_pending(): + gtk.main_iteration() + + class DownloadDialog(gtk.Dialog): + def handle_delete_event(self, wid, ev, data=None): + self.handle_cancel(wid) + + def handle_cancel(self, button): + if self.watch: + gobject.source_remove(self.watch) + if self.download: + self.download.cancel() + gtk.main_quit() + self.user_cancelled = True + + def handle_ok(self, button): + # begin download + self.ok.hide() + self.download = DownloadState() + self.one_chunk = self.download.copy_data() + self.watch = gobject.io_add_watch(self.download.file, + gobject.IO_IN | + gobject.IO_PRI | + gobject.IO_ERR | + gobject.IO_HUP, + self.handle_data_waiting) + self.label.hide() + self.progress.show() + + def update_progress(self, text, fraction): + self.progress.set_text(text % int(fraction*100)) + self.progress.set_fraction(fraction) + gtk_flush_events() + + def handle_data_waiting(self, fd, condition): + if condition == gobject.IO_HUP: + FatalVisibleError("Connection to server unexpectedly closed.") + elif condition == gobject.IO_ERR: + FatalVisibleError("Unexpected error occurred with download.") + try: + while self.one_chunk.next(): + self.update_progress(DOWNLOADING, float(self.download.progress)/self.download.size) + except StopIteration: + self.update_progress(DOWNLOADING, 1.0) + self.unpack_dropbox() + return False + else: + self.update_progress(DOWNLOADING, float(self.download.progress)/self.download.size) + return True + + def unpack_dropbox(self): + one_member = self.download.unpack() + try: + while True: + name, i, total = one_member.next() + self.update_progress(UNPACKING, float(i)/total) + except StopIteration: + self.update_progress(UNPACKING, 1.0) + gtk.main_quit() + + def mouse_down(self, widget, event): + if self.hovering: + self.clicked_link = True + + def mouse_up(self, widget, event): + if self.clicked_link: + webbrowser.open(LINK) + self.clicked_link = False + + def label_motion(self, widget, event): + offx, offy = self.label.get_layout_offsets() + layout = self.label.get_layout() + index = layout.xy_to_index(int((offx+event.x)*pango.SCALE), + int((offy+event.y)*pango.SCALE))[0] + link_index = layout.get_text().find(LINK) + if index >= link_index and index < link_index+len(LINK): + self.hovering = True + self.label_box.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2)) + else: + self.hovering = False + self.label_box.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.ARROW)) + + + def __init__(self): + super(DownloadDialog, self).__init__(parent = None, + title = "Dropbox Installation") + + self.download = None + self.watch = None + self.hovering = False + self.clicked_link = False + self.user_cancelled = False + + self.ok = ok = gtk.Button(stock=gtk.STOCK_OK) + ok.connect('clicked', self.handle_ok) + self.action_area.add(ok) + ok.show() + + cancel = gtk.Button(stock=gtk.STOCK_CANCEL) + cancel.connect('clicked', self.handle_cancel) + self.action_area.add(cancel) + cancel.show() + + self.connect('delete_event', self.handle_delete_event) + + self.box_logo = gtk.image_new_from_pixbuf(box_logo_pixbuf) + self.box_logo.show() + + self.set_icon(window_icon) + + self.progress = gtk.ProgressBar() + self.progress.set_property('width-request', 300) + + self.label = gtk.Label() + self.label.set_markup('%s %s\n\n%s' % (INFO, LINK, WARNING)) + self.label.set_line_wrap(True) + self.label.set_property('width-request', 300) + self.label.show() + + self.label_box = gtk.EventBox() + self.label_box.add(self.label) + self.label_box.connect("button-release-event", self.mouse_up) + self.label_box.connect("button-press-event", self.mouse_down) + self.label_box.connect("motion-notify-event", self.label_motion) + self.label_box.show() + def on_realize(widget): + self.label_box.add_events(gtk.gdk.POINTER_MOTION_MASK) + self.label_box.connect("realize", on_realize) + + self.hbox = gtk.HBox(spacing=10) + self.hbox.set_property('border-width',10) + self.hbox.pack_start(self.box_logo, False, False) + self.hbox.pack_start(self.label_box, False, False) + self.hbox.pack_start(self.progress, False, False) + self.hbox.show() + + self.vbox.add(self.hbox) + self.set_resizable(False) + + dialog = DownloadDialog() + dialog.show() + gtk.main() + if dialog.user_cancelled: + raise Exception("user cancelled download!!!") +else: + def download(): + global FatalVisibleError + def FatalVisibleError(s): + console_print(u"\nError: %s" % s, f=sys.stderr) + sys.exit(-1) + + + ESC = "\x1b" + save = ESC+"7" + unsave = ESC+"8" + clear = ESC+"[2J" + erase_to_start = ESC+"[1K" + write = sys.stdout.write + flush = sys.stdout.flush + + last_progress = [None, None] + def setprogress(text, frac): + if last_progress == [text, frac]: + return + if sys.stdout.isatty(): + write(erase_to_start) + write(unsave) + console_print(text % int(100*frac), linebreak=not sys.stdout.isatty()) + if sys.stdout.isatty(): + flush() + last_progress[0], last_progress[1] = text, frac + + console_print() + if sys.stdout.isatty(): + write(save) + flush() + console_print(u"%s %s\n" % (INFO, LINK)) + + if not yes_no_question(WARNING): + return + + download = DownloadState() + one_chunk = download.copy_data() + + try: + while True: + one_chunk.next() + setprogress(DOWNLOADING, float(download.progress)/download.size) + except StopIteration: + setprogress(DOWNLOADING, 1.0) + console_print() + write(save) + + one_member = download.unpack() + + try: + while True: + name, i, total = one_member.next() + setprogress(UNPACKING, float(i)/total) + except StopIteration: + setprogress(UNPACKING, 1.0) + + console_print() + +class DropboxCommand(object): + class CouldntConnectError(Exception): pass + class BadConnectionError(Exception): pass + class EOFError(Exception): pass + class CommandError(Exception): pass + + def __init__(self): + self.s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + self.s.settimeout(3) + try: + self.s.connect(os.path.expanduser(u'~/.dropbox/command_socket')) + except socket.error, e: + raise DropboxCommand.CouldntConnectError() + self.f = self.s.makefile("r+", 4096) + + def close(self): + self.f.close() + self.s.close() + + def __readline(self): + try: + toret = self.f.readline().decode('utf8').rstrip(u"\n") + except socket.error, e: + raise DropboxCommand.BadConnectionError() + if toret == '': + raise DropboxCommand.EOFError() + else: + return toret + + # atttribute doesn't exist, i know what you want + def send_command(self, name, args): + self.f.write(name.encode('utf8')) + self.f.write(u"\n".encode('utf8')) + self.f.writelines((u"\t".join([k] + (list(v) + if hasattr(v, '__iter__') else + [v])) + u"\n").encode('utf8') + for k,v in args.iteritems()) + self.f.write(u"done\n".encode('utf8')) + + self.f.flush() + + ok = self.__readline() == u"ok" + if ok: + toret = {} + for i in range(21): + if i == 20: + raise Exception(u"close this connection!") + + line = self.__readline() + if line == u"done": + break + + argval = line.split(u"\t") + toret[argval[0]] = argval[1:] + + return toret + else: + problems = [] + for i in range(21): + if i == 20: + raise Exception(u"close this connection!") + + line = self.__readline() + if line == u"done": + break + + problems.append(line) + + raise DropboxCommand.CommandError(u"\n".join(problems)) + + # this is the hotness, auto marshalling + def __getattr__(self, name): + try: + return super(DropboxCommand, self).__getattr__(name) + except: + def __spec_command(**kw): + return self.send_command(unicode(name), kw) + self.__setattr__(name, __spec_command) + return __spec_command + +commands = {} + +def command(meth): + global commands + assert meth.__doc__, "All commands need properly formatted docstrings (even %r!!)" % meth + if hasattr(meth, 'im_func'): # bound method, if we ever have one + meth = meth.im_func + commands[meth.func_name] = meth + return meth + +def requires_dropbox_running(meth): + def newmeth(*n, **kw): + if is_dropbox_running(): + return meth(*n, **kw) + else: + console_print(u"Dropbox isn't running!") + newmeth.func_name = meth.func_name + newmeth.__doc__ = meth.__doc__ + return newmeth + +def start_dropbox(): + db_path = os.path.expanduser(u"~/.dropbox-dist/dropboxd").encode(sys.getfilesystemencoding()) + if os.access(db_path, os.X_OK): + f = open("/dev/null", "w") + # we don't reap the child because we're gonna die anyway, let init do it + a = subprocess.Popen([db_path], preexec_fn=os.setsid, cwd=os.path.expanduser("~"), + stderr=sys.stderr, stdout=f, close_fds=True) + + # in seconds + interval = 0.5 + wait_for = 60 + for i in xrange(int(wait_for / interval)): + if is_dropbox_running(): + return True + # back off from connect for a while + time.sleep(interval) + + return False + else: + return False + +@command +@requires_dropbox_running +def filestatus(args): + u"""get current sync status of one or more files +dropbox filestatus [-l] [-a] [FILE]... + +Prints the current status of each FILE. + +options: + -l --list prints out information in a format similar to ls. works best when your console supports color :) + -a --all do not ignore entries starting with . +""" + oparser = optparse.OptionParser() + oparser.add_option("-l", "--list", action="store_true", dest="list") + oparser.add_option("-a", "--all", action="store_true", dest="all") + (options, args) = oparser.parse_args(args) + + # first check if dropbox is already running + try: + with closing(DropboxCommand()) as dc: + if options.list: + # TODO: ls style columns + + if len(args) == 0: + dirs, nondirs = [u"."], [] + else: + dirs, nondirs = [], [] + + for a in args: + try: + (dirs if os.path.isdir(a) else nondirs).\ + append(a.decode(sys.getfilesystemencoding())) + except UnicodeDecodeError: + pass + + if len(dirs) == 0 and len(nondirs) == 0: + exit(1) + + def lowerkey(st): + return st.lower() + + dirs.sort(key=lowerkey) + nondirs.sort(key=lowerkey) + + def printstatus(fp): + if not os.path.exists(fp): + console_print(u"%s (File doesn't exist!)" % os.path.basename(fp)) + return + + try: + status = dc.icon_overlay_file_status(path=fp).get(u'status', [None])[0] + except DropboxCommand.CommandError, e: + console_print(u"%s (%s)" % (os.path.basename(fp), e)) + return + + if not sys.stdout.isatty(): + console_print(os.path.basename(fp)) + return + + if status == u"up to date": + INIT, CLEANUP = "\x1b[32m", "\x1b[0m" + elif status == u"syncing": + INIT, CLEANUP = "\x1b[36m", "\x1b[0m" + elif status == u"unsyncable": + INIT, CLEANUP = "\x1b[41m", "\x1b[0m" + else: + INIT, CLEANUP = '', '' + + console_print(u"%s%s%s" % (INIT, os.path.basename(fp), CLEANUP)) + + def printdir(name): + for subname in sorted(os.listdir(name), key=lowerkey): + if type(subname) != unicode: + continue + + if not options.all and subname[0] == u'.': + continue + + try: + printstatus(unicode_abspath(os.path.join(name, subname))) + except (UnicodeEncodeError, UnicodeDecodeError), e: + continue + try: + if len(dirs) == 1 and len(nondirs) == 0: + printdir(dirs[0]) + else: + for name in nondirs: + try: + printstatus(unicode_abspath(name)) + except (UnicodeEncodeError, UnicodeDecodeError), e: + continue + + if len(nondirs) == 0: + console_print(dirs[0] + u":") + printdir(dirs[0]) + dirs = dirs[1:] + + for name in dirs: + console_print() + console_print(name + u":") + printdir(name) + except DropboxCommand.EOFError: + console_print(u"Dropbox daemon stopped.") + except DropboxCommand.BadConnectionError, e: + console_print(u"Dropbox isn't responding!") + else: + if len(args) == 0: + args = [name for name in os.listdir(u".") if type(name) == unicode] + indent = max(len(st)+1 for st in args) + for file in args: + try: + fp = unicode_abspath(file.decode(sys.getfilesystemencoding())) + except (UnicodeEncodeError, UnicodeDecodeError), e: + continue + if not os.path.exists(fp): + console_print(u"%-*s %s" % \ + (indent, file+':', "File doesn't exist")) + continue + + try: + status = dc.icon_overlay_file_status(path=fp).get(u'status', [u'unknown'])[0] + console_print(u"%-*s %s" % (indent, file+':', status)) + except DropboxCommand.CommandError, e: + console_print(u"%-*s %s" % (indent, file+':', e)) + except DropboxCommand.CouldntConnectError, e: + console_print(u"Dropbox isn't running!") + +@command +@requires_dropbox_running +def ls(args): + u"""list directory contents with current sync status +dropbox ls [FILE]... + +This is an alias for filestatus -l +""" + return filestatus(["-l"] + args) + +@command +@requires_dropbox_running +def puburl(args): + u"""get public url of a file in your dropbox +dropbox puburl FILE + +Prints out a public url for FILE. +""" + if len(args) != 1: + console_print(puburl.__doc__,linebreak=False) + return + + try: + with closing(DropboxCommand()) as dc: + try: + console_print(dc.get_public_link(path=unicode_abspath(args[0].decode(sys.getfilesystemencoding()))).get(u'link', [u'No Link'])[0]) + except DropboxCommand.CommandError, e: + console_print(u"Couldn't get public url: " + str(e)) + except DropboxCommand.BadConnectionError, e: + console_print(u"Dropbox isn't responding!") + except DropboxCommand.EOFError: + console_print(u"Dropbox daemon stopped.") + except DropboxCommand.CouldntConnectError, e: + console_print(u"Dropbox isn't running!") + +@command +@requires_dropbox_running +def status(args): + u"""get current status of the dropboxd +dropbox status + +Prints out the current status of the Dropbox daemon. +""" + if len(args) != 0: + console_print(status.__doc__,linebreak=False) + return + + try: + with closing(DropboxCommand()) as dc: + try: + lines = dc.get_dropbox_status()[u'status'] + if len(lines) == 0: + console_print(u'Idle') + else: + for line in lines: + console_print(line) + except KeyError: + console_print(u"Couldn't get status: daemon isn't responding") + except DropboxCommand.CommandError, e: + console_print(u"Couldn't get status: " + str(e)) + except DropboxCommand.BadConnectionError, e: + console_print(u"Dropbox isn't responding!") + except DropboxCommand.EOFError: + console_print(u"Dropbox daemon stopped.") + except DropboxCommand.CouldntConnectError, e: + console_print(u"Dropbox isn't running!") + +@command +@requires_dropbox_running +def stop(args): + u"""stop dropboxd +dropbox stop + +Stops the dropbox daemon. +""" + try: + with closing(DropboxCommand()) as dc: + try: + dc.tray_action_hard_exit() + except DropboxCommand.BadConnectionError, e: + console_print(u"Dropbox isn't responding!") + except DropboxCommand.EOFError: + console_print(u"Dropbox daemon stopped.") + except DropboxCommand.CouldntConnectError, e: + console_print(u"Dropbox isn't running!") + +@command +def start(argv): + u"""start dropboxd +dropbox start [-i] + +Starts the dropbox daemon, dropboxd. If dropboxd is already running, this will do nothing. + +options: + -i --install auto install dropboxd if not available on the system +""" + + should_install = "-i" in argv or "--install" in argv + + # first check if dropbox is already running + if is_dropbox_running(): + console_print(u"Dropbox is already running!") + return + + console_print(u"Starting Dropbox...", linebreak=False) + console_flush() + if not start_dropbox(): + if not should_install: + console_print() + console_print(u"The Dropbox daemon is not installed!") + console_print(u"Run with -i to install the daemon") + return + + # install dropbox!!! + try: + download() + except: + pass + else: + if GUI_AVAILABLE: + start_dropbox() + else: + console_print(u"Dropbox has been downloaded successfully.") + console_print(u"In order to link to an account for the first time, a graphical environment is required.") + console_print(u"Try running 'dropbox start' from X windows") + console_print(u"Done!") + +@command +def help(argv): + u"""provide help +dropbox help [COMMAND] + +With no arguments, print a list of commands and a short description of each. With a command, print descriptive help on how to use the command. +""" + if not argv: + return usage(argv) + for command in commands: + if command == argv[0]: + console_print(commands[command].__doc__.split('\n', 1)[1].decode('ascii')) + return + console_print(u"unknown command '%s'" % argv[0], f=sys.stderr) + +def usage(argv): + console_print(u"Dropbox command-line interface\n") + console_print(u"commands:\n") + out = [] + for command in commands: + out.append((command, commands[command].__doc__.splitlines()[0])) + spacing = max(len(o[0])+3 for o in out) + for o in out: + console_print(" %-*s%s" % (spacing, o[0], o[1])) + console_print() + +def main(argv): + global commands + + # now we need to find out if one of the commands are in the + # argv list, and if so split the list at the point to + # separate the argv list at that point + cut = None + for i in range(len(argv)): + if argv[i] in commands: + cut = i + break + + if cut == None: + usage(argv) + return + + # lol no options for now + globaloptionparser = optparse.OptionParser() + globaloptionparser.parse_args(argv[0:i]) + + # now dispatch and run + return commands[argv[i]](argv[i+1:]) + +if __name__ == "__main__": + main(sys.argv) diff --git a/dvd-blank b/dvd-blank new file mode 100755 index 0000000..a58592c --- /dev/null +++ b/dvd-blank @@ -0,0 +1,6 @@ + +. /etc/dvd-scripts.env + +dvd+rw-format -blank $DVD_DEVICE + +echo Fertig. diff --git a/dvd-burn-files b/dvd-burn-files new file mode 100755 index 0000000..6929dcd --- /dev/null +++ b/dvd-burn-files @@ -0,0 +1,24 @@ + +set -x + +. /etc/dvd-scripts.env + +DVD_DIR=$1 + +echo "Verzeichnis $DVD_DIR auf DVD brennen..." + +MAX_SIZE=4702989182 + +# DVD-Size 4,702,989,182 +size=`du -sb "$DVD_DIR" | awk '{print $1}'` +#printf "size: %4d MB\n" `expr $size \/ 1024 \/ 1024` +printf "size: %4d MB\n" `echo "$size/1024/1024;" | bc ` +if [ $size -gt $MAX_SIZE ] +then + printf "Zu Groß (max: %4d MB) !!!\n" `expr $MAX_SIZE \/ 1024 \/ 1024` +else + growisofs -Z $DVD_DEVICE -R -J $DVD_DIR +fi +sleep 1 +echo Fertig. +eject diff --git a/dvd-burn-image b/dvd-burn-image new file mode 100755 index 0000000..df130aa --- /dev/null +++ b/dvd-burn-image @@ -0,0 +1,15 @@ +#!/bin/bash + +set -x + +. /etc/dvd-scripts.env + +#/etc/init.d/hdparm restart +hdparm -u1 -d1 $DVD_DEVICE + +DVD_IMAGE=$1 + +[ -r $DVD_IMAGE ] && growisofs -Z $DVD_DEVICE=$DVD_IMAGE +echo Fertig. +sleep 1 +eject diff --git a/dvd-burn-video b/dvd-burn-video new file mode 100755 index 0000000..2239ad8 --- /dev/null +++ b/dvd-burn-video @@ -0,0 +1,16 @@ +#!/bin/sh + +set -x + +. /etc/dvd-scripts.env + +#A/etc/init.d/hdparm restart +hdparm -d1 -u1 $DVD_DEVICE + +DVD_DIR=$1 + +growisofs -Z $DVD_DEVICE -dvd-video $DVD_DIR +growisofs -lead-out $DVD_DEVICE +echo Fertig. +sleep 1 +eject diff --git a/dvd-check-size b/dvd-check-size new file mode 100755 index 0000000..1dfd29e --- /dev/null +++ b/dvd-check-size @@ -0,0 +1,17 @@ + +#set -x + +. /etc/dvd-scripts.env + +DVD_DIR=$1 +MAX_DVD_SIZE=4702989182 + +# DVD-Size 4,702,989,182 +size=`du -sb "$DVD_DIR" | awk '{print $1}'` +printf "Größe: %4d MB\n" `expr $size \/ 1024 \/ 1024` +if [ $size -gt $MAX_DVD_SIZE ] +then + printf "zu Groß (max %4d MB)\n" `expr $MAX_DVD_SIZE \/ 1024 \/ 1024` +else + echo Paßt. +fi diff --git a/dvd-createdev b/dvd-createdev new file mode 100755 index 0000000..e85147c --- /dev/null +++ b/dvd-createdev @@ -0,0 +1,16 @@ +#!/bin/sh + +DVD_DEVICE=/dev/dvd + +if [ -L $DVD_DEVICE ] +then + echo "Link löschen" + rm $DVD_DEVICE +else + echo "Altes Device löschen $DVD_DEVICE" + umount $DVD_DEVICE + rmdir $DVD_DEVICE +fi +echo "neuen device erstellen" +mkdir $DVD_DEVICE + diff --git a/dvd-format b/dvd-format new file mode 100755 index 0000000..9299008 --- /dev/null +++ b/dvd-format @@ -0,0 +1,6 @@ + +. /etc/dvd-scripts.env + +dvd+rw-format -force $DVD_DEVICE + +echo Fertig. diff --git a/dvd-gen-movix b/dvd-gen-movix new file mode 100755 index 0000000..a054cd6 --- /dev/null +++ b/dvd-gen-movix @@ -0,0 +1,31 @@ + +set -x + +. /etc/dvd-scripts.env + +DVD_DIR=$1 +FILES=$2 + +cd $DVD_DIR + +echo "Movix DVD aus Dateien $DVD_DIR/$FILES erzeugen..." + +#MAX_SIZE=4702989182 + +# DVD-Size 4,702,989,182 +i#size=`du -sb "$DVD_DIR" | awk '{print $1}'` +#printf "size: %4d MB\n" `expr $size \/ 1024 \/ 1024` +#printf "size: %4d MB\n" `echo "$size/1024/1024;" | bc ` +#if [ $size -gt $MAX_SIZE ] +#then +# printf "Zu Groß (max: %4d MB) !!!\n" `expr $MAX_SIZE \/ 1024 \/ 1024` +#lse +# growisofs -Z $DVD_DEVICE -R -J $DVD_DIR +#fi + +mkmovixiso $FILES +ln -s movix.iso last.iso + +sleep 1 +echo Fertig. +eject diff --git a/dvd-rip-image b/dvd-rip-image new file mode 100755 index 0000000..b0c203f --- /dev/null +++ b/dvd-rip-image @@ -0,0 +1,17 @@ +#!/bin/sh + +. /etc/dvd-scripts.env + +DVD_IMAGE=$1 + +rm "$DVD_IMAGE" +rm /dat/dvd/last.iso + +echo Image wird erstellt... +dd if=$DVD_DEVICE of="$DVD_IMAGE" + +ln -s "$DVD_IMAGE" /dat/dvd/last.iso + +echo Fertig. + +eject diff --git a/dvd2vdr b/dvd2vdr new file mode 100755 index 0000000..eed83d0 --- /dev/null +++ b/dvd2vdr @@ -0,0 +1,1378 @@ +#! /bin/bash + +############################################################################ +# Copyright (C) 2006 by Ronny Frankowski (lini@lausitz.net) # +# & AngieSoft (vdr@angiesoft.de) # +# & Matthias Appel (private_tweety@gmx.net) # +# # +# This program is free software; you can redistribute it and#or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program; if not, write to the # +# Free Software Foundation, Inc., # +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # +############################################################################ + + +########################################################################### +# define some variables +########################################################################### + +VERSION="1.0.1" + +VIDEODIR=/video0/vdr/video # video directory of vdr +WORKDIR=/video0/vdr/tmp/dvd2vdr # working directory of dvd2vdr +DVD_DEVICE=/dev/cdrom # dvd device + +DVD2VDR_CONF=/video0/vdr/conf/plugins/dvd2vdr.conf + + # this file overrides some + # internal settings and + # command line options + +LANGUAGE="de" # select preferred language + # "de", "en" + +RECORDING_LIFETIME=99 # lifetime from 00 to 99 +RECORDING_MAX_SIZE=2000000000 # max size (byte) for a single + # *.vdr file +RECORDING_MAX_CHUNKS=255 # max chunks for spliting + +#TITLE_MIN_LENGTH=60 # mimimun length in sec for + # a title on a DVD to be + # considered for conversion + +PRIO=15 # priority from 1 to 19 +SLEEPTIME=10 # wait for user action +VERBOSE=1 # be verbose - 0: off, 1: on +DEBUG=1 # debug info - 0: off, 1-3: level +FORCE=0 # force exec - 0: off, 1: on (erzwingen) +CLEAN=1 # clean dirs - 0: off, 1: on (abschliesendes loeschen) +REMOVE=1 # remove tmp file - 0: off, 1: on (temp. loeschen im Betrieb) + +OSDINFO=1 # svdrpsend - 0: off, 1: on + +A52DEC_GAIN="+5.0" # add gain in decibels +CREATE_MARKS=0 # create a marks.vdr for vdr - 0: off, 1: on + + +########################################################################### +# define required tools +########################################################################### + +PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/X11R6/bin:~/bin + +SVDRPSEND_PL=svdrpsend.pl + +VOBCOPY_BIN=vobcopy +EJECT_BIN=eject +TCPROBE_BIN=tcprobe +TCCAT_BIN=tccat +TCEXTRACT_BIN=tcextract +TCDEMUX_BIN=tcdemux + +A52DEC_BIN=a52dec +TOOLAME_BIN=toolame +MP2ENC_BIN=mp2enc + +JAVA_BIN=/usr/lib/java/bin/java +PROJECTX_JAR=/usr/local/share/vdrconvert/pX/pX.jar #/usr/local/bin/projectX.jar +PROJECTX_INI=/usr/local/share/vdrconvert/pX/pX.ini #/usr/local/etc/dvd2vdr-projectX.ini +XVFB_BIN=/usr/X11R6/bin/Xvfb + +TCMPLEX_BIN=tcmplex +TCMPLEX_PANTELTJE_BIN=tcmplex-panteltje +MPLEX_BIN=mplex + +SPLIT_BIN=split + +GENINDEX_BIN=genindex +GENINDEX_MJPEGFIX_BIN=genindex-mjpegfix + +LOGDIR=/var/log/vdr +LOGFILE=$LOGDIR/dvd2vdr.log +LOCKFILE=$LOGDIR/dvd2vdr.LOCK + + +########################################################################### +# print usage information +########################################################################### + +usage() { +test -n "$1" && echo "${RED} Error: $1${NORMAL}" && echo +echo " DVD2VDR Version ${MAGENTA}$VERSION${NORMAL}" +echo +echo " ${CYAN}Usage: ${GREEN}$0${NORMAL}" +echo " ${CYAN} or: ${GREEN}$0${NORMAL} [options]" +echo +echo " DVD2VDR is intended to convert the main movie of a DVD into" +echo " a VDR recoring. If required the main movie will be demuxed" +echo " transcoded and remuxed again." +echo +echo " ${CYAN}Actions:${NORMAL}" +echo +echo "${GREEN} all${NORMAL}" +echo " Do all steps of the following" +echo "${GREEN} copy${NORMAL}" +echo " Copy the main movie to disk" +echo "${GREEN} demux${NORMAL}" +echo " Demultiplex the main movie in mpv and ac3" +echo "${GREEN} encode${NORMAL}" +echo " Encode ac3 to mp2" +echo "${GREEN} mplex${NORMAL}" +echo " Multiplex the parts to a VDR recording" +echo "${GREEN} split${NORMAL}" +echo " Split the VDR recording into chunks" +echo "${GREEN} genindex${NORMAL}" +echo " Create an index.vdr" +echo "${GREEN} move${NORMAL}" +echo " Move recording to video directory" +echo +echo " ${CYAN}Options:${NORMAL}" +echo +echo "${GREEN} -i | --device ${MAGENTA}${NORMAL}" +echo " Read DVD structure from this device" +echo "${GREEN} -o ${MAGENTA}${NORMAL}" +echo " Write output into this video directory" +echo "${GREEN} -w ${NORMAL}" +echo " Use working directory as base for temp directory" +echo "${GREEN} -t ${MAGENTA}${NORMAL}" +echo " Use temp directory for temporary files" +echo "${GREEN} --preferred-language ${MAGENTA}${NORMAL}" +echo " Choose preferred language for messages" +echo " and the main movie (default is \"de\")" +echo "${GREEN} --no-osd-info${NORMAL}" +echo " Don't send messages to the OSD of VDR" +echo "${GREEN} --set-title ${MAGENTA}${NORMAL}" +echo " Set title of main movie to " +echo "${GREEN} --read-title-num ${MAGENTA}${NORMAL}" +echo " Read specific title set (1-99)" +echo "${GREEN} --use-tcextract${NORMAL}" +echo " Demux the main movie with tcextract (default)" +echo "${GREEN} --use-projectX${NORMAL}" +echo " Demux the main movie with projectX." +echo " Ensure to have a X server running" +echo "${GREEN} --projectX-ini ${MAGENTA}${NORMAL}" +echo " Use this X.ini for projectX" +echo "${GREEN} --use-Xvfb | --without-X${NORMAL}" +echo " Start a virtual X Server with Xvfb" +echo "${GREEN} --add-gain ${MAGENTA}${NORMAL}" +echo " Add gain to mp2 audio (-96.0 to +96.0)" +echo "${GREEN} --use-mp2enc${NORMAL}" +echo " Encode the audio track with mp2enc" +echo "${GREEN} --use-toolame${NORMAL}" +echo " Encode the audio track with toolame (default)" +echo "${GREEN} --use-mp3gain${NORMAL}" +echo " Normalize ac3 (time consuming)" +echo "${GREEN} --use-tcmplex${NORMAL}" +echo " Remux with tcmplex (default)" +echo "${GREEN} --use-tcmplex-panteltje${NORMAL}" +echo " Remux with tcmplex-panteltje" +echo "${GREEN} --use-mplex${NORMAL}" +echo " Remux with mplex" +echo "${GREEN} --use-genindex${NORMAL}" +echo " Create index.vdr with genindex (default)" +echo "${GREEN} --use-genindex-mjpegfix${NORMAL}" +echo " Create index.vdr with genindex-mjpegfix" +echo "${GREEN} --force${NORMAL}" +echo " Force execution of " +echo "${GREEN} --verbose${NORMAL}" +echo " Turns verbosity on" +echo "${GREEN} -V | --version${NORMAL}" +echo " Print version information and exit" +echo "${GREEN} --all-versions${NORMAL}" +echo " Print version information of most used tools" +echo "${GREEN} -h | -? | --help${NORMAL}" +echo " Print this usage information" +exit 1 +} + +########################################################################### +# set color parameters +########################################################################### + +# ANSI COLORS +CRE=" +" +NORMAL="" +# RED: Failure or error message +RED="" +# GREEN: Success message +GREEN="" +# YELLOW: Descriptions +YELLOW="" +# BLUE: System messages +BLUE="" +# MAGENTA: Found devices or drivers (pink) +MAGENTA="" +# CYAN: Questions (hellblau) +CYAN="" +# BOLD WHITE: Hint +WHITE="" + +########################################################################### +# check for given parameters +########################################################################### + +case $DEBUG in + 1) ;; + 2) set -x ;; + 3) set -xv ;; + *) LOGFILE=/dev/null ;; +esac + +ACTION="all" +OPTIONS=$@ +TEMPDIR="" +LANGUAGES=("de" "en") +TITLE="" +TITLENUM="AUTO" # AUTO = vobcopy-test; MAX = max. Frames; 1,2,3... DVD-Title +RECORDING="" +AUDIOTRACK=-1 +AUDIOFORMAT="" +TCEXTRACTOPTAUDIO="" +WITHOUT_X=1 +AC3_TRACK=1 + +GETTITLE_TOOLS=("user-input" "vobcopy") +COPY_TOOLS=("tccat") +DEMUX_TOOLS=("tcextract" "projectX") +ENCODE_TOOLS=("mp2enc" "toolame") +MPLEX_TOOLS=("tcmplex" "tcmplex-panteltje" "mplex") +SPLIT_TOOLS=("split") +GENINDEX_TOOLS=("genindex" "genindex-mjpegfix") + +ACTION_GETTITLE=${GETTITLE_TOOLS[1]} +ACTION_COPY=${COPY_TOOLS[0]} +ACTION_DEMUX=${DEMUX_TOOLS[0]} +ACTION_ENCODE=${ENCODE_TOOLS[0]} +ACTION_MPLEX=${MPLEX_TOOLS[1]} +ACTION_SPLIT=${SPLIT_TOOLS[0]} +ACTION_GENINDEX=${GENINDEX_TOOLS[0]} + +while [ $# -gt 0 ]; do + case $1 in + all|gettitle|copy|demux|encode|mplex|split|genindex|move) + ACTION="$1" + ;; + -i|--device) + [ -b "$2" ] || usage "${RED}unknown device ${MAGENTA}'$2'${NORMAL}" + DVD_DEVICE="$2" + shift + ;; + -o) + [ -d "$2" ] || usage "${RED}missing directory ${MAGENTA}'$2'${NORMAL}" + VIDEODIR="$2" + shift + ;; + -w) + [ -d "$2" ] || usage "${RED}missing directory ${MAGENTA}'$2'${NORMAL}" + WORKDIR="$2" + shift + ;; + -t) + [ -d "$2" ] || usage "${RED}missing directory ${MAGENTA}'$2'${NORMAL}" + TEMPDIR=`echo $2 | sed "s/\/$//"` + shift + ;; + --preferred-language) + [ $2 = "" ] || usage "${RED}missing language${NORMAL}" + LANGUAGE=$2 + shift + ;; + --no-osd-info) + OSDINFO=0 + ;; + --set-title) + TITLE=`echo $2 | sed "s/[^a-zA-Z0-9???????/:.#'&_-]/_/g"` + ACTION_GETTITLE=${GETTITLE_TOOLS[0]} + shift + ;; + --read-title-num) +# [ $2 -ge 1 -a $2 -le 99 ] || usage "${RED}invalid title number ${MAGENTA}'$2'${NORMAL}" + TITLENUM=$2 + shift + ;; + --use-tcextract) + ACTION_DEMUX=${DEMUX_TOOLS[0]} + ;; + --use-projectX) + ACTION_DEMUX=${DEMUX_TOOLS[1]} + ;; + --projectX-ini) + [ -e "$2" ] || usage "${RED}missing file ${MAGENTA}'$2'${NORMAL}" + PROJECTX_INI="$2" + shift + ;; + --use-Xvfb|--without-X) + WITHOUT_X=0 + ;; + --add-gain) + [ `echo $2 | \\ + grep -c "[+-][[:digit:]]\{1,2\}\.[[:digit:]]"` -eq 1 ] || \ + usage "${RED}invalid gain ${MAGENTA}'$2'${NORMAL}" + A52DEC_GAIN="$2" + shift + ;; + --use-mp2enc) + ACTION_ENCODE=${ENCODE_TOOLS[0]} + ;; + --use-toolame) + ACTION_ENCODE=${ENCODE_TOOLS[1]} + ;; + --use-tcmplex) + ACTION_MPLEX=${MPLEX_TOOLS[0]} + ;; + --use-tcmplex-panteltje) + ACTION_MPLEX=${MPLEX_TOOLS[1]} + ;; + --use-mplex) + ACTION_MPLEX=${MPLEX_TOOLS[2]} + ;; + --use-genindex) + ACTION_GENINDEX=${GENINDEX_TOOLS[0]} + ;; + --use-genindex-mjpegfix) + ACTION_GENINDEX=${GENINDEX_TOOLS[1]} + ;; + --force) + FORCE=1 + ;; + --clean) + CLEAN=1 + ;; + --verbose) + VERBOSE=1 + ;; + -V|--version) + echo "${GREEN}$0 ${MAGENTA}Version $VERSION${NORMAL}" + exit 1 + ;; + --all-versions) + echo "${GREEN}$0 ${MAGENTA}Version $VERSION${NORMAL}" + echo + $VOBCOPY_BIN --version + $TCPROBE_BIN -v + $TCCAT_BIN -v + $TCEXTRACT_BIN -v + $TCDEMUX_BIN -v + echo + $A52DEC_BIN - 2>&1|grep a52dec + $TOOLAME_BIN --version 2>&1|grep version + echo + $JAVA_BIN -version + echo + $MPLEX_BIN -? 2>&1|grep version + $TCMPLEX_BIN -v + $TCMPLEX_PANTELTJE_BIN -v + echo + $GENINDEX_BIN 2>&1|grep genindex + exit 1 + ;; + -h|-?|--help) + usage + ;; + *) + usage "${RED}unknown option ${MAGENTA}'$1'${NORMAL}" ;; + esac + shift +done + +[ -f "$DVD2VDR_CONF" ] && . "$DVD2VDR_CONF" + + +########################################################################### +# translation tables for user messages +########################################################################### + +LNG=0 +for i in 0 1 ; do + [ $LANGUAGE = ${LANGUAGES[$i]} ] && LNG=$i +done + +MESG_01=( \ +"Bitte die zu wandelne DVD einlegen" \ +"please insert DVD" \ +) + +MESG_02=( \ +"Keine DVD im Laufwerk erkannt" \ +"DVD not found" \ +) + +MESG_03=( \ +"Kopiere DVD auf Disk" \ +"Copy DVD to disk" \ +) + +MESG_04=( \ +"Videospur nicht gefunden - Abbruch" \ +"main movie not found - exiting" \ +) + +MESG_05=( \ +"Tonspur '$LANGUAGE' nicht gefunden - Abbruch" \ +"Audio track '$LANGUAGE' not found - exiting" \ +) + +MESG_06=( \ +"Kein unterstuetztes Audioformat auf der DVD gefunden - Abbruch" \ +"no supported audio format found - exiting" \ +) + +MESG_07=( \ +"Kopieren der DVD gescheitert - Abbruch" \ +"copying of main movie failed - exiting" \ +) + +MESG_08=( \ +"DVD auslesen beendet, bitte DVD entnehmen" \ +"main movie successfully read, please remove DVD" \ +) + +MESG_09=( \ +"Fehler bei der Umwandlung der DVD-Daten - Abbruch" \ +"failed to transcode the main movie - exiting" \ +) + +MESG_10=( \ +"DVD Daten werden mit '$ACTION_DEMUX' bearbeitet" \ +"" \ +) + +MESG_11=( \ +"DVD Daten werden mit '$ACTION_MPLEX' bearbeitet" \ +"" \ +) + +MESG_12=( \ +"DVD Daten werden gesplittet" \ +"" \ +) + +MESG_13=( \ +"DVD Daten werden mit '$ACTION_GENINDEX' bearbeitet" \ +"" \ +) + +MESG_14=( \ +"Alle temp. Daten geloescht" \ +"" \ +) + +MESG_15=( \ +"Daten befinden sich in ${VIDEODIR}" \ +"" \ +) + +MESG_16=( \ +"!!! GRATULATION , FERTIG !!!" \ +"" \ +) + +MESG_30=( \ +"textutils Fehler, update dein coreutils" \ +"error textutils, upgrade your coreutils" \ +) + +########################################################################### +# prepare to run +########################################################################### + +d2v_error () { + echo "${RED}ERROR: ${MAGENTA}$1${NORMAL}" + $EJECT_BIN $DVD_DEVICE + exit 255 +} + + +d2v_log () { + [ $VERBOSE -eq 1 -o "$2" = "force" ] && echo "`date +"%T"`: $1" + echo "`date +"%T"`: $1" >> $LOGFILE +} + + +d2v_log_separator () { + d2v_log "---------------------------------------------------------------" +} + + +d2v_log_force () { + d2v_log "$1" force +} + + +d2v_mesg () { + if [ $OSDINFO -eq 1 ] ; then + d2v_log "$SVDRPSEND_PL MESG $1" + $SVDRPSEND_PL MESG "$1" >> $LOGFILE + fi +} + + +if [ -e $LOCKFILE ] ; then + if [ $FORCE -eq 1 ] ; then + rm -f $LOCKFILE + else + PIDID=`cat $LOCKFILE` + RUNCHECK=`ps $PIDID | grep 'dvd2' | wc -l` + if [ $RUNCHECK -eq 0 ]; then + rm -f $LOCKFILE + d2v_log "dvd2vdr is not active, remove lockfile done" + else + d2v_error "$0 is already running" + fi + fi +fi + +echo "$0 $OPTIONS" > $LOGFILE || d2v_error "${RED}Cannot create \$LOGFILE ${MAGENTA}'$LOGFILE'${NORMAL}" +echo $$ > $LOCKFILE || d2v_error "${RED}Cannot create \$LOCKFILE ${MAGENTA}'$LOCKFILE'${NORMAL}" + +d2v_log_separator +d2v_log_force START + +[ -d $VIDEODIR ] || d2v_error "${RED}\$VIDEODIR ${MAGENTA}'$VIDEODIR' ${RED}not found${NORMAL}" + VIDEODIR=`echo $VIDEODIR | sed "s/\/$//"` +[ -d $WORKDIR ] || d2v_error "${RED}\$WORKDIR ${MAGENTA}'$WORKDIR' ${RED}not found${NORMAL}" + WORKDIR=`echo $WORKDIR | sed "s/\/$//"` +[ -b $DVD_DEVICE ] || d2v_error "${RED}\$DVD_DEVICE ${MAGENTA}'$DVD_DEVICE' ${RED}not found${NORMAL}" + +[ $PRIO -ge 1 -a $PRIO -le 19 ] || \ + d2v_error "${RED}\$PRIO ${MAGENTA}$PRIO ${RED}out of range${NORMAL}" +[ $VERBOSE -ge 0 -a $VERBOSE -le 1 ] || \ + d2v_error "${RED}\$VERBOSE ${MAGENTA}$VERBOSE ${RED}out of range${NORMAL}" + +########################################################################### +# check the temp directory +########################################################################### + +d2v_log_separator +d2v_log_force "checking the temp directory" + +if [ $ACTION = "all" -a -z "$TEMPDIR" ] ; then + TEMPDIR=`mktemp -dp ${WORKDIR}` + d2v_log "\$TEMPDIR='$TEMPDIR' created" +elif [ $ACTION != "all" -a -z "$TEMPDIR" ] ; then + HELP="`echo && echo \$\> ls -d1 ${WORKDIR} && \ + ls -d1 ${WORKDIR}/tmp.* 2> /dev/null`" + [ `ls -d1 ${WORKDIR}/tmp.* 2> /dev/null | wc -l` -ne 1 ] && \ + d2v_error "${RED}no unique temp directory found $HELP${NORMAL}" + TEMPDIR=`ls -d1 ${WORKDIR}/tmp.* | head -n 1` + d2v_log "\$TEMPDIR='$TEMPDIR' used" +else + d2v_log "\$TEMPDIR='$TEMPDIR' used" +fi + + + +########################################################################### +# read and write global variables to disk +########################################################################### + +VARIABLES="TITLE RECORDING TITLENUM AUDIOTRACK AUDIOFORMAT TCEXTRACTOPTAUDIO" + +readvars () { + local FILE=${TEMPDIR}/variables.info + + if [ -f $FILE ] ; then + d2v_log_separator + d2v_log_force "reading file '$FILE'" + + for i in $VARIABLES ; do + if [ "$i" != "TITLE" -o "$TITLE" = "" ] ; then + eval $i=\"`grep "^$i=" $FILE | awk -F = '{print $2}'`\" + eval d2v_log \"\\\$$i=\'$`echo $i`\'\" + fi + done + fi +} + +writevars () { + local FILE=${TEMPDIR}/variables.info + + if [ "$TITLE" != "" -a "$RECORDING" != "" ] ; then + d2v_log_separator + d2v_log_force "writing file '$FILE'" + + echo "LASTRUN=`date +"%Y-%m-%d %T"`" > $FILE || \ + d2v_error "${RED}Cannot create file ${MAGENTA}'$FILE'${NORMAL}" + + for i in $VARIABLES ; do + eval echo "$i=$`echo $i`" >> $FILE + done + fi +} + + +########################################################################### +# gettitle of the main movie +########################################################################### + +gettitle () { + d2v_log_separator + d2v_log_force \ + "using '$ACTION_GETTITLE' to get the title of the main movie" + + if [ "$TITLE" = "" -o "$RECORDING" = "" -o $FORCE -eq 1 ] ; then + + # insert DVD and do some checks + d2v_mesg "${MESG_01[$LNG]}" + $EJECT_BIN $DVD_DEVICE + sleep $SLEEPTIME + + local DVDSTATUS=1 + while [ "$DVDSTATUS" -gt 0 ] ; do + $TCPROBE_BIN -i $DVD_DEVICE -H 10 >> $LOGFILE 2>&1> /dev/null + DVDSTATUS=$? + if [ $DVDSTATUS -gt 0 ]; then + d2v_mesg "${MESG_02[$LNG]}" + # insert DVD + d2v_mesg "${MESG_01[$LNG]}" + $EJECT_BIN $DVD_DEVICE + sleep $SLEEPTIME + fi + done + + case $ACTION_GETTITLE in + ${GETTITLE_TOOLS[0]}) + ;; + ${GETTITLE_TOOLS[1]}) + d2v_log "`echo && echo \$\> $VOBCOPY_BIN -i $DVD_DEVICE \ + -v -v -I -L ${TEMPDIR} 2\> /dev/null`" + $VOBCOPY_BIN -i $DVD_DEVICE -v -v -I \ + -L ${TEMPDIR} 2> /dev/null && \ + TITLE=`cat ${TEMPDIR}/vobcopy_*.log | \ + grep 'Name of the dvd' | head -n 1 | awk '{print $6}'` && \ + cat ${TEMPDIR}/vobcopy_*.log >> $LOGFILE + if [ $TITLENUM = "AUTO" ] ; then + TITLENUM=`cat ${TEMPDIR}/vobcopy_*.log | \ + grep 'Using Title' | head -n 1 | awk '{print $4}'` && \ + fi + ;; + esac + + d2v_log "`echo && echo \$\> ls -l ${TEMPDIR} && ls -l ${TEMPDIR}`" + + TITLE=`echo $TITLE | sed "s/[^a-zA-Z0-9???????/:.#'&_-]/_/g"` + [ `echo $TITLE | wc -m` -le 2 ] && TITLE="DVD`date +%Y-%m-%d-%M-%H`" + + RECORDING="`date +%Y-%m-%d.%H.%M`.99.$RECORDING_LIFETIME.rec" + fi + + d2v_log_force "\$TITLE='$TITLE'" + d2v_log_force "\$TITLENUM='$TITLENUM'" + d2v_log_force "\$RECORDING='$RECORDING'" +} + + +########################################################################### +# test for the main movie +########################################################################### + +test () { + d2v_log_separator + d2v_log_force \ + "using 'tcprobe' to test for the main movie" + + if [ ! -f ${TEMPDIR}/001.vob -o $FORCE -eq 1 -o \ + $AUDIOTRACK -lt 0 -o "$AUDIOFORMAT" = "" -o \ + "$TCEXTRACTOPTAUDIO" = "" ] ; then + + # find main movie + local MAX_TITLENUM=0 + + d2v_log "`echo && echo \$\> $TCPROBE_BIN -H 0 \ + -i $DVD_DEVICE 2\>\&1 \| grep 'title 1/' \| awk '{print $5}'`" + + MAX_TITLENUM=`$TCPROBE_BIN -H 0 -i $DVD_DEVICE 2>&1 | \ + grep 'title 1/' | awk '{print $5}'` + + if [ $MAX_TITLENUM -eq 0 ] ; then + d2v_mesg "${MESG_04[$LNG]}" + $TCPROBE_BIN -H 0 -i $DVD_DEVICE 2>&1 >> $LOGFILE + cp $LOGFILE ${TEMPDIR}/$TITLE.log + d2v_error "${RED}exiting${NORMAL}" + fi + + d2v_log "\$MAX_TITLENUM='$MAX_TITLENUM'" + + local i=0 + local FRAMES=0 + local MAX_FRAMES=0 + + if [ $TITLENUM = "MAX" ] ; then + while [ "$i" -lt $MAX_TITLENUM ] ; do + i=$((i+1)) + FRAMES=`$TCPROBE_BIN -i $DVD_DEVICE -H 10 -T $i \ + 2>/dev/null | grep 'frames' | awk '{print $3}'` + [ -z $FRAMES ] && FRAMES="0" + if [ $FRAMES -gt $MAX_FRAMES ] ; then + if [ $FRAMES -gt $((${TITLE_MIN_LENGTH}*25)) ]; then + TITLENUM="$i" + MAX_FRAMES="$FRAMES" + fi + fi + done + fi + + d2v_log "\$MAX_FRAMES='$MAX_FRAMES'" + + if [ $TITLENUM = "MAX" ]; then + d2v_mesg "${MESG_04[$LNG]}" + $TCPROBE_BIN -H 0 -i $DVD_DEVICE 2>&1 >> $LOGFILE + cp $LOGFILE ${TEMPDIR}/$TITLE.log + d2v_error "${RED}exiting${NORMAL}" + fi + + d2v_log "\$TITLENUM='$TITLENUM'" + + # create the marks.vdr + + if [ $CREATE_MARKS -eq 1 ]; then + d2v_log "`echo && echo \$\> $TCPROBE_BIN -i $DVD_DEVICE -H 10 \ + -T $TITLENUM 2\>\&1 \| grep Chapter \| cut -d \\\" \\\" -f 4 \ + \> ${TEMPDIR}/marks.vdr`" + $TCPROBE_BIN -i $DVD_DEVICE -H 10 -T $TITLENUM 2>&1 | \ + grep Chapter | cut -d " " -f 4 > ${TEMPDIR}/marks.vdr + fi + + # read audio track + local AUDIOTYPE="" + local AUDIOTYPELINES=0 + local AUDIOFORMATLINES=0 + + d2v_log "`echo && echo \$\> $TCPROBE_BIN -i $DVD_DEVICE -H 10 \ + -T $TITLENUM 2\> /dev/null \| grep dvd_reader.c \| grep kHz \| \ + cat -b - \> ${TEMPDIR}/transcode-audio.log`" + $TCPROBE_BIN -i $DVD_DEVICE -H 10 -T $TITLENUM 2> /dev/null | \ + grep dvd_reader.c | \ + grep kHz | cat -b - > ${TEMPDIR}/transcode-audio.log + + d2v_log "`echo && echo \$\> $TCPROBE_BIN -i $DVD_DEVICE -H 10 \ + -T $TITLENUM 2\> /dev/null \| grep "audio track:" \ + cat -b - \> ${TEMPDIR}/transcode-audio2.log`" + $TCPROBE_BIN -i $DVD_DEVICE -H 10 -T $TITLENUM 2> /dev/null | \ + grep "audio track:" | cat -b - > ${TEMPDIR}/transcode-audio2.log + + AUDIOTRACK=`cat ${TEMPDIR}/transcode-audio.log | \ + grep -n " "$LANGUAGE" " | grep "ac3" | head -n 1 | \ + awk '{print (($1-1))}'` + + if [ -z $AUDIOTRACK ] ; then + AUDIOTRACK=`cat ${TEMPDIR}/transcode-audio.log | grep -n " "$LANGUAGE" " | \ + head -n 1 | awk '{print (($1-1))}'` + if [ -z $AUDIOTRACK ] ; then + AUDIOTRACK=-1 + fi + fi + + AUDIOTYPE=`cat ${TEMPDIR}/transcode-audio.log | \ + grep " "$LANGUAGE" " | head -n 1 | awk '{print $3}'` + AUDIOTYPELINES=`cat ${TEMPDIR}/transcode-audio.log | \ + grep " "$LANGUAGE" " | head -n 1 | awk '{print $3}' | \ + wc -m | awk '{print $1}'` + AUDIOFORMATLINES=`cat ${TEMPDIR}/transcode-audio2.log | \ + grep "0x55"| head -n 1 | wc -m | awk '{print $1}'` + TRANSCODE_AUDIO=`cat ${TEMPDIR}/transcode-audio.log` + TRANSCODE_AUDIO2=`cat ${TEMPDIR}/transcode-audio2.log` + + if [ -z $AUDIOTYPELINES ] ; then + d2v_mesg "${MESG_30[$LNG]}" + $TRANSCODE_AUDIO >> $LOGFILE + $TRANSCODE_AUDIO2 >> $LOGFILE + cp $LOGFILE ${TEMPDIR}/$TITLE.log + d2v_error "${RED}exiting${NORMAL}" + fi + + if [ $AUDIOTYPELINES -eq 0 ] ; then + d2v_mesg "${MESG_05[$LNG]}" + $TRANSCODE_AUDIO >> $LOGFILE + $TRANSCODE_AUDIO2 >> $LOGFILE + cp $LOGFILE ${TEMPDIR}/$TITLE.log + d2v_error "${RED}exiting${NORMAL}" + fi + + + [ -z $AUDIOFORMATLINES ] && $AUDIOFORMATLINES="0" + if [ $AUDIOFORMATLINES -eq 0 ] ; then + AUDIOFORMAT="other" + else + AUDIOFORMAT="mp3" + fi + + if [ $DEBUG -gt 1 ] ; then + d2v_log_separator + d2v_log_force "write output from transcode-audio.log" + d2v_log "\$TRANSCODE_AUDIO='$TRANSCODE_AUDIO'" + d2v_log_separator + d2v_log_separator + d2v_log_force "write output from transcode-audio2.log" + d2v_log "\$TRANSCODE_AUDIO2='$TRANSCODE_AUDIO2'" + d2v_log_separator + fi + + d2v_log_force "\$AUDIOTRACK='$AUDIOTRACK'" + d2v_log "\$AUDIOTYPE='$AUDIOTYPE'" + d2v_log "\$AUDIOTYPELINES='$AUDIOTYPELINES'" + d2v_log_force "\$AUDIOFORMAT='$AUDIOFORMAT'" + d2v_log "\$AUDIOFORMATLINES='$AUDIOFORMATLINES'" + + case $AUDIOTYPE in + a??) + TCEXTRACTOPTAUDIO="ac3" + ;; + *pcm|raw) + TCEXTRACTOPTAUDIO="pcm" + if [ ACTION_ENCODE != ${ENCODE_TOOLS[1]} ] ; then + ACTION_ENCODE=${ENCODE_TOOLS[1]} + d2v_log "pcm audio track found - \ + forced the usage of '$ACTION_ENCODE'" + fi + ;; + mpeg?) + TCEXTRACTOPTAUDIO="mp2" + ;; + dts) + TCEXTRACTOPTAUDIO="dts" + ;; + *) + d2v_mesg "${MESG_06[$LNG]}" + cat $TRANSCODE_AUDIO >> $LOGFILE + cat $TRANSCODE_AUDIO2 >> $LOGFILE + cp $LOGFILE ${TEMPDIR}/$TITLE.log + d2v_error "${RED}exiting${NORMAL}" + ;; + esac + + d2v_log_force "\$TCEXTRACTOPTAUDIO='$TCEXTRACTOPTAUDIO'" + + d2v_log "`echo && echo \$\> ls -l ${TEMPDIR} && ls -l ${TEMPDIR}`" + else + d2v_log_force "\$AUDIOTRACK='$AUDIOTRACK'" + d2v_log_force "\$AUDIOFORMAT='$AUDIOFORMAT'" + d2v_log_force "\$TCEXTRACTOPTAUDIO='$TCEXTRACTOPTAUDIO'" + fi +} + + +########################################################################### +# copy the main movie to disk +########################################################################### + +copy () { + d2v_log_separator + d2v_log_force \ + "using '$ACTION_COPY' to copy the main movie to disk" + + if [ ! -f ${TEMPDIR}/001.vob -o $FORCE -eq 1 ] ; then + + # clean up + [ -f ${TEMPDIR}/001.vob ] && rm -f ${TEMPDIR}/001.vob + + # read main movie off the DVD + d2v_mesg "${MESG_03[$LNG]} TITEL: $TITLE NUM: $TITLENEM AUDIO: $TCEXTRACTOPTAUDIO" + + d2v_log "`echo && echo \$\> $TCCAT_BIN -t dvd -i $DVD_DEVICE \ + -T $TITLENUM,-1 -L 2\> /dev/null \> ${TEMPDIR}/001.vob`" + nice -n ${PRIO} $TCCAT_BIN -t dvd -i $DVD_DEVICE -T $TITLENUM,-1 \ + -L 2> /dev/null > ${TEMPDIR}/001.vob + + local STATUS=$? + if [ $STATUS -eq 1 ] ; then + d2v_mesg "${MESG_07[$LNG]}" + cp $LOGFILE ${TEMPDIR}/$TITLE.log + d2v_error "${MAGENTA}$TCCAT_BIN ${RED}failed - exiting${NORMAL}" + fi + + # eject DVD + d2v_mesg "${MESG_08[$LNG]}" + $EJECT_BIN $DVD_DEVICE + sleep $SLEEPTIME + + d2v_log "`echo && echo \$\> ls -l ${TEMPDIR} && ls -l ${TEMPDIR}`" + + if [ $AUDIOFORMAT = "mp3" ] ; then + d2v_log "`echo && echo \$\> mv ${TEMPDIR}/001.vob \ + ${TEMPDIR}/001.mpeg`" && \ + mv ${TEMPDIR}/001.vob ${TEMPDIR}/001.mpeg + d2v_log "`echo && echo \$\> ls -l ${TEMPDIR} && ls -l ${TEMPDIR}`" + fi + if [ $AUDIOFORMAT = "other" -a "$TCEXTRACTOPTAUDIO" = "mp2" ] ; then + d2v_log "cho && echo \$\> mv ${TEMPDIR}/001.vob \ + ${TEMPDIR}/001.mpeg" && \ + mv ${TEMPDIR}/001.vob ${TEMPDIR}/001.mpeg + d2v_log "cho && echo \$\> ls -l ${TEMPDIR} && ls -l ${TEMPDIR}" + fi + + + fi +} + + +########################################################################### +# demultiplex the main movie in mpv and ac3 +########################################################################### + +demux () { + d2v_log_separator + d2v_log_force \ + "using '$ACTION_DEMUX' to demultiplex the main movie in mpv and ac3" + + if [ ! -f ${TEMPDIR}/001.vob ] ; then + d2v_log "`echo && echo \$\> ls -l ${TEMPDIR} && ls -l ${TEMPDIR}`" + d2v_error "${MAGENTA}'${TEMPDIR}/001.vob' ${RED}not found${NORMAL}" + fi + + if [ ! -f ${TEMPDIR}/001.mpv -o ! -f ${TEMPDIR}/001.ac3 -o $FORCE -eq 1 ] ; then + + # clean up + [ -f ${TEMPDIR}/001.mpv ] && rm -f ${TEMPDIR}/001.mpv + [ -f ${TEMPDIR}/001.ac3 ] && rm -f ${TEMPDIR}/001.ac3 + rm -f ${TEMPDIR}/video.fifo + rm -f ${TEMPDIR}/audio.fifo + + local STATUS=1 + + if [ "$AUDIOFORMAT" != "mp3" ] ; then + case $ACTION_DEMUX in + ${DEMUX_TOOLS[0]}) + + # demux using fifos and tcextract + d2v_mesg "${MESG_10[$LNG]}" + mkfifo ${TEMPDIR}/video.fifo + mkfifo ${TEMPDIR}/audio.fifo + + d2v_log "`echo && echo \$\> $TCEXTRACT_BIN -i \ + ${TEMPDIR}/video.fifo -t vob -x mpeg2 -a 0xe0 \ + \> ${TEMPDIR}/001.mpv \&`" + + nice -n ${PRIO} $TCEXTRACT_BIN -i ${TEMPDIR}/video.fifo \ + -t vob -x mpeg2 -a 0xe0 \ + > ${TEMPDIR}/001.mpv & + + d2v_log "`echo && echo \$\> $TCEXTRACT_BIN -i \ + ${TEMPDIR}/audio.fifo -t vob -x ${TCEXTRACTOPTAUDIO} \ + -a $AUDIOTRACK \> ${TEMPDIR}/001.ac3 \&`" + nice -n ${PRIO} $TCEXTRACT_BIN -i ${TEMPDIR}/audio.fifo \ + -t vob -x ${TCEXTRACTOPTAUDIO} -a ${AUDIOTRACK} \ + > ${TEMPDIR}/001.ac3 & + + sleep 5 + d2v_log "`echo && echo \$\> cat ${TEMPDIR}/001.vob \| \ + tee ${TEMPDIR}/video.fifo ${TEMPDIR}/audio.fifo \ + \> /dev/null`" + nice -n ${PRIO} cat ${TEMPDIR}/001.vob | \ + tee ${TEMPDIR}/audio.fifo ${TEMPDIR}/video.fifo \ + > /dev/null + + STATUS=$? + ;; + ${DEMUX_TOOLS[1]}) + + if [ $WITHOUT_X -eq 0 ] ; then + # start virtual X server + $XVFB_BIN -once :4 >/dev/null 2>&1 & + export DISPLAY=localhost:4 + fi + + export LANG=de_DE@euro + + # demux using projectX + d2v_log "`echo && echo \$\> $JAVA_BIN -jar $PROJECTX_JAR \ + -c $PROJECTX_INI -o ${TEMPDIR} \ + ${TEMPDIR}/001.vob 2\>\&1 \>\> $LOGFILE`" + nice -n ${PRIO} $JAVA_BIN -jar $PROJECTX_JAR \ + -c $PROJECTX_INI -o ${TEMPDIR} \ + ${TEMPDIR}/001.vob 2>&1 >> $LOGFILE + + STATUS=$? + + if [ $WITHOUT_X -eq 0 ] ; then + # stop Virtual X server + /usr/bin/killall Xvfb + fi + ;; + esac + + if [ $STATUS -eq 1 ] ; then + d2v_mesg "${MESG_09[$LNG]}" + cp $LOGFILE ${TEMPDIR}/$TITLE.log + d2v_error "${MAGENTA}$ACTION_DEMUX ${RED}failed - exiting${NORMAL}" + fi + + d2v_log "`echo && echo \$\> ls -l ${TEMPDIR} && ls -l ${TEMPDIR}`" + else + d2v_log "demultiplexing not required - \ + main movie contains mp2 audio track" + fi + fi + [ $REMOVE -eq 1 ] && rm -f ${TEMPDIR}/001.vob +} + + +########################################################################### +# encode ac3 to mp2 +########################################################################### + +encode () { + d2v_log_separator + d2v_log_force \ + "using '$ACTION_ENCODE' to encode ac3 to mp2" + + if [ ! -f ${TEMPDIR}/001.ac3 ] ; then + d2v_log "`echo && echo \$\> ls -l ${TEMPDIR} && ls -l ${TEMPDIR}`" + d2v_error "${MAGENTA}'${TEMPDIR}/001.ac3' ${RED}not found${NORMAL}" + fi + + if [ ! -f ${TEMPDIR}/001.mp2 -o $FORCE -eq 1 ] ; then + + # clean up + [ -f ${TEMPDIR}/001.mp2 ] && rm -f ${TEMPDIR}/001.mp2 + + local STATUS=1 + + if [ "$AUDIOFORMAT" != "mp3" ] ; then + + if [ "$TCEXTRACTOPTAUDIO" = "pcm" ] ; then + d2v_log "pcm or raw audio track move to wav audio track" + mv ${TEMPDIR}/001.ac3 ${TEMPDIR}/001.wav + fi + + if [ "$TCEXTRACTOPTAUDIO" != "pcm" ] ; then + # encode with a52dec ... + d2v_log "`echo && echo \$\> $A52DEC_BIN -o wavdolby \ + -g "$A52DEC_GAIN" ${TEMPDIR}/001.ac3 \ + 2\>\&1 \> ${TEMPDIR}/001.wav \| grep -v \'last\' \ + \>\> $LOGFILE`" + nice -n ${PRIO} $A52DEC_BIN -o wavdolby \ + -g "$A52DEC_GAIN" ${TEMPDIR}/001.ac3 \ + 2>&1 > ${TEMPDIR}/001.wav | grep -v 'last' \ + >> $LOGFILE + STATUS=$? + if [ $STATUS -eq 1 ] ; then + d2v_mesg "${MESG_09[$LNG]}" + cp $LOGFILE ${TEMPDIR}/$TITLE.log + d2v_error "${MAGENTA}$A52DEC_BIN ${RED}failed - exiting${NORMAL}" + fi + fi + + d2v_log "`echo && echo \$\> ls -l ${TEMPDIR} && ls -l ${TEMPDIR}`" + + case $ACTION_ENCODE in + ${ENCODE_TOOLS[0]}) + + # ... and mp2enc + d2v_log "`echo && echo \$\> cat ${TEMPDIR}/001.wav \| \ + $MP2ENC_BIN -r 48000 -o ${TEMPDIR}/001.mp2 \ + \> /dev/null 2\>\> $LOGFILE`" + nice -n ${PRIO} cat ${TEMPDIR}/001.wav | \ + $MP2ENC_BIN -r 48000 -o ${TEMPDIR}/001.mp2 \ + > /dev/null 2>> $LOGFILE + STATUS=$? + ;; + ${ENCODE_TOOLS[1]}) + + # ... and toolame + d2v_log "`echo && echo \$\> cat ${TEMPDIR}/001.wav \| \ + $TOOLAME_BIN -s 48 /dev/stdin ${TEMPDIR}/001.mp2 \ + \> /dev/null 2\>\> $LOGFILE`" + nice -n ${PRIO} cat ${TEMPDIR}/001.wav | \ + $TOOLAME_BIN -s 48 /dev/stdin ${TEMPDIR}/001.mp2 \ + > /dev/null 2>> $LOGFILE + STATUS=$? + ;; + esac + + if [ $STATUS -eq 1 ] ; then + d2v_mesg "${MESG_09[$LNG]}" + cp $LOGFILE ${TEMPDIR}/$TITLE.log + d2v_error "${MAGENTA}$ACTION_ENCODE ${RED}failed - exiting${NORMAL}" + fi + + d2v_log "`echo && echo \$\> ls -l ${TEMPDIR} && ls -l ${TEMPDIR}`" + else + d2v_log "encoding not required - \ + main movie contains mp2 audio track" + fi + fi + [ $REMOVE -eq 1 ] && rm -f ${TEMPDIR}/001.wav +} + + +########################################################################### +# multiplex the parts to a VDR recording +########################################################################### + +mplex () { + d2v_log_separator + d2v_log_force \ + "using '$ACTION_MPLEX' to multiplex the part to a VDR recording" + + if [ ! -f ${TEMPDIR}/001.mpv ] ; then + d2v_log "`echo && echo \$\> ls -l ${TEMPDIR} && ls -l ${TEMPDIR}`" + d2v_error "${MAGENTA}'${TEMPDIR}/001.mpv' ${RED}not found${NORMAL}" + fi + + if [ ! -f ${TEMPDIR}/001.ac3 ] ; then + d2v_log "`echo && echo \$\> ls -l ${TEMPDIR} && ls -l ${TEMPDIR}`" + d2v_error "${MAGENTA}'${TEMPDIR}/001.ac3' ${RED}not found${NORMAL}" + fi + + if [ ! -f ${TEMPDIR}/001.mp2 ] ; then + d2v_log "`echo && echo \$\> ls -l ${TEMPDIR} && ls -l ${TEMPDIR}`" + d2v_error "${MAGENTA}'${TEMPDIR}/001.mp2' ${RED}not found${NORMAL}" + fi + + if [ ! -f ${TEMPDIR}/001.mpeg -o $FORCE -eq 1 ] ; then + + # clean up + [ -f ${TEMPDIR}/001.mpeg ] && rm -f ${TEMPDIR}/001.mpeg + + if [ "$AUDIOFORMAT" != "mp3" ] ; then + + local STATUS=1 + + d2v_mesg "${MESG_11[$LNG]}" + + case $ACTION_MPLEX in + ${MPLEX_TOOLS[0]}) + [ $AC3_TRACK -eq 1 ] && \ + INC_AC3_TRACK="-s ${TEMPDIR}/001.ac3" + + # tcmplex a MPEG file + d2v_log "`echo && echo \$\> $TCMPLEX_BIN -m 2 \ + -i ${TEMPDIR}/001.mpv -p ${TEMPDIR}/001.mp2 \ + $INC_AC3_TRACK -o ${TEMPDIR}/001.mpeg \ + 2\>\&1 \| grep -v \'%\' - \>\> $LOGFILE`" + nice -n ${PRIO} $TCMPLEX_BIN -m 2 \ + -i ${TEMPDIR}/001.mpv -p ${TEMPDIR}/001.mp2 \ + $INC_AC3_TRACK -o ${TEMPDIR}/001.mpeg \ + 2>&1 | grep -v '%' - >> $LOGFILE + STATUS=$? + ;; + ${MPLEX_TOOLS[1]}) + [ $AC3_TRACK -eq 1 ] && \ + INC_AC3_TRACK="-1 ${TEMPDIR}/001.ac3" + + # tcmplex-panteltje a MPEG file + d2v_log "`echo && echo \$\> $TCMPLEX_PANTELTJE_BIN -m 2 \ + -i ${TEMPDIR}/001.mpv -0 ${TEMPDIR}/001.mp2 \ + $INC_AC3_TRACK -o ${TEMPDIR}/001.mpeg \ + 2\>\&1 \| grep -v \'%\' - \>\> $LOGFILE`" + nice -n ${PRIO} $TCMPLEX_PANTELTJE_BIN -m 2 \ + -i ${TEMPDIR}/001.mpv -0 ${TEMPDIR}/001.mp2 \ + $INC_AC3_TRACK -o ${TEMPDIR}/001.mpeg \ + 2>&1 | grep -v '%' - >> $LOGFILE + STATUS=$? + ;; + ${MPLEX_TOOLS[2]}) + [ $AC3_TRACK -eq 1 ] && \ + INC_AC3_TRACK="${TEMPDIR}/001.ac3" + + # mplex a MPEG file + d2v_log "`echo && echo \$\> $MPLEX_BIN -f 9 \ + ${TEMPDIR}/001.mpv ${TEMPDIR}/001.mp2 \ + $INC_AC3_TRACK -o ${TEMPDIR}/001.mpeg \ + 2\>\&1 \| grep -v \'%\' - \>\> $LOGFILE`" + nice -n ${PRIO} $TCMPLEX_BIN -f 9 \ + ${TEMPDIR}/001.mpv ${TEMPDIR}/001.mp2 \ + $INC_AC3_TRACK -o ${TEMPDIR}/001.mpeg \ + 2>&1 | grep -v '%' - >> $LOGFILE + STATUS=$? + ;; + esac + + if [ $STATUS -eq 1 ] ; then + d2v_mesg "${MESG_09[$LNG]}" + cp $LOGFILE ${TEMPDIR}/$TITLE.log + d2v_error "${MAGENTA}$ACTION_MPLEX ${RED}failed - exiting${NORMAL}" + fi + + d2v_log "`echo && echo \$\> ls -l ${TEMPDIR} && ls -l ${TEMPDIR}`" + else + d2v_log "multiplexing not required - \ + main movie contains mp2 audio track" + fi + fi + [ $REMOVE -eq 1 ] && rm -f ${TEMPDIR}/001.mpv ${TEMPDIR}/001.ac3 ${TEMPDIR}/001.mp2 +} + + +########################################################################### +# split the VDR recording into chunks +########################################################################### + +split () { + d2v_log_separator + d2v_log_force \ + "using '$ACTION_SPLIT' to split the VDR recording into chunks" + + d2v_mesg "${MESG_12[$LNG]}" + + if [ ! -f ${TEMPDIR}/001.mpeg ] ; then + d2v_log "`echo && echo \$\> ls -l ${TEMPDIR} && ls -l ${TEMPDIR}`" + d2v_error "${MAGENTA}'${TEMPDIR}/001.mpeg' ${RED}not found${NORMAL}" + fi + + if [ ! -f ${TEMPDIR}/001.vdr -o $FORCE -eq 1 ] ; then + + # clean up + [ -f ${TEMPDIR}/002.vdr ] && rm -f ${TEMPDIR}/???.vdr + [ -f ${TEMPDIR}/001.mpeg.* ] && rm -f ${TEMPDIR}/001.mpeg.* + + local FILESIZE=`ls -l ${TEMPDIR}/001.mpeg | awk '{print $5}'` + + if [ $FILESIZE -gt $RECORDING_MAX_SIZE ] ; then + d2v_log "`echo && echo \$\> $SPLIT_BIN -b $RECORDING_MAX_SIZE \ + ${TEMPDIR}/001.mpeg ${TEMPDIR}/001.vdr.`" + nice -n ${PRIO} $SPLIT_BIN -b $RECORDING_MAX_SIZE \ + ${TEMPDIR}/001.mpeg ${TEMPDIR}/001.mpeg. + + local STATUS=$? + if [ $STATUS -eq 1 ] ; then + d2v_mesg "${MESG_09[$LNG]}" + cp $LOGFILE ${TEMPDIR}/$TITLE.log + d2v_error "${MAGENTA}$ACTION_SPLIT ${RED}failed - exiting${NORMAL}" + fi + + d2v_log "`echo && echo \$\> ls -l ${TEMPDIR} && \ + ls -l ${TEMPDIR}`" + + local NEWNAME=0 + for DNAME in ${TEMPDIR}/001.mpeg.* ; do + NEWNAME=`echo $NEWNAME | awk '{printf "%03d",$1+1}'` + mv $DNAME ${TEMPDIR}/$NEWNAME.vdr + + if [ $NEWNAME -gt $RECORDING_MAX_CHUNKS ] ; then + d2v_mesg "${MESG_09[$LNG]}" + cp $LOGFILE ${TEMPDIR}/$TITLE.log + d2v_error "${MAGENTA}$RECORDING_MAX_CHUNKS ${RED}to many chunks - exiting${NORMAL}" + fi + done + else + mv ${TEMPDIR}/001.mpeg ${TEMPDIR}/001.vdr + fi + fi + + d2v_log "`echo && echo \$\> ls -l ${TEMPDIR} && ls -l ${TEMPDIR}`" +} + + +########################################################################### +# create an index.vdr +########################################################################### + +genindex () { + d2v_log_separator + d2v_log_force \ + "using '$ACTION_GENINDEX' to create an index.vdr" + + if [ ! -f ${TEMPDIR}/001.vdr ] ; then + d2v_log "`echo && echo \$\> ls -l ${TEMPDIR} && ls -l ${TEMPDIR}`" + d2v_error "${MAGENTA}'${TEMPDIR}/001.vdr' ${RED}not found${NORMAL}" + fi + + if [ ! -f ${TEMPDIR}/index.vdr -o $FORCE -eq 1 ] ; then + + # clean up + [ -f ${TEMPDIR}/index.vdr ] && rm -f ${TEMPDIR}/index.vdr + + cd ${TEMPDIR} + + case $ACTION_GENINDEX in + ${GENINDEX_TOOLS[0]}) + d2v_log "`echo && echo \$\> $GENINDEX_BIN 2\>\&1 \| \ + grep -v \'%\' - \>\> $LOGFILE`" + nice -n ${PRIO} $GENINDEX_BIN 2>&1 | \ + grep -v '%' - >> $LOGFILE + ;; + ${GENINDEX_TOOLS[1]}) + d2v_log "`echo && echo \$\> $GENINDEX_MJPEGFIX_BIN 2\>\&1 \| \ + grep -v \'I-Frame\' - \>\> $LOGFILE`" + nice -n ${PRIO} $GENINDEX_MJPEGFIX_BIN 2>&1 | \ + grep -v 'I-Frame' - >> $LOGFILE + ;; + esac + fi + + d2v_log "`echo && echo \$\> ls -l ${TEMPDIR} && ls -l ${TEMPDIR}`" +} + + +########################################################################### +# move recording to video directory +########################################################################### + +move () { + d2v_log_separator + d2v_log_force \ + "using 'mv' to move recording to video directory" + + mkdir -p ${VIDEODIR}/${TITLE}/${RECORDING} >> $LOGFILE || \ + d2v_error "${RED}failed to create ${MAGENTA}'${VIDEODIR}/${TITLE}/${RECORDING}'${NORMAL}" + d2v_log "'${VIDEODIR}/${TITLE}/${RECORDING}' created" + + mv ${TEMPDIR}/*.vdr ${VIDEODIR}/${TITLE}/${RECORDING} + + d2v_log "`echo && echo \$\> ls -l ${TEMPDIR} && ls -l ${TEMPDIR}`" + d2v_log "`echo && echo \$\> ls -l ${VIDEODIR}/${TITLE}/${RECORDING} && \ + ls -l ${VIDEODIR}/${TITLE}/${RECORDING}`" +} + + +########################################################################### +# do all the bits +########################################################################### + +if [ $ACTION = "copy" ] ; then + gettitle + test + eval $ACTION +fi + + +if [ $ACTION = "all" ] ; then + readvars + gettitle + test + copy + if [ "$AUDIOFORMAT" = "mp3" ] ; then + split + genindex + move + elif [ "$AUDIOFORMAT" = "other" -a "$TCEXTRACTOPTAUDIO" = "mp2" ] ; then + split + genindex + move + else + demux + encode + mplex + split + genindex + move + fi +fi + +writevars + + +########################################################################### +# yeeha, we did it +########################################################################### + +[ $ACTION = "all" -a $CLEAN = 1 ] && rm -rf $TEMPDIR && d2v_log "\$TEMPDIR '$TEMPDIR' deleted" + +rm -f $LOCKFILE + +d2v_log_separator +d2v_log_force END +d2v_log_separator diff --git a/dvdauthor_helperfunctions.sh b/dvdauthor_helperfunctions.sh new file mode 100755 index 0000000..10f6855 --- /dev/null +++ b/dvdauthor_helperfunctions.sh @@ -0,0 +1,86 @@ +#!/bin/sh +# +# (P) & (C) 2003 by Dr. Peter Bieringer +# +# Original site of publishing: +# ftp://ftp.bieringer.de/pub/linux/dvd/dvdauthor-addons/ +# +# License: GPLv2 +# +# Requires: +# - gozer, imlib2, netpbm-progs +# +# ChangeLog +# 20030510/PB: initial creation +# 20030511/PB: import info function + +. ~/.vdrconvert/vdrconvert.env + +##### Functions ###### + +# Put text into a bitmap +put_text() { + local file="$1"; shift + if [ ! -z "$PATH_FONTS" -a ! -z "$DVD_USE_FONT" ] + then + local font="$1" + shift + fi + local color_bg="$1"; shift + local color_fg="$1"; shift + local loc_x="$1"; shift + local loc_y="$1"; shift + local text="$1"; shift + local rest="$*" + + local tmp_png="tmp-txt.png" + local tmp_pnm="tmp-txt.pnm" + local tmp_alphapnm="tmp-txt.alpha.pnm" + local tmp_output="tmp-output.pnm" + if [ ! -w "." ]; then + echo "ERR(put_text): file not writable: $file" + return 1 + fi + + [ ! -z "$RECODE" ] && rtext="`echo $text | $RECODE`" || rtext=$text + if [ -z "$PATH_FONTS" -o -z "$DVD_USE_FONT" ] + then + #set -x + gozer --background $color_bg --foreground $color_fg --text "$rtext" $rest $tmp_png + else + gozer --fontpath $PATH_FONTS --font $font --background $color_bg --foreground $color_fg --text "$rtext" $rest $tmp_png + #set +x + fi + + pngtopnm $tmp_png >$tmp_pnm + pngtopnm -alpha $tmp_png >$tmp_alphapnm + + pnmcomp -xoff=$loc_x -yoff=$loc_y -alpha=$tmp_alphapnm $tmp_pnm $file >$tmp_output + mv $tmp_output $file + + rm -f $tmp_png $tmp_pnm $tmp_alphapnm $tmp_output +} + +# Put a bitmap file into another bitmap file +put_file() { + local file=$1 + local loc_x=$2 + local loc_y=$3 + local file2=$4 + + local tmp_pnm="tmp-txt.pnm" + + if [ ! -w "." ]; then + echo "ERR(put_file): file not writable: $file" + return 1 + fi + if [ ! -r "$file2" ]; then + echo "ERR(put_file): file not readable: $file2" + return 1 + fi + + pnmcomp -xoff=$loc_x -yoff=$loc_y $file2 $file >$tmp_pnm + mv $tmp_pnm $file + + rm -f $tmp_pnm +} diff --git a/dvddirdel b/dvddirdel new file mode 100755 index 0000000..42a3a43 --- /dev/null +++ b/dvddirdel @@ -0,0 +1,41 @@ +#!/bin/sh + +if [ -f /usr/local/etc/dvdauthor.conf ]; then + . /usr/local/etc/dvdauthor.conf +fi + +if [ -f ~/.dvdauthorrc ]; then + . ~/.dvdauthorrc +fi + +help=0 +out=0 +for i in "$@"; do + if [ $out = 1 ]; then + WORKDIR="$i" + out=0 + elif [ "x$i" = "x-h" ]; then + help=1 + elif [ "x$i" = "x-o" ]; then + out=1 + fi +done + +if [ $help = 1 -o "x$WORKDIR" = "x" ]; then + echo "DVDAuthor, version 0.6.18. Send bugs to " + echo "syntax: dvddirdel [-o DIR]" + echo " deletes a previously authored DVD directory structure in DIR" + exit 1 +fi + +if [ -d "$WORKDIR" ]; then + rm -f "$WORKDIR/VIDEO_TS"/VIDEO_TS.VOB + rm -f "$WORKDIR/VIDEO_TS"/VIDEO_TS.IFO + rm -f "$WORKDIR/VIDEO_TS"/VIDEO_TS.BUP + rm -f "$WORKDIR/VIDEO_TS"/VTS_??_?.VOB + rm -f "$WORKDIR/VIDEO_TS"/VTS_??_0.IFO + rm -f "$WORKDIR/VIDEO_TS"/VTS_??_0.BUP + rmdir "$WORKDIR/VIDEO_TS" + rmdir "$WORKDIR/AUDIO_TS" + rmdir "$WORKDIR" +fi diff --git a/dvdunauthor b/dvdunauthor new file mode 100755 index 0000000..048da77 Binary files /dev/null and b/dvdunauthor differ diff --git a/fv_html b/fv_html new file mode 100755 index 0000000..b718d4a --- /dev/null +++ b/fv_html @@ -0,0 +1,5 @@ +#!/bin/bash + +arg=$1 + +/home/marc/bin/fv $1 | awk '{printf("

%s

\n", $0);}' diff --git a/getrecnames.sh b/getrecnames.sh new file mode 100644 index 0000000..fb5fd77 --- /dev/null +++ b/getrecnames.sh @@ -0,0 +1,18 @@ + +hd=/media/test +videodir=/video/ + +recdirs=$(find . -name "*.rec") + +echo $recdirs +for i in $recdirs +do + echo rec:$i + recdir=$(basename "$i") + dirv=$(find $videodir -name "$recdir") + d=$(echo $dirv | awk -F/ '{print $(NF-1)}') + echo "$dirv = $d" + mkdir -p $hd/$d + mv $i $hd/$d + +done diff --git a/git-prompt.sh b/git-prompt.sh new file mode 100755 index 0000000..41aa587 --- /dev/null +++ b/git-prompt.sh @@ -0,0 +1,707 @@ + + # don't set prompt if this is not interactive shell + [[ $- != *i* ]] && return + +################################################################### CONFIG + + ##### read config file if any. + + unset dir_color rc_color user_id_color root_id_color init_vcs_color clean_vcs_color + unset modified_vcs_color added_vcs_color addmoded_vcs_color untracked_vcs_color op_vcs_color detached_vcs_color hex_vcs_color + unset rawhex_len + + conf=git-prompt.conf; [[ -r $conf ]] && . $conf + conf=/etc/git-prompt.conf; [[ -r $conf ]] && . $conf + conf=~/.git-prompt.conf; [[ -r $conf ]] && . $conf + conf=~/.config/git-prompt.conf; [[ -r $conf ]] && . $conf + unset conf + + + ##### set defaults if not set + + git_module=${git_module:-on} + svn_module=${svn_module:-off} + hg_module=${hg_module:-on} + vim_module=${vim_module:-on} + error_bell=${error_bell:-off} + cwd_cmd=${cwd_cmd:-\\w} + + + #### dir, rc, root color + cols=`tput colors` # in emacs shell-mode tput colors returns -1 + if [[ -n "$cols" && $cols -ge 8 ]]; then # if terminal supports colors + dir_color=${dir_color:-CYAN} + rc_color=${rc_color:-red} + user_id_color=${user_id_color:-blue} + root_id_color=${root_id_color:-magenta} + else # only B/W + dir_color=${dir_color:-bw_bold} + rc_color=${rc_color:-bw_bold} + fi + unset cols + + #### prompt character, for root/non-root + prompt_char=${prompt_char:-'>'} + root_prompt_char=${root_prompt_char:-'>'} + + #### vcs colors + init_vcs_color=${init_vcs_color:-WHITE} # initial + clean_vcs_color=${clean_vcs_color:-blue} # nothing to commit (working directory clean) + modified_vcs_color=${modified_vcs_color:-red} # Changed but not updated: + added_vcs_color=${added_vcs_color:-green} # Changes to be committed: + addmoded_vcs_color=${addmoded_vcs_color:-yellow} + untracked_vcs_color=${untracked_vcs_color:-BLUE} # Untracked files: + op_vcs_color=${op_vcs_color:-MAGENTA} + detached_vcs_color=${detached_vcs_color:-RED} + + hex_vcs_color=${hex_vcs_color:-BLACK} # gray + + + max_file_list_length=${max_file_list_length:-100} + short_hostname=${short_hostname:-off} + upcase_hostname=${upcase_hostname:-on} + count_only=${count_only:-off} + rawhex_len=${rawhex_len:-5} + + aj_max=20 + + +##################################################################### post config + + ################# make PARSE_VCS_STATUS + unset PARSE_VCS_STATUS + [[ $git_module = "on" ]] && type git >&/dev/null && PARSE_VCS_STATUS+="parse_git_status" + [[ $svn_module = "on" ]] && type svn >&/dev/null && PARSE_VCS_STATUS+="${PARSE_VCS_STATUS+||}parse_svn_status" + [[ $hg_module = "on" ]] && type hg >&/dev/null && PARSE_VCS_STATUS+="${PARSE_VCS_STATUS+||}parse_hg_status" + PARSE_VCS_STATUS+="${PARSE_VCS_STATUS+||}return" + ################# terminfo colors-16 + # + # black? 0 8 + # red 1 9 + # green 2 10 + # yellow 3 11 + # blue 4 12 + # magenta 5 13 + # cyan 6 14 + # white 7 15 + # + # terminfo setaf/setab - sets ansi foreground/background + # terminfo sgr0 - resets all attributes + # terminfo colors - number of colors + # + ################# Colors-256 + # To use foreground and background colors: + # Set the foreground color to index N: \033[38;5;${N}m + # Set the background color to index M: \033[48;5;${M}m + # To make vim aware of a present 256 color extension, you can either set + # the $TERM environment variable to xterm-256color or use vim's -T option + # to set the terminal. I'm using an alias in my bashrc to do this. At the + # moment I only know of two color schemes which is made for multi-color + # terminals like urxvt (88 colors) or xterm: inkpot and desert256, + + ### if term support colors, then use color prompt, else bold + + black='\['`tput sgr0; tput setaf 0`'\]' + red='\['`tput sgr0; tput setaf 1`'\]' + green='\['`tput sgr0; tput setaf 2`'\]' + yellow='\['`tput sgr0; tput setaf 3`'\]' + blue='\['`tput sgr0; tput setaf 4`'\]' + magenta='\['`tput sgr0; tput setaf 5`'\]' + cyan='\['`tput sgr0; tput setaf 6`'\]' + white='\['`tput sgr0; tput setaf 7`'\]' + + BLACK='\['`tput setaf 0; tput bold`'\]' + RED='\['`tput setaf 1; tput bold`'\]' + GREEN='\['`tput setaf 2; tput bold`'\]' + YELLOW='\['`tput setaf 3; tput bold`'\]' + BLUE='\['`tput setaf 4; tput bold`'\]' + MAGENTA='\['`tput setaf 5; tput bold`'\]' + CYAN='\['`tput setaf 6; tput bold`'\]' + WHITE='\['`tput setaf 7; tput bold`'\]' + + dim='\['`tput sgr0; tput setaf p1`'\]' # half-bright + + bw_bold='\['`tput bold`'\]' + + on='' + off=': ' + bell="\[`eval ${!error_bell} tput bel`\]" + colors_reset='\['`tput sgr0`'\]' + + # replace symbolic colors names to raw treminfo strings + init_vcs_color=${!init_vcs_color} + modified_vcs_color=${!modified_vcs_color} + untracked_vcs_color=${!untracked_vcs_color} + clean_vcs_color=${!clean_vcs_color} + added_vcs_color=${!added_vcs_color} + op_vcs_color=${!op_vcs_color} + addmoded_vcs_color=${!addmoded_vcs_color} + detached_vcs_color=${!detached_vcs_color} + hex_vcs_color=${!hex_vcs_color} + + unset PROMPT_COMMAND + + ####### work around for MC bug. + ####### specifically exclude emacs, want full when running inside emacs + if [[ -z "$TERM" || ("$TERM" = "dumb" && -z "$INSIDE_EMACS") || -n "$MC_SID" ]]; then + unset PROMPT_COMMAND + PS1="\w$prompt_char " + return 0 + fi + + #################################################################### MARKERS + screen_marker="sCRn" + if [[ $LC_CTYPE =~ "UTF" && $TERM != "linux" ]]; then + elipses_marker="…" + else + elipses_marker="..." + fi + + export who_where + + +cwd_truncate() { + # based on: https://www.blog.montgomerie.net/pwd-in-the-title-bar-or-a-regex-adventure-in-bash + + # arg1: max path lenght + # returns abbrivated $PWD in public "cwd" var + + cwd=${PWD/$HOME/\~} # substitute "~" + + case $1 in + full) + return + ;; + last) + cwd=${PWD##/*/} + [[ $PWD == $HOME ]] && cwd="~" + return + ;; + *) + # if bash < v3.2 then don't truncate + if [[ ${BASH_VERSINFO[0]} -eq 3 && ${BASH_VERSINFO[1]} -le 1 || ${BASH_VERSINFO[0]} -lt 3 ]] ; then + return + fi + ;; + esac + + # split path into: head='~/', truncateble middle, last_dir + + local cwd_max_length=$1 + # expression which bash-3.1 or older can not understand, so we wrap it in eval + exp31='[[ "$cwd" =~ (~?/)(.*/)([^/]*)$ ]]' + if eval $exp31 ; then # only valid if path have more then 1 dir + local path_head=${BASH_REMATCH[1]} + local path_middle=${BASH_REMATCH[2]} + local path_last_dir=${BASH_REMATCH[3]} + + local cwd_middle_max=$(( $cwd_max_length - ${#path_last_dir} )) + [[ $cwd_middle_max < 0 ]] && cwd_middle_max=0 + + + # trunc middle if over limit + if [[ ${#path_middle} -gt $(( $cwd_middle_max + ${#elipses_marker} + 5 )) ]]; then + + # truncate + middle_tail=${path_middle:${#path_middle}-${cwd_middle_max}} + + # trunc on dir boundary (trunc 1st, probably tuncated dir) + exp31='[[ $middle_tail =~ [^/]*/(.*)$ ]]' + eval $exp31 + middle_tail=${BASH_REMATCH[1]} + + # use truncated only if we cut at least 4 chars + if [[ $(( ${#path_middle} - ${#middle_tail})) -gt 4 ]]; then + cwd=$path_head$elipses_marker$middle_tail$path_last_dir + fi + fi + fi + return + } + + +set_shell_label() { + + xterm_label() { + local args="$*" + echo -n "]2;${args:0:200}" ; # FIXME: replace hardcodes with terminfo codes + } + + screen_label() { + # FIXME: run this only if screen is in xterm (how to test for this?) + xterm_label "$screen_marker $plain_who_where $@" + + # FIXME $STY not inherited though "su -" + [ "$STY" ] && screen -S $STY -X title "$*" + } + if [[ -n "$STY" ]]; then + screen_label "$*" + else + case $TERM in + + screen*) + screen_label "$*" + ;; + + xterm* | rxvt* | gnome-terminal | konsole | eterm | wterm ) + # is there a capability which we can to test + # for "set term title-bar" and its escapes? + xterm_label "$plain_who_where $@" + ;; + + *) + ;; + esac + fi + } + + export -f set_shell_label + +###################################################### ID (user name) + id=`id -un` + id=${id#$default_user} + +########################################################### TTY + tty=`tty` + tty=`echo $tty | sed "s:/dev/pts/:p:; s:/dev/tty::" ` # RH tty devs + tty=`echo $tty | sed "s:/dev/vc/:vc:" ` # gentoo tty devs + + if [[ "$TERM" = "screen" ]] ; then + + # [ "$WINDOW" = "" ] && WINDOW="?" + # + # # if under screen then make tty name look like s1-p2 + # # tty="${WINDOW:+s}$WINDOW${WINDOW:+-}$tty" + # tty="${WINDOW:+s}$WINDOW" # replace tty name with screen number + tty="$WINDOW" # replace tty name with screen number + fi + + # we don't need tty name under X11 + case $TERM in + xterm* | rxvt* | gnome-terminal | konsole | eterm* | wterm | cygwin) unset tty ;; + *);; + esac + + dir_color=${!dir_color} + rc_color=${!rc_color} + user_id_color=${!user_id_color} + root_id_color=${!root_id_color} + + ########################################################### HOST + ### we don't display home host/domain $SSH_* set by SSHD or keychain + + # How to find out if session is local or remote? Working with "su -", ssh-agent, and so on ? + + ## is sshd our parent? + # if { for ((pid=$$; $pid != 1 ; pid=`ps h -o pid --ppid $pid`)); do ps h -o command -p $pid; done | grep -q sshd && echo == REMOTE ==; } + #then + + host=${HOSTNAME} + if [[ $short_hostname = "on" ]]; then + host=`hostname -s` + fi + host=${host#$default_host} + uphost=`echo ${host} | tr a-z A-Z` + if [[ $upcase_hostname = "on" ]]; then + host=${uphost} + fi + + host_color=${uphost}_host_color + host_color=${!host_color} + if [[ -z $host_color && -x /usr/bin/cksum ]] ; then + cksum_color_no=`echo $uphost | cksum | awk '{print $1%7}'` + color_index=(green yellow blue magenta cyan white) # FIXME: bw, color-256 + host_color=${color_index[cksum_color_no]} + fi + + host_color=${!host_color} + + # we might already have short host name + host=${host%.$default_domain} + +#################################################################### WHO_WHERE + # [[user@]host[-tty]] + + if [[ -n $id || -n $host ]] ; then + [[ -n $id && -n $host ]] && at='@' || at='' + color_who_where="${id}${host:+$host_color$at$host}${tty:+ $tty}" + plain_who_where="${id}$at$host" + + # add trailing " " + color_who_where="$color_who_where " + plain_who_where="$plain_who_where " + + # if root then make it root_color + if [ "$id" == "root" ] ; then + user_id_color=$root_id_color + prompt_char="$root_prompt_char" + fi + color_who_where="$user_id_color$color_who_where$colors_reset" + else + color_who_where='' + fi + + +parse_svn_status() { + + [[ -d .svn ]] || return 1 + + vcs=svn + + ### get rev + eval ` + svn info | + sed -n " + s@^URL[^/]*//@repo_dir=@p + s/^Revision: /rev=/p + " + ` + ### get status + + unset status modified added clean init added mixed untracked op detached + eval `svn status 2>/dev/null | + sed -n ' + s/^A... \([^.].*\)/modified=modified; modified_files[${#modified_files[@]}]=\"\1\";/p + s/^M... \([^.].*\)/modified=modified; modified_files[${#modified_files[@]}]=\"\1\";/p + s/^\?... \([^.].*\)/untracked=untracked; untracked_files[${#untracked_files[@]}]=\"\1\";/p + ' + ` + # TODO branch detection if standard repo layout + + [[ -z $modified ]] && [[ -z $untracked ]] && clean=clean + vcs_info=svn:r$rev + } + +parse_hg_status() { + + # ☿ + + [[ -d ./.hg/ ]] || return 1 + + vcs=hg + + ### get status + unset status modified added clean init added mixed untracked op detached + + eval `hg status 2>/dev/null | + sed -n ' + s/^M \([^.].*\)/modified=modified; modified_files[${#modified_files[@]}]=\"\1\";/p + s/^A \([^.].*\)/added=added; added_files[${#added_files[@]}]=\"\1\";/p + s/^R \([^.].*\)/added=added;/p + s/^! \([^.].*\)/modified=modified;/p + s/^? \([^.].*\)/untracked=untracked; untracked_files[${#untracked_files[@]}]=\\"\1\\";/p + '` + + branch=`hg branch 2> /dev/null` + + [[ -z $modified ]] && [[ -z $untracked ]] && [[ -z $added ]] && clean=clean + vcs_info=${branch/default/D} + } + + + +parse_git_status() { + + # TODO add status: LOCKED (.git/index.lock) + + git_dir=`[[ $git_module = "on" ]] && git rev-parse --git-dir 2> /dev/null` + #git_dir=`eval \$$git_module git rev-parse --git-dir 2> /dev/null` + #git_dir=` git rev-parse --git-dir 2> /dev/null` + + [[ -n ${git_dir/./} ]] || return 1 + + vcs=git + + ########################################################## GIT STATUS + file_regex='\([^/ ]*\/\{0,1\}\).*' + added_files=() + modified_files=() + untracked_files=() + freshness="$dim" + unset branch status modified added clean init added mixed untracked op detached + + # quoting hell + eval " $( + git status 2>/dev/null | + sed -n ' + s/^# On branch /branch=/p + s/^nothing to commi.*/clean=clean/p + s/^# Initial commi.*/init=init/p + + s/^# Your branch is ahead of .[/[:alnum:]]\+. by [[:digit:]]\+ commit.*/freshness=${WHITE}↑/p + s/^# Your branch is behind .[/[:alnum:]]\+. by [[:digit:]]\+ commit.*/freshness=${YELLOW}↓/p + s/^# Your branch and .[/[:alnum:]]\+. have diverged.*/freshness=${YELLOW}↕/p + + /^# Changes to be committed:/,/^# [A-Z]/ { + s/^# Changes to be committed:/added=added;/p + + s/^# modified: '"$file_regex"'/ [[ \" ${added_files[*]} \" =~ \" \1 \" ]] || added_files[${#added_files[@]}]=\"\1\"/p + s/^# new file: '"$file_regex"'/ [[ \" ${added_files[*]} \" =~ \" \1 \" ]] || added_files[${#added_files[@]}]=\"\1\"/p + s/^# renamed:[^>]*> '"$file_regex"'/ [[ \" ${added_files[*]} \" =~ \" \1 \" ]] || added_files[${#added_files[@]}]=\"\1\"/p + s/^# copied:[^>]*> '"$file_regex"'/ [[ \" ${added_files[*]} \" =~ \" \1 \" ]] || added_files[${#added_files[@]}]=\"\1\"/p + } + + /^# Changed but not updated:/,/^# [A-Z]/ { + s/^# Changed but not updated:/modified=modified;/p + s/^# modified: '"$file_regex"'/ [[ \" ${modified_files[*]} \" =~ \" \1 \" ]] || modified_files[${#modified_files[@]}]=\"\1\"/p + s/^# unmerged: '"$file_regex"'/ [[ \" ${modified_files[*]} \" =~ \" \1 \" ]] || modified_files[${#modified_files[@]}]=\"\1\"/p + } + + /^# Changes not staged for commit:/,/^# [A-Z]/ { + s/^# Changes not staged for commit:/modified=modified;/p + s/^# modified: '"$file_regex"'/ [[ \" ${modified_files[*]} \" =~ \" \1 \" ]] || modified_files[${#modified_files[@]}]=\"\1\"/p + s/^# unmerged: '"$file_regex"'/ [[ \" ${modified_files[*]} \" =~ \" \1 \" ]] || modified_files[${#modified_files[@]}]=\"\1\"/p + } + + /^# Unmerged paths:/,/^[^#]/ { + s/^# Unmerged paths:/modified=modified;/p + s/^# both modified:\s*'"$file_regex"'/ [[ \" ${modified_files[*]} \" =~ \" \1 \" ]] || modified_files[${#modified_files[@]}]=\"\1\"/p + } + + /^# Untracked files:/,/^[^#]/{ + s/^# Untracked files:/untracked=untracked;/p + s/^# '"$file_regex"'/ [[ \" ${untracked_files[*]} ${modified_files[*]} ${added_files[*]} \" =~ \" \1 \" ]] || untracked_files[${#untracked_files[@]}]=\"\1\"/p + } + ' + )" + + if ! grep -q "^ref:" $git_dir/HEAD 2>/dev/null; then + detached=detached + fi + + + ################# GET GIT OP + + unset op + + if [[ -d "$git_dir/.dotest" ]] ; then + + if [[ -f "$git_dir/.dotest/rebasing" ]] ; then + op="rebase" + + elif [[ -f "$git_dir/.dotest/applying" ]] ; then + op="am" + + else + op="am/rebase" + + fi + + elif [[ -f "$git_dir/.dotest-merge/interactive" ]] ; then + op="rebase -i" + # ??? branch="$(cat "$git_dir/.dotest-merge/head-name")" + + elif [[ -d "$git_dir/.dotest-merge" ]] ; then + op="rebase -m" + # ??? branch="$(cat "$git_dir/.dotest-merge/head-name")" + + # lvv: not always works. Should ./.dotest be used instead? + elif [[ -f "$git_dir/MERGE_HEAD" ]] ; then + op="merge" + # ??? branch="$(git symbolic-ref HEAD 2>/dev/null)" + + elif [[ -f "$git_dir/index.lock" ]] ; then + op="locked" + + else + [[ -f "$git_dir/BISECT_LOG" ]] && op="bisect" + # ??? branch="$(git symbolic-ref HEAD 2>/dev/null)" || \ + # branch="$(git describe --exact-match HEAD 2>/dev/null)" || \ + # branch="$(cut -c1-7 "$git_dir/HEAD")..." + fi + + + #### GET GIT HEX-REVISION + if [[ $rawhex_len -gt 0 ]] ; then + rawhex=`git rev-parse HEAD 2>/dev/null` + rawhex=${rawhex/HEAD/} + rawhex="=$hex_vcs_color${rawhex:0:$rawhex_len}" + else + rawhex="" + fi + + #### branch + branch=${branch/master/M} + + # another method of above: + # branch=$(git symbolic-ref -q HEAD || { echo -n "detached:" ; git name-rev --name-only HEAD 2>/dev/null; } ) + # branch=${branch#refs/heads/} + + ### compose vcs_info + + if [[ $init ]]; then + vcs_info=${white}init + + else + if [[ "$detached" ]] ; then + branch="/dev/null`" + + + elif [[ "$op" ]]; then + branch="$op:$branch" + if [[ "$op" == "merge" ]] ; then + branch+="<--$(git name-rev --name-only $(<$git_dir/MERGE_HEAD))" + fi + #branch="<$branch>" + fi + vcs_info="$branch$freshness$rawhex" + + fi + } + + +parse_vcs_status() { + + unset file_list modified_files untracked_files added_files + unset vcs vcs_info + unset status modified untracked added init detached + unset file_list modified_files untracked_files added_files + + [[ $vcs_ignore_dir_list =~ $PWD ]] && return + + eval $PARSE_VCS_STATUS + + + ### status: choose primary (for branch color) + unset status + status=${op:+op} + status=${status:-$detached} + status=${status:-$clean} + status=${status:-$modified} + status=${status:-$added} + status=${status:-$untracked} + status=${status:-$init} + # at least one should be set + : ${status?prompt internal error: git status} + eval vcs_color="\${${status}_vcs_color}" + # no def: vcs_color=${vcs_color:-$WHITE} # default + + + ### VIM + + if [[ $vim_module = "on" ]] ; then + # equivalent to vim_glob=`ls .*.vim` but without running ls + unset vim_glob vim_file vim_files + old_nullglob=`shopt -p nullglob` + shopt -s nullglob + vim_glob=`echo .*.sw?` + eval $old_nullglob + + if [[ $vim_glob ]]; then + set $vim_glob + #vim_file=${vim_glob#.} + if [[ $# > 1 ]] ; then + vim_files="*" + else + vim_file=${1#.} + vim_file=${vim_file/.sw?/} + [[ .${vim_file}.swp -nt $vim_file ]] && vim_files=$vim_file + fi + # if swap is newer, then this is unsaved vim session + # [temoto custom] if swap is older, then it must be deleted, so show all swaps. + fi + fi + + + ### file list + unset file_list + if [[ $count_only = "on" ]] ; then + [[ ${added_files[0]} ]] && file_list+=" "${added_vcs_color}+${#added_files[@]} + [[ ${modified_files[0]} ]] && file_list+=" "${modified_vcs_color}*${#modified_files[@]} + [[ ${untracked_files[0]} ]] && file_list+=" "${untracked_vcs_color}?${#untracked_files[@]} + else + [[ ${added_files[0]} ]] && file_list+=" "$added_vcs_color${added_files[@]} + [[ ${modified_files[0]} ]] && file_list+=" "$modified_vcs_color${modified_files[@]} + [[ ${untracked_files[0]} ]] && file_list+=" "$untracked_vcs_color${untracked_files[@]} + fi + [[ ${vim_files} ]] && file_list+=" "${MAGENTA}vim:${vim_files} + + if [[ ${#file_list} -gt $max_file_list_length ]] ; then + file_list=${file_list:0:$max_file_list_length} + if [[ $max_file_list_length -gt 0 ]] ; then + file_list="${file_list% *} $elipses_marker" + fi + fi + + + head_local="$vcs_color(${vcs_info}$vcs_color${file_list}$vcs_color)" + + ### fringes + head_local="${head_local+$vcs_color$head_local }" + #above_local="${head_local+$vcs_color$head_local\n}" + #tail_local="${tail_local+$vcs_color $tail_local}${dir_color}" + } + +disable_set_shell_label() { + trap - DEBUG >& /dev/null + } + +# show currently executed command in label +enable_set_shell_label() { + disable_set_shell_label + # check for BASH_SOURCE being empty, no point running set_shell_label on every line of .bashrc + trap '[[ -z "$BASH_SOURCE" && ($BASH_COMMAND != prompt_command_function) ]] && + set_shell_label $BASH_COMMAND' DEBUG >& /dev/null + } + +declare -ft disable_set_shell_label +declare -ft enable_set_shell_label + +# autojump (see http://wiki.github.com/joelthelion/autojump) + +# TODO reverse the line order of a file +#awk ' { line[NR] = $0 } +# END { for (i=NR;i>0;i--) +# print line[i] }' listlogs + +j (){ + : ${1? usage: j dir-beginning} + # go in ring buffer starting from current index. cd to first matching dir + for (( i=(aj_idx-1)%aj_max; i != aj_idx%aj_max; i=(--i+aj_max)%aj_max )) ; do + if [[ ${aj_dir_list[$i]} =~ ^.*/$1[^/]*$ ]] ; then + cd "${aj_dir_list[$i]}" + return + fi + done + echo '?' + } + +alias jumpstart='echo ${aj_dir_list[@]}' + +###################################################################### PROMPT_COMMAND + +prompt_command_function() { + rc="$?" + + if [[ "$rc" == "0" ]]; then + rc="" + else + rc="$rc_color$rc$colors_reset$bell " + fi + + cwd=${PWD/$HOME/\~} # substitute "~" + set_shell_label "${cwd##[/~]*/}/" # default label - path last dir + + parse_vcs_status + + # autojump + if [[ ${aj_dir_list[aj_idx%aj_max]} != $PWD ]] ; then + aj_dir_list[++aj_idx%aj_max]="$PWD" + fi + + # if cwd_cmd have back-slash, then assign it value to cwd + # else eval cwd_cmd, cwd should have path after exection + eval "${cwd_cmd/\\/cwd=\\\\}" + + PS1="$colors_reset$rc$head_local$color_who_where$dir_color$cwd$tail_local$dir_color$prompt_char $colors_reset" + + unset head_local tail_local pwd + } + + PROMPT_COMMAND=prompt_command_function + + enable_set_shell_label + + unset rc id tty modified_files file_list + +# vim: set ft=sh ts=8 sw=8 et: diff --git a/init-var-on-tmp.sh b/init-var-on-tmp.sh index 248e9b3..3bf02ea 100755 --- a/init-var-on-tmp.sh +++ b/init-var-on-tmp.sh @@ -4,7 +4,7 @@ set -x VARTEMP=/tmp/var VARPERSISTENT=/var -VARDIRS="cache" +VARDIRS="cache log/fhem" BINDDIRS="cache lock run" case $1 in @@ -14,7 +14,8 @@ case $1 in for f in $VARDIRS do - rsync -av $VARPERSISTENT/$f.bak/ $VARTEMP/$f + fbase=$(basename $f) + rsync -av $VARPERSISTENT/$fbase.bak/ $VARTEMP/$f done for f in $BINDDIRS @@ -27,7 +28,8 @@ case $1 in echo "saving var-directory from temp to flash" for f in $VARDIRS do - [ -d $VARTEMP/$f ] && rsync -av $VARTEMP/$f/ $VARPERSISTENT/$f.bak + fbase=$(basename $f) + [ -d $VARTEMP/$f ] && rsync -av $VARTEMP/$f/ $VARPERSISTENT/$fbase.bak done ;; esac diff --git a/instapaper_epub.sh b/instapaper_epub.sh new file mode 100644 index 0000000..c06d806 --- /dev/null +++ b/instapaper_epub.sh @@ -0,0 +1,10 @@ +#!/bin/bash +Username="MarcHoppe@gmx.de" +Password="insta0815" +Docs=~/Documents +OutputDir=~/Documents/ePub + +curl --cookie-jar ${Docs}/cjar --data "username=$Username" -d "password=${Password}" --output ${Docs}/insta.html http://www.instapaper.com/user/login +curl -b ${Docs}/cjar --output ${OutputDir}/insta.epub http://www.instapaper.com/epub +rm -f ${Docs}/cjar ${Docs}/insta.html + diff --git a/ipad.sh b/ipad.sh index 0bcb480..dc46e9d 100644 --- a/ipad.sh +++ b/ipad.sh @@ -1,3 +1,5 @@ +#!/bin/bash + ipaddir=/dat/ipad @@ -40,9 +42,9 @@ do done # Podcasts -filedir="/dat/mp3/podcast/cache" -dstdir=$ipaddir/ -ln -s $filedir $dstdir/podcast +#filedir="/dat/mp3/podcast/cache" +#dstdir=$ipaddir/ +#ln -s $filedir $dstdir/podcast # Musik linkdir=$ipaddir/music @@ -90,7 +92,7 @@ done dstdir=$ipaddir/bilder srcdir=/dat/bilder -#[ -d $dstdir ] || mkdir -p $dstdir +[ -d $dstdir ] || mkdir -p $dstdir cd $dstdir || exit [ "$dstdir" != "" ] && rm -r * @@ -99,6 +101,8 @@ find $srcdir -name ipad -print0 | while read -d $'\0' f do fileindir=$f linkdest=$(dirname "$fileindir") + echo "adding: $f" + ln -s "$linkdest" #[ -x "$artist/$album" ] || ln -s "$linkdest" "$artist/$album" done diff --git a/iso2utf.sh b/iso2utf.sh new file mode 100755 index 0000000..9ea2380 --- /dev/null +++ b/iso2utf.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +set -x + +file_iso=$1 +file_utf=${file_iso}.utf8 + +[ -f $file_iso ] || exit +iconv --from-code=ISO-8859-1 --to-code=UTF-8 $file_iso > $file_utf + diff --git a/m4a2ogg.sh b/m4a2ogg.sh new file mode 100644 index 0000000..e4ec7b8 --- /dev/null +++ b/m4a2ogg.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# +# m4a to ogg + +i=$1 + tmp=$(mktemp) + y=`echo "$i"|sed -e 's/.m4a/.ogg/'` + faad -i "$i" 1>/dev/null 2>"$tmp" + if [ $? -ne 0 ] ; then + rm "$tmp" + echo "failed to get information from $i" + continue + fi + title=`grep 'title: ' "$tmp"|sed -e 's/title: //'` + artist=`grep 'artist: ' "$tmp"|sed -e 's/artist: //'` + album=`grep 'album: ' "$tmp"|sed -e 's/album: //'` + genre=`grep 'genre: ' "$tmp"|sed -e 's/genre: //'` + track=`grep 'track: ' "$tmp"|sed -e 's/track: //'` + year=`grep 'year: ' "$tmp"|sed -e 's/date: //'` + faad "$i" -o - | oggenc -q 4 -t "$title" -a "$artist" -l "$album" -G "$genre" -N "$track" -d "$year" -o "$y" - + if [ $? -ne 0 ] ; then + echo "failed to encode $i" + fi + rm "$tmp" + diff --git a/mirrors.update b/mirrors.update new file mode 100644 index 0000000..904c335 --- /dev/null +++ b/mirrors.update @@ -0,0 +1,15 @@ +#!/bin/bash + +fhemdir=/home/marc/src/fhem +fhem_mirror=$fhemdir/fhem-git +myfhem=$fhemdir/my + +cd $fhem_mirror +git svn rebase +#git merge remotes/git-svn +git push github master +#cd $myfhem +#git fetch origin +#git push github master + + diff --git a/mkosm.sh b/mkosm.sh new file mode 100644 index 0000000..cdaf155 --- /dev/null +++ b/mkosm.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +set -x + +mapfile=$1 +splitter=../splitter.jar +mkgmap=../mkgmap.jar +mapid=65241345 +country_name=greece + +sudo swapon /dat/tmp/swap.img + + +#wget http://download.geofabrik.de/osm/europe/germany/$mapfile.bz2 +#bunzip $mapfile.bz2 + +mkdir tiles +rm -r tiles/* +cd tiles/ + +java -Xmx5000M -jar $splitter --mapid=$mapid --max-nodes=500000 ../$mapfile + +cd .. +mkdir gbasemap +rm -r gbasemap/* +cd gbasemap +java -Xmx5000M -jar $mkgmap --style-file=../styles/masterstyle --description='Openstreetmap' --country-name=$country_name --country-abbr=GR --family-id=3 --product-id=45 --series-name='master-edition' --family-name=OSM --area-name=GR --latin1 --lower-case --mapname=$mapid --draw-priority=10 --add-pois-to-areas --road-name-pois --net --route --gmapsupp ../tiles/*.osm.gz /home/marc/osm/styles/master.TYP + +sudo swapoff /dat/tmp/swap.img diff --git a/mkvdrrecdir.sh b/mkvdrrecdir.sh new file mode 100755 index 0000000..e57fff0 --- /dev/null +++ b/mkvdrrecdir.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +#set -x + +RECORDING_LIFETIME=99 +RECORDING="$(date +%Y-%m-%d.%H.%M).99.$RECORDING_LIFETIME.rec" +mkdir $RECORDING diff --git a/mp32wav b/mp32wav new file mode 100755 index 0000000..455d407 --- /dev/null +++ b/mp32wav @@ -0,0 +1,85 @@ +#!/bin/bash +# +# /usr/local/bin/mp3tocd -- mp3-Files nach wav oder au umwandeln +# und brennen. +# Das Format 44100 Hz, 16Bit Stereo ist notwendig, siehe Text +# +# mp32wav mp3dir wavdir + +set -x + +function usage () +{ + echo " +mp32wav mp3dir wavdir + mp3dir: Verzeichnis, in dem die mp3-Dateien gepseichert sind. + wavdir: Verzeichnis, in das die erzeugten wave-Dateien geschrieben werden" +} + +function yesno () +{ + while true; do + read ans + case "$ans" in + y|Y|j|J|[yY]es|[jJ]a) + return 1 + ;; + n|N|[nN]o|[nN]ein) + return 0 + ;; + *) + echo -e '\a\nVertipper. (j,ja,y,yes/n,nein,no)' + ;; + esac + done +} + +if ! test -d "$1"; then + usage +fi +if ! test -d "$2"; then + usage +fi + +mp3dir="$1" +wavdir="$2" + +#pushd $destdir > /dev/null +let count=0 + +for i in "$mp3dir"/*.mp3; do + echo "$i wird decodiert" + + ## Der Umstand mit der fuehrenden Null in der 'if'-Abfrage bewirkt, + ## dass (maximal) 100 Tracks in der richtigen Reihenfolge gebrannt + ## werden + + if test "$count" -le 9; then + track=""0$count"track.wav" + else + track=""$count"track.wav" + fi + trakfile="$i" + echo Datei1 "$trakfile" + track=$(basename "$i" .mp3).wav + echo Datei2 "$track" + + mpg123 -v -s -r 44100 --stereo --wav "$wavdir"/"$track" "$i" + + let count=$(expr $count + 1) +done + +echo -e "\n erzeugte Tracks:" +ls -l "$wavdir"/[0-9][0-9]*.wav +echo "KByte insgesamt: $(du -kc "$wavdir"/[0-9][0-9]*.wav | tail -n 1 | awk '{print $1}')" +#echo " +#Brennen durchfuehren (j,y,ja,yes/n,nein,no)?" + +#if ! yesno; then + #cdrecord -v -speed=$speed $blank -pad dev=$wdev -audio [0-9][0-9]track.$format + # popd > /dev/null +# rm -R $destdir +#else +# echo "Die Tracks in $destdir wurden nicht geloescht" +#fi + diff --git a/podcastupdate.sh b/podcastupdate.sh new file mode 100755 index 0000000..dee30fd --- /dev/null +++ b/podcastupdate.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +LOGFILE=/tmp/podcatcher.log +set -x +sleep +#swapon /dat/tmp/swap.img +svdrpsend MESG "Podcasts aktualisieren-gestarted" +cd /mp3/podcast +echo "start ----------------------------" >> $LOGFILE +date >> $LOGFILE +./catch.sh >> $LOGFILE 2>&1 +svdrpsend MESG "Podcasts aktualisiert" +#swapoff /dat/tmp/swap.img diff --git a/podcastupdated.sh b/podcastupdated.sh new file mode 100755 index 0000000..1eaa74d --- /dev/null +++ b/podcastupdated.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +echo "/usr/local/bin/podcastupdate.sh" | at now diff --git a/queue b/queue new file mode 100755 index 0000000..4de31de --- /dev/null +++ b/queue @@ -0,0 +1,16 @@ +#!/bin/bash + +qfile=/tmp/queue.commands + +if [ "$1" = "-list" ]; then + cat $qfile + exit +fi + +echo $* >> $qfile + +lines=$(cat $qfile | wc -l) + +if [ $lines -eq 1 ]; then + nohup /usr/local/bin/unqueue $qfile & +fi diff --git a/recwebradio.sh b/recwebradio.sh new file mode 100644 index 0000000..2f4fda9 --- /dev/null +++ b/recwebradio.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +t1=$1 +t2=$2 + diff --git a/rmdvbmodules.sh b/rmdvbmodules.sh new file mode 100644 index 0000000..a3ed50b --- /dev/null +++ b/rmdvbmodules.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +sudo rmmod budget_ci +sudo rmmod tda1004x +sudo rmmod dvb_ttpci +sudo rmmod stv0299 +sudo rmmod ves1x93 +sudo rmmod rc_hauppauge +sudo rmmod saa7146_vv +sudo rmmod videodev +sudo rmmod budget_core +sudo rmmod dvb_core +sudo rmmod v4l2_compat_ioctl32 +sudo rmmod videobuf_dma_sg +sudo rmmod saa7146 +sudo rmmod ttpci_eeprom +sudo rmmod v4l1_compat diff --git a/start_dropbox.sh b/start_dropbox.sh new file mode 100644 index 0000000..2e8ae6b --- /dev/null +++ b/start_dropbox.sh @@ -0,0 +1 @@ +HOME=/home/marc/.dropbox-ipad/ nohup .dropbox-dist/dropbox start diff --git a/sync_pod.pl b/sync_pod.pl new file mode 100755 index 0000000..49352b5 --- /dev/null +++ b/sync_pod.pl @@ -0,0 +1,862 @@ +#!/usr/bin/perl -w + +# (c) 2002 Armin Obersteiner +# License: GPL v2 + +use MP3::Info; +use Unicode::String qw( latin1 utf16 ); +use Shell qw ( find gzip ); +use Getopt::Std; +use File::Copy; +use Filesys::DiskFree; + +use Data::Dumper qw (Dumper); + +use strict; + +my $version="0.68"; + +# +# options & config +# + +my %opt; +getopts("fcnh",\%opt); + +if($opt{h}) { + print <<"EOF"; +$0 [-c] [-f] [Search Pattern 1] [Search Pattern 2] ... + + -c create: create directory structure on plain ipod before syncing + (default: you get a warning if there is no ipod structure) + + -f force: rename ipod and use it with $0 before syncing + (default: an unknown ipod stays untouched) + + -n name check: checks mp3 names for possible illegal characters + + Search Patterns: for each search pattern a playlist is created + (case insensitive) +EOF + exit; +} + +my $buffer = 5*1024*1024; # leave some MB free for iTunesDB + +my @required = qw ( SYNCMODE PLAYLISTDIR IPODDIR BACKUPDIR ); + +my $rc=readrc("$ENV{HOME}/.ipod/config",\@required); + +#print Dumper($rc); + + +# +# check ipod name +# + +my ($ipod_name, $real_name, $computer_name)=get_ipodname($rc->{IPODDIR}); +unless($ipod_name) { + die "IPOD dir not found: $rc->{IPODDIR}" unless $opt{c}; +} + +# +# check ipod dirs (recreate them if necessary) +# + +mkdir "$rc->{IPODDIR}/iPod_Control",0755 unless(-d "$rc->{IPODDIR}/iPod_Control"); +mkdir "$rc->{IPODDIR}/iPod_Control/Music",0755 unless(-d "$rc->{IPODDIR}/iPod_Control/Music"); +mkdir "$rc->{IPODDIR}/iPod_Control/iTunes",0755 unless(-d "$rc->{IPODDIR}/iPod_Control/iTunes"); +mkdir "$rc->{IPODDIR}/iPod_Control/Device",0755 unless(-d "$rc->{IPODDIR}/iPod_Control/Device"); +for(0..19) { + my $d=sprintf "%.2d",$_; + mkdir "$rc->{IPODDIR}/iPod_Control/Music/F$d",0755 unless(-d "$rc->{IPODDIR}/iPod_Control/Music/F$d"); +} + +unless($opt{c}) { + print STDERR "IPOD name: $ipod_name\n"; + print STDERR "Synced by: $real_name\n"; + print STDERR "Synced on: $computer_name\n"; + + if($rc->{WRITEDEVICEINFO} && !$opt{f}) { + my $exit=0; + unless($rc->{IPODNAME} eq $ipod_name) { + $exit=1; + print STDERR "Your IPOD name: $rc->{IPODNAME}\n"; + } + unless($rc->{REALNAME} eq $real_name) { + $exit=1; + print STDERR "Your real name: $rc->{REALNAME}\n"; + } + unless($rc->{COMPUTERNAME} eq $computer_name) { + $exit=1; + print STDERR "Your computer: $rc->{COMPUTERNAME}\n"; + } + die "names mismatch, use -f to override" if $exit; + } + print STDERR "\n"; +} + +# +# write ipod name +# + +if($rc->{WRITEDEVICEINFO}) { + set_ipodname( + $rc->{IPODDIR},$rc->{BACKUPDIR}, + $rc->{IPODNAME},$rc->{REALNAME},$rc->{COMPUTERNAME} + ); + $ipod_name=$rc->{IPODNAME}; +} + +# +# check for songs +# + +my %songs; +my %check; + +my $dir; +$dir=$rc->{IPODDIR}."/iPod_Control/Music"; +$dir=$rc->{SYNCDIR} if($rc->{SYNCMODE} >= 2); + +my %tosync; +if(($rc->{SYNCLIST}) && ($rc->{SYNCMODE} == 2)) { + open IN,$rc->{SYNCLIST} or die "all-playlist: $rc->{SYNCLIST} not found"; + while() { + chomp; + $tosync{$_}=1; + } + close IN; +} + +my @mp3s; +if(($rc->{SYNCMODE} == 3)) { + my @pl=find("$rc->{PLAYLISTDIR}/* 2>/dev/null"); + my %test; + + for my $p (@pl) { + chomp $p; + my ($n) = $p =~ /.*\/(.*?)$/; + open IN,$p or die "playlist: $p could not be opened"; + while() { + unless($test{$_}) { + push @mp3s,$_; + $test{$_}=1; + } + } + } +} else { + @mp3s=find($dir); +} + +for(@mp3s) { + chomp $_; + next unless(/\.(m|M)(p|P)3$/); + my $name=$_; + + if(keys %tosync) { + next unless($tosync{$name}); + } + + if($opt{n}) { + die "illegal character in filename [$name]\n" unless ($name =~ /^[A-Za-z0-9\.\-_\/\,]+$/); + } + + s/\://g; + s/.*\///g; + $songs{$name}{name}=$_; + if($rc->{SYNCMODE} >= 2) { + $songs{$name}{dir}="F".hash($_); + } else { + ($songs{$name}{dir}) = $name =~ /\/(F\d\d)\//; + } + + { + my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, + $atime,$mtime,$ctime,$blksize,$blocks) = stat($name); + $songs{$name}{size}=$size; + $songs{$name}{date}=$mtime; + } + + my $tag; + $tag = get_mp3tag($name) unless($rc->{ALWAYSTEMPLATES}); + + my ($artist,$album,$title,$order,$_dummy_); + + if($tag) { + # print Dumper($tag); + # YEAR ARTIST COMMENT TRACKNUM TITLE ALBUM GENRE + $artist=$tag->{ARTIST}; + $album=$tag->{ALBUM}; + $title=$tag->{TITLE}; + $order=$tag->{TRACKNUM}; + $order=$1 if($order =~ /(\d+)\s*\//); + + } else { + for(sort {length($b) <=> length($a)} keys %{$rc->{FILETEMPLATES}}) { + if(my @x = $name =~ /$_/) { + my $c=0; + for my $x (@x) { + #print "\$$rc->{FILETEMPLATES}->{$_}->[$c]=\"$x\";\n"; + eval "\$$rc->{FILETEMPLATES}->{$_}->[$c]=\"$x\";"; + die "eval error: $@" if($@); + $c++; + } + last; + } + } + } + + unless($title) { + die "no title found in: $name"; + } + + $title =~ s/_/ /g; + $artist =~ s/_/ /g; + $album =~ s/_/ /g; + + $songs{$name}{title}=$title; + $songs{$name}{artist}=""; + $songs{$name}{album}=""; + $songs{$name}{order}=0; + $songs{$name}{artist}=$artist if $artist; + $songs{$name}{album}=$album if $album; + $songs{$name}{order}=$order if $order; + + my $info = get_mp3info ($name); + + $songs{$name}{size}=$info->{SIZE}; + $songs{$name}{bitrate}=$info->{BITRATE}; + $songs{$name}{duration}=int($info->{SECS}*1000); + $songs{$name}{vbr}=$info->{VBR}; + + #print Dumper($info); + + my $n=$songs{$name}{dir}."/".$songs{$name}{name}; + unless($check{$n}) { + $check{$n}=1; + } else { + die "songname: $songs{$name}{name} not unique"; + } +} + +# +# deleting unwanted songs +# + +my %known; +for(keys %songs) { + $known{$songs{$_}{name}}=1; +} + +#print Dumper(\%known); + +my @ipod = find ("$rc->{IPODDIR}/iPod_Control/Music"); +my @todel; +for(@ipod) { + next unless (/\.mp3$/i); + chomp; + + my ($name) = $_ =~ /\/([^\/]+\.mp3)$/i; + unless($known{$name}) { + push @todel,$_; + } +} + +my $del; +if($rc->{DELETEASK} && @todel) { + for(@todel) { + print "del: $_\n"; + } + print "Do you really want to delete this songs? (y/N) "; + my $in=; + chomp $in; + $del=1 if($in =~ /^y$/i); +} else { + $del=1; +} + +if($del) { + for(@todel) { + print STDERR "deleting: $_\n"; + unlink($_); + } +} + +# +# copy songs +# + +my $main_sl=""; +my $main_pl=""; +my $index=500; + +#print Dumper(\%songs); + +my $df = new Filesys::DiskFree; + +SONGS: for my $song (keys %songs) { + my $attr; + my $out=""; + my $attr_c=3; + + if($rc->{SYNCMODE} >= 2) { + my $to = "$rc->{IPODDIR}/iPod_Control/Music/$songs{$song}{dir}/$songs{$song}{name}"; + #my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, + # $atime,$mtime,$ctime,$blksize,$blocks) = stat($to); + #$size=0 unless $size; + #print "checking: $song [$songs{$song}{size}] -> $to [$size]\n"; + #if($size != $songs{$song}{size}) { + + unless(-e $to) { + print STDERR "syncing: $songs{$song}{name}\n"; + # cp "\"$song\" \"$to\""; + + $df->df(); + my $free=$df->avail($rc->{IPODDIR}); + + if($free-$songs{$song}{size}-$buffer>0) { + copy($song,$to); + } else { + print STDERR "no space availiable for: $songs{$song}{name} [$songs{$song}{size}]\n"; + delete $songs{$song}; + next SONGS; + } + } + } + + $songs{$song}{index}=$index; + + $out.=create_mhod($songs{$song}{title},1); + + if($songs{$song}{artist}) { + $attr_c++; + $out.=create_mhod($songs{$song}{artist},4); + } + if($songs{$song}{album}) { + $attr_c++; + $out.=create_mhod($songs{$song}{album},3); + } + + $out.=create_mhod("MPEG audio file",6); + $out.=create_mhod(":iPod_Control:Music:".$songs{$song}{dir}.":".$songs{$song}{name},2); + + $out=create_mhit( + $attr_c,length($out),$index,$songs{$song}{vbr}, + $songs{$song}{date},$songs{$song}{size}, + $songs{$song}{duration},$songs{$song}{order}, + $songs{$song}{bitrate} + ).$out; + + $main_sl.=$out; + + $main_pl.=create_mhod_mhip($songs{$song}{index}); + + $index++; +} + +#print Dumper(\%songs); + +my %playlists; +my @pl=find("$rc->{PLAYLISTDIR}/* 2>/dev/null"); + +for my $p (@pl) { + chomp $p; + my ($n) = $p =~ /.*\/(.*?)$/; + open IN,$p or die "playlist: $p could not be opened"; + while() { + my $song=$_; + chomp $song; + + unless($songs{$song}) { + print STDERR "ignoring song in playlist [$p], [$song] does not exist in syncdir or ipod full\n"; + } else { + $playlists{$n}{raw}.=create_mhod_mhip($songs{$song}{index}); + $playlists{$n}{count}++; + } + } + close IN; +} + +# +# creating search pattern playlists +# + +for my $pattern (@ARGV) { + my @list; + for(keys %songs) { + push @list,$songs{$_}{index} if($_ =~ /$pattern/i); + } + unless(@list) { + print STDERR "nothing for searchpattern: $pattern found\n"; + } else { + my ($name)=$pattern=~/(\S\S\S+)/; + unless(length($name)>=3) { + $name=$pattern; + $name =~ s/[^A-Za-z0-9]//g; + } + for(@list) { + $playlists{$name}{raw}.=create_mhod_mhip($_); + $playlists{$name}{count}++; + } + print STDERR @list." songs for searchpattern: $pattern found\n"; + } +} + +#print Dumper(\%playlists); + +# +# build the pieces together +# + +my $output; + +my $song_c=keys %songs; + +print STDERR "\nFound songs: $song_c\n"; + +my $tmp=create_mhlt($song_c).$main_sl; +$main_sl=create_mhsd(96+length($tmp),1).$tmp; + +print STDERR "Songlist created\n"; + +my $pl_c=keys %playlists; + +print STDERR "\nFound additional playlists: $pl_c\n"; + +$tmp=create_mhlp($pl_c+1).create_playlist_main($ipod_name,$song_c).$main_pl; +print STDERR "\nMain playlist created: $song_c songs\n\n"; + +for(keys %playlists) { + $tmp.=create_playlist($_,$playlists{$_}{count}).$playlists{$_}{raw}; + print STDERR "Playlist \"$_\" created: $playlists{$_}{count} songs\n"; +} + +$main_pl=create_mhsd(96+length($tmp),2).$tmp; + + +$output=create_mhbd(104+length($main_sl.$main_pl)).$main_sl.$main_pl; + +# backup old iTunesDB +if(-e "$rc->{IPODDIR}/iPod_Control/iTunes/iTunesDB") { + my $t=time(); + copy("$rc->{IPODDIR}/iPod_Control/iTunes/iTunesDB","$rc->{BACKUPDIR}/iTunesDB_$t"); + gzip("$rc->{BACKUPDIR}/iTunesDB_$t"); +} + +open OUT,">".$rc->{IPODDIR}."/iPod_Control/iTunes/iTunesDB" or die "cannot write iTunesDB"; +print OUT $output; +close OUT; + +print STDERR "\niTunesDB created.\n"; +exit; +# END + + +# +# internal subroutines +# + +sub create_mhbd { + my ($size) = @_; + + my $r= "mhbd"; + $r.= pack "V",104; + $r.= pack "V",$size; + $r.= pack "V",1; + $r.= pack "V",1; + $r.= pack "V",2; + for(1..20) { + $r.= pack "V",0; + } + + return $r; +} + +sub create_mhlp { + my ($count) = @_; + + my $r= "mhlp"; + $r.= pack "V",92; + $r.= pack "V",$count; + for(1..20) { + $r.= pack "V",0; + } + + return $r; +} + +sub create_playlist { + my ($name,$anz) = @_; + + my $ipod_name=create_mhod($name,1); + + my $r= "mhyp"; + $r.= pack "V",108; + $r.= pack "V",108+648+length($ipod_name)+$anz*(76+44); + $r.= pack "V",2; + $r.= pack "V",$anz; + $r.= pack "V",0; + $r.= pack "V",3088620292; + $r.= pack "V",2317718671; + $r.= pack "V",3655876446; + for(1..18) { + $r.= pack "V",0; + } + + $r.= "mhod"; + $r.= pack "V",24; + $r.= pack "V",648; + $r.= pack "V",100; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",12714187; # ?? 12714187 + $r.= pack "V",26215000; + $r.= pack "V",0; + $r.= pack "V",65736; + $r.= pack "V",1; # ?? 1 + $r.= pack "V",6; # ?? 6 + $r.= pack "V",0; # ?? 0 + $r.= pack "V",2555905; # ?? 2555905 + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",13107202; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",3276813; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",8192004; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",8192003; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",5242888; + for(1..107) { + $r.= pack "V",0; + } + $r.= pack "V",140; + for(1..19) { + $r.= pack "V",0; + } + + return $r.$ipod_name; +} + +sub create_playlist_main { + my ($name,$anz) = @_; + + my $ipod_name=create_mhod($name,1); + + my $r= "mhyp"; + $r.= pack "V",108; + $r.= pack "V",108+648+length($ipod_name)+$anz*(76+44); + $r.= pack "V",2; + $r.= pack "V",$anz; + $r.= pack "V",1; + $r.= pack "V",3087491191; + $r.= pack "V",837788566; + $r.= pack "V",62365; + for(1..18) { + $r.= pack "V",0; + } + + $r.= "mhod"; + $r.= pack "V",24; + $r.= pack "V",648; + $r.= pack "V",100; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",13172927; # ?? 12714187 + $r.= pack "V",26215000; + $r.= pack "V",0; + $r.= pack "V",65736; + $r.= pack "V",5; # ?? 1 + $r.= pack "V",6; # ?? 6 + $r.= pack "V",3; # ?? 0 + $r.= pack "V",1179649; # ?? 2555905 + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",13107202; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",3276813; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",8192004; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",8192003; + for(1..3) { + $r.= pack "V",0; + } + $r.= pack "V",5242888; + for(1..107) { + $r.= pack "V",0; + } + $r.= pack "V",140; + for(1..19) { + $r.= pack "V",0; + } + + return $r.$ipod_name; +} + +sub create_mhod_mhip { + my ($ref) = @_; + + my $r= "mhip"; + $r.= pack "V",76; + $r.= pack "V",76; + $r.= pack "V",1; + $r.= pack "V",0; + $r.= pack "V",$ref-1; + $r.= pack "V",$ref; + $r.= pack "V",3088619525; + for(1..11) { + $r.= pack "V",0; + } + + $r.="mhod"; + $r.= pack "V",24; + $r.= pack "V",44; + $r.= pack "V",100; + $r.= pack "V",0; + $r.= pack "V",0; + $r.= pack "V",$ref-1; + for(1..4) { + $r.= pack "V",0; + } + + return $r; +} + +sub create_mhsd { + my ($size,$type) = @_; + + my $r="mhsd"; + $r.= pack "V",96; + $r.= pack "V",$size; + $r.= pack "V",$type; + for(1..20) { + $r.= pack "V",0; + } + + return $r; +} + +sub create_mhlt { + my ($count) = @_; + + my $r="mhlt"; + $r.= pack "V",92; + $r.= pack "V",$count; + for(1..20) { + $r.= pack "V",0; + } + + return $r; +} + +sub create_mhit { + my ($arttr_c,$attr_s,$index,$vbr,$date,$size,$dur,$order,$bitrate) = @_; + + my $r="mhit"; + $r.= pack "V",156; + $r.= pack "V",156+$attr_s; + $r.= pack "V",$arttr_c; + $r.= pack "V",$index; + $r.= pack "V",1; + $r.= pack "V",0; + my $type=256; + $type+=1 if($vbr); + $r.= pack "V",$type; + $r.= pack "V",$date+2082844800; + $r.= pack "V",$size; + $r.= pack "V",$dur; + $r.= pack "V",$order; + $r.= pack "V",0; + $r.= pack "V",0; + $r.= pack "V",$bitrate; + $r.= pack "V",2890137600; + for(1..23) { + $r.= pack "V",0; + } + + return $r; +} + +sub create_mhod { + my ($string,$type) = @_; + my $len=length($string); + + my $r="mhod"; + $r.= pack "V",24; + $r.= pack "V",(40+2*$len); + $r.= pack "V",$type; + $r.= pack "V2",0; + $r.= pack "V",1; + $r.= pack "V",(2*$len); + $r.= pack "V2",0; + + my $u=latin1($string); + $u->byteswap; + $r.= $u->utf16; + + return $r; +} + +sub set_ipodname { + my ($dev,$backup,$name,$real,$cpu)=@_; + $dev.="/iPod_Control/iTunes/DeviceInfo"; + + my $file; + + for(1..384) { + $file.=pack "V",0; + } + + my $l=length($name); + substr($file,0,2)=pack "v",$l; + my $u=latin1($name); + $u->byteswap; + substr($file,2,$l*2)=$u->utf16; + + $l=length($real); + substr($file,512,2)=pack "v",$l; + $u=latin1($real); + $u->byteswap; + substr($file,514,$l*2)=$u->utf16; + + $l=length($cpu); + substr($file,1024,2)=pack "v",$l; + $u=latin1($cpu); + $u->byteswap; + substr($file,1026,$l*2)=$u->utf16; + + if(-e $dev) { + my $t=time(); + copy($dev,"$backup/DeviceInfo_$t"); + gzip("$backup/DeviceInfo_$t"); + } + open IPOD,">$dev" or die "cannot write DeviceInfo"; + print IPOD $file; + close IPOD; +} + +sub get_ipodname { + my $dev=shift; + $dev.="/iPod_Control/iTunes/DeviceInfo"; + my $file; + my $buff; + + open IPOD,$dev or return undef; + while (read(IPOD, $buff, 8 * 2**10)) { + $file.=$buff; + } + close IPOD; + + my $l=unpack "v",substr($file,0,2); + my $s=substr($file,2,$l*2); + my $u=utf16($s); + $u->byteswap; + my $name=$u->latin1; + + $l=unpack "v",substr($file,512,2); + $s=substr($file,514,$l*2); + $u=utf16($s); + $u->byteswap; + my $realname=$u->latin1; + + $l=unpack "v",substr($file,1024,2); + $s=substr($file,1026,$l*2); + $u=utf16($s); + $u->byteswap; + my $computername=$u->latin1; + + return ($name,$realname,$computername); +} + +sub hash { + my $string=shift; + my $key; + + my $len=length($string); + + for(my $j=$len-1 ; $j>1 ; $j--) { + $key+=ord(substr($string,$j,1)); + } + + return sprintf "%.2d",(substr($key,length($key)-2,2) % 20); +} + +sub readrc { + my $file = shift; + my $req = shift; + my $rc; + + my $sub; + + open IN,$file or die "cannot open rc file: $file"; + while() { + next if /^\s*$/; + next if /^\s*#/; + + if(/^\s*(\S+)\s*=\s*(.*?)\s*$/) { + my $k=$1; + my $n=$2; + ($n) = $n =~ /^\"(.*?)\"$/ if($n =~ /\"/); + unless($sub) { + $rc->{$k}=$n; + } else { + ($k) = $k =~ /^\"(.*?)\"$/ if($k =~ /\"/); + my @n=split /,/,$n; + for(@n) { + s/^\s+//g; + s/\s+$//g; + s/^\"//; + s/\"$//; + } + $rc->{$sub}->{$k}=\@n; + } + } elsif (/^\s*(\S+)\s*\{/) { + $sub=$1; + } elsif (/^\s*}/) { + $sub=undef; + } + } + + if($rc->{SYNCMODE} == 2) { + push @$req,"SYNCDIR"; + } + if($rc->{WRITEDEVICEINFO} == 1) { + push @$req,("IPODNAME","REALNAME","COMPUTERNAME"); + } + if($rc->{ALWAYSTEMPLATES} == 1) { + push @$req,"FILETEMPLATES"; + } + + for my $d (keys %$rc) { + if($d =~ /DIR$/) { + $rc->{$d} =~ s/\~/$ENV{HOME}/; + } + } + $rc->{SYNCLIST} =~ s/\~/$ENV{HOME}/ if $rc->{SYNCLIST}; + + for(@$req) { + die "RC PARAMETER: $_ not found" unless($rc->{$_}); + } + return $rc; +} diff --git a/syncauto.sh b/syncauto.sh new file mode 100644 index 0000000..d84e5ae --- /dev/null +++ b/syncauto.sh @@ -0,0 +1,3 @@ + +# sudo mount -o uid=marc /dev/sdt1 /media/hdext +rsync -a --no-o --no-p --no-g -L --modify-window 1 --stats --delete --progress /mp3/auto/ /media/hdext/ diff --git a/taz-download.sh b/taz-download.sh index c3adb93..6c549f0 100755 --- a/taz-download.sh +++ b/taz-download.sh @@ -8,7 +8,7 @@ # So sehen die Dateien aus: # http://www.taz.de/cgi-bin/digiabo/2007_04_17_HTM.zip -TAZDIR=/dat/books/taz +TAZDIR=/media/nas/books/taz TAZUSER=103450 TAZPASSWD=oxculo TAZTYPE=.pdf @@ -72,3 +72,6 @@ for i in {1..16} do download "${TAG[$i]}""$TAZTYPE_EPUB" "$TAZURL""taz_""${TAG[$i]}""$TAZTYPE_EPUB" done + +# Sync to Dropbox +bash /home/marc/bin/tazsync.sh diff --git a/tazsync.sh b/tazsync.sh new file mode 100644 index 0000000..b02073a --- /dev/null +++ b/tazsync.sh @@ -0,0 +1,26 @@ + +daysback=10 + +srcdir=/dat/books/taz +dstdir=/home/marc/Dropbox-ipad/taz +tmpdir=/tmp + +[ -d $dstdir ] || exit +[ -d $srcdir ] || exit +[ -d $tmpdir ] || exit + +cd $dstdir +find . -type f | sort> $tmpdir/alt.lst + +cd $srcdir +find . -mtime -$daysback -name "*.epub" | sort > $tmpdir/new.lst + +rsync --files-from=$tmpdir/new.lst . $dstdir/ + +cd $dstdir + +cat $tmpdir/alt.lst $tmpdir/new.lst | sort -u > $tmpdir/all.lst +cat $tmpdir/all.lst +cat $tmpdir/new.lst +diff $tmpdir/new.lst $tmpdir/all.lst | grep "^>" | sed "s/^> //" | xargs rm +# $rmfiles diff --git a/test.sh b/test.sh new file mode 100644 index 0000000..19b5d7f --- /dev/null +++ b/test.sh @@ -0,0 +1,7 @@ + +echo "#!/bin/bash" > /tmp/cctest +echo "dstdir=\$(dirname \$1)" >> /tmp/cctest +echo "echo rsync -av \$1 \$bakdir/\$dstdir" >> /tmp/cctest + +export bakdir=/media/hdext/git +find /home/marc/ -type d -name .git -exec bash -x /tmp/cctest {} \; diff --git a/tonas.sh b/tonas.sh new file mode 100644 index 0000000..f067a3f --- /dev/null +++ b/tonas.sh @@ -0,0 +1,3 @@ + +sudo -u vdr rsync -avz --progress --delete --exclude "*.del" /video/ /media/hdext/video/vdr/ +sudo -u vdr rsync -avz --progress --delete /mp3/ /media/hdext/audio/ diff --git a/torrentcreate.sh b/torrentcreate.sh new file mode 100644 index 0000000..f4441cc --- /dev/null +++ b/torrentcreate.sh @@ -0,0 +1 @@ +ctorrent -t -u http://tracker.thepiratebay.org/announce -s test.torrent garmin_allinone_d_2009-07-17.tar diff --git a/tvm2vdr_start b/tvm2vdr_start new file mode 100755 index 0000000..7b66a39 --- /dev/null +++ b/tvm2vdr_start @@ -0,0 +1,12 @@ +#!/bin/bash + +tmpdir1=/tmp/tvmovie2vdr +tmpdir2=/tmp/tvmovie2vdrup +logdir=/var/log/tvmovie2vdr + +[ -d $tmpdir1 ] || mkdir $tmpdir1 +[ -d $tmpdir2 ] || mkdir $tmpdir2 +[ -d $logdir ] || mkdir $logdir + +tvm2vdr + diff --git a/unqueue b/unqueue new file mode 100755 index 0000000..7f865b2 --- /dev/null +++ b/unqueue @@ -0,0 +1,15 @@ +#!/bin/bash +set -x +qfile=$1 + +lines=$(cat $qfile | wc -l) + +while [ $lines -ge 1 ]; do + entry=$(head -n 1 $qfile) + $entry + tail -n +2 $qfile > ${qfile}.tmp + mv ${qfile}.tmp ${qfile} + lines=$(cat $qfile | wc -l) +done + +rm $qfile diff --git a/update_garmin.sh b/update_garmin.sh index 7c25455..5476c89 100644 --- a/update_garmin.sh +++ b/update_garmin.sh @@ -3,8 +3,8 @@ LocalDir=/dat/gps/garmin -allinone=1 -radfahrer=1 +allinone=0 +radfahrer=0 kleineisel=1 # ------------------------------------------- @@ -67,14 +67,15 @@ if [ $radfahrer -eq 1 ]; then cd $LocalDir/radfahrer - wget -nv http://osm.arndnet.de/ -O index.html + #wget -nv http://osm.arndnet.de/ -O index.html + wget -N http://radkarte.formann.de/gmapsupp.img.zip #uncompress < Radkarte > Radkarte.html - cp index.html Radkarte.html - url_rad=$(cat Radkarte.html | grep img\.zip | cut -f 2 -d '"') - wget -nv -N $url_rad + #cp index.html Radkarte.html + #url_rad=$(cat Radkarte.html | grep img\.zip | cut -f 2 -d '"') + #wget -nv -N $url_rad datestr=$(stat -c %y gmapsupp.img.zip | cut -f 1 -d ' ') [ -f radfahrer_$datestr.zip ] || cp gmapsupp.img.zip radfahrer_$datestr.zip - rm Radkarte.html + #rm Radkarte.html fi diff --git a/vdrrecren b/vdrrecren new file mode 100755 index 0000000..4602a79 --- /dev/null +++ b/vdrrecren @@ -0,0 +1,199 @@ +#!/usr/bin/ruby +require 'socket' + +DEBUG=1 +#Port=6419 +Port=2001 + +def SvdrpRecv(s) + lines=Array.new + begin + str=s.readline + lines.push(str) + #puts("SvdrpReceived: " + str + " - |" + str[3,1] + "|" ) if $DEBUG + end while str[3,1]=="-" + return(lines) +end + +def SvdrpSend( s, strSvdrpCmd ) + s.write(strSvdrpCmd + "\n") + l=SvdrpRecv(s) + return(l) +end + +def Svdrp( strSvdrpCmd ) + puts("Svdrp:" + strSvdrpCmd) if DEBUG + s=TCPSocket::new("localhost", Port) + l=SvdrpRecv(s) + l=SvdrpSend(s, strSvdrpCmd) + s.write("quit\r\n") + s.close + return(l) +end + +def CmdRen( num, strNewName ) + cmd=sprintf("MOVR %d %s", num, strNewName) + printf("Aufnahme umbennenen in '%s' ...\n", cmd) + Svdrp(cmd) +end + +if ARGV.size!=2 + printf("invalid arguments: %d\n",ARGV.size ) + exit +end +CMD=ARGV[0] +REC=ARGV[1] +if not File.directory?(REC) + puts("not a directory") + exit +end +RECDATEDIR=File.basename(REC) +RECPATH=File.dirname(REC) +RECNAME=File.basename(RECPATH) +BASEDIR=File.dirname(RECPATH) +EPISODENAME=File.basename(BASEDIR) + +printf("recpath:%s basedir:%s recname:%s recdatedir:%s\n", RECPATH, BASEDIR, RECNAME, RECDATEDIR) +sp=RECDATEDIR.split(".") +RECDATE=sp[0] +RECHOUR=sp[1].to_i +RECMIN=sp[2].to_i +if sp.last()!="rec" + puts("not .rec-dir") + exit +end +#printf("1\n") + +sp=RECDATE.split("-") +RECDAY=sp[2].to_i +RECMON=sp[1].to_i +RECYEAR=sp[0].to_i + +strTime=sprintf("%02d:%02d", RECHOUR, RECMIN); +strDate=sprintf("%02d.%02d.%02d", RECDAY, RECMON, RECYEAR % 100); + +l=Svdrp("LSTR") + +recs=Array.new +printf("Date:%s ; Time:%s\n", strDate,strTime) if DEBUG +l.each do |x| + z=x[4..x.size-1] + sp=z.split(" ") + + #printf("d:%s;t:%s-%s;%s-%s\n", sp[1], sp[2], strDate,strTime, x) + #printf("%s%s|%s %s|%s\n", z, sp[1], sp[2][0,5], strDate, strTime) + if sp[1]==strDate && sp[2][0,5]==strTime + puts("LSTR:"+x) if DEBUG + recs.push(x) + end +end + +if recs.size==0 + puts("Aufnahme nicht gefunden") + exit +end +if recs.size>1 + puts("Aufnahmezeit nicht eindeutig") + exit +end + + +#p(recs[0]) +# Get Rec-Num +rec=recs[0][4..(recs[0].size-1)] +puts("rec:"+rec) if DEBUG +rec_s=rec.split(' ') +num=rec_s[0].to_i +printf("Num:%s\n",num) if DEBUG +# Get Title of Rec +title="" +rec_s[4..rec_s.size].each { |x| title=title+x+' ' } +printf("Title:%s\n",title) if DEBUG +# Get Dir of Rec +dir_s=title.split('~') +dir="" +printf("Dir_s:%s size:%d\n", dir_s, dir_s.size) if DEBUG +if(dir_s.size>1) + dir_s[0..dir_s.size-2].each { |x| dir=dir+x+'~' } +end +puts("Dir: " + dir) if DEBUG +dir_parent="" +dir_parent=dir_s[dir_s.size-2] if dir_s.size>=2 +puts("ParentDir: " + dir_parent) if DEBUG + +# read info.vdr-file +info_title="" +info_short="" +info_desc="" +infofile=REC + "/info.vdr" +if ! File.exists?( infofile ) + infofile=REC + "/info" +end +puts("Infofile: " + infofile) if DEBUG +if File.exists?( infofile ) + puts("Infofile: " + infofile) if DEBUG + f = File.new( infofile ) + lines=f.readlines + f.close + lines.each do |l| + if l[0,2]=="T " + info_title=l[2..l.size].chop + elsif l[0,2]=="S " + info_short=l[2..l.size].chop + elsif l[0,2]=="D " + ld=l.size + ld=80 if ld>80 + info_desc=l[2..ld].chop + end + end +end +#printf("5\n") + +puts("Info Title: " + info_title) if DEBUG +puts(" Short: " + info_short) if DEBUG +puts(" Desc : " + info_desc) if DEBUG +#printf("6 %d\n", DEBUG) + +puts("CMD:"+CMD) if DEBUG +case CMD +when "ShortToName" : + if info_short.size>0 + puts("ShortToName") if DEBUG + newname=(dir+info_short) #.gsub(" ", "\\ ") + CmdRen(num, newname) + end +when "TitleToName" : + if info_title.size>0 + puts("TitleToName") if DEBUG + newname=(dir+info_title) #.gsub(" ", "\\ ") + CmdRen(num, newname) + end +when "DescToName" : + if info_desc.size>0 + puts("DescToName") if DEBUG + newname=(dir+info_desc) #.gsub(" ", "\\ ") + CmdRen(num, newname) + end +when "DirToName" : + if dir_parent.size>0 + puts("DirToName") if DEBUG + CmdRen(num, dir.chop) + end +when "TitleToDir" : + if info_title.size>0 + puts("TitleToDir") if DEBUG + title=info_title.gsub(" ", "_").gsub("(","\(").gsub(")","\)").gsub("/", "#2F").gsub(":", "#3A") + printf("title:%s recpath:%s\n", title, RECPATH) + newdir=BASEDIR+"/"+title + cmd=sprintf("mkdir %s", newdir) + puts(cmd) + system("mkdir", newdir) + cmd=sprintf("mv %s %s", RECPATH, newdir+"/"+RECNAME) + puts(cmd) + system("mv", RECPATH, newdir+"/"+RECNAME) + cmd=sprintf("touch /video/.update") + puts(cmd) + system("touch", "/video/.update") + #system("ls -l") + end +end diff --git a/vdrrecren.rb b/vdrrecren.rb new file mode 100755 index 0000000..a75a1a9 --- /dev/null +++ b/vdrrecren.rb @@ -0,0 +1,144 @@ +#!/usr/bin/ruby + +require 'socket' + +def SvdrpRecv(s) + lines=Array.new + begin + str=s.readline + lines.push(str) + #puts("SvdrpReceived: " + str + " - |" + str[3,1] + "|" ) if $DEBUG + end while str[3,1]=="-" + return(lines) +end + +def SvdrpSend( s, strSvdrpCmd ) + s.write(strSvdrpCmd + "\n") + l=SvdrpRecv(s) + return(l) +end + +def Svdrp( strSvdrpCmd ) + puts("opening socket...") if $DEBUG + s=TCPSocket::new("localhost", 2001) + l=SvdrpRecv(s) + l=SvdrpSend(s, strSvdrpCmd) + s.write("quit\r\n") + s.close + return(l) +end + +def RenameRec( num, strDir, strName) + if strName.size>0 + cmd=sprintf("RENR %d '%s'", num, strDir + strName) + printf("Aufnahme %d umbennenen in '%s'...\n", num, strDir+strName) + #Svdrp(cmd) + end +end + +if ARGV.size!=2 + printf("invalid arguments: %d\n",ARGV.size ) + exit +end + +CMD=ARGV[0] +REC=ARGV[1] + +if not File.directory?(REC) + puts("not a directory") + exit +end +RECDATEDIR=File.basename(REC) +RECPATH=File.dirname(REC) +RECNAME=File.basename(RECPATH) +BASEDIR=File.dirname(RECPATH) +EPISODENAME=File.basename(BASEDIR) + +sp=RECDATEDIR.split(".") +RECDATE=sp[0] +RECHOUR=sp[1].to_i +RECMIN=sp[2].to_i +if sp[5]!="rec" + puts("not .rec-dir") + exit +end + +sp=RECDATE.split("-") +RECDAY=sp[2].to_i +RECMON=sp[1].to_i +RECYEAR=sp[0].to_i + +strTime=sprintf("%02d:%02d", RECHOUR, RECMIN); +strDate=sprintf("%02d.%02d.%02d", RECDAY, RECMON, RECYEAR % 100); + +l=Svdrp("LSTR") + +recs=Array.new +#printf("Date:%s ; Time:%s\n", strDate,strTime) if $DEBUG +l.each do |x| + sp=x.split(" ") + #printf("d:%s;t:%s\n", sp[1], sp[2]) + if sp[1]==strDate && sp[2][0,5]==strTime + recs.push(x) + end +end + +if recs.size>1 + puts("Aufnahmezeit nicht eindeutig") + exit +end + +# Get Rec-Num +rec=recs[0][4..(recs[0].size-1)] +rec_s=rec.split(' ') +num=rec_s[0].to_i + +# Get Title of Rec +title="" +rec_s[3..rec_s.size].each { |x| title=title+x+' ' } +#printf("t:%s\n",title) + +# Get Dir of Rec +dir_s=title.split('~') +dir="" +dir_s[0..dir_s.size-2].each { |x| dir=dir+x+'~' } +dir_parent=dir_s[dir_s.size-2] if dir_s.size>=2 +#puts("D:"+dir) + +# read info.vdr-file +infofile=REC + "/info.vdr" +if File.exists?( infofile ) + puts("reading " + infofile) if $DEBUG + f = File.new( infofile ) + lines=f.readlines + f.close + info_title="" + info_short="" + info_desc="" + lines.each do |l| + if l[0,2]=="T " + info_title=l[2..l.size].chop + elsif l[0,2]=="S " + info_short=l[2..l.size].chop + elsif l[0,2]=="D " + ld=l.size + ld=80 if l.size > 80 + info_desc=l[2..ld].chop + end + end +end + +puts(info_title) if $DEBUG +puts(info_short) if $DEBUG +puts(info_desc) if $DEBUG + +case CMD +when "ShortToName" : + RenameRec(num, dir, info_short) +when "DirToName" : + if dir_parent.size>0 + RenameRec(num, "", dir.chop) + end +when "DescToName" : + RenameRec(nu, dir, info_desc) +end diff --git a/vdrrecren_start b/vdrrecren_start new file mode 100755 index 0000000..6119593 --- /dev/null +++ b/vdrrecren_start @@ -0,0 +1,4 @@ +#!/bin/sh + +echo "/usr/local/bin/vdrrecren $1 '$2' 2>&1 >> /tmp/vdrrecren.log" | at now +echo "Command: /usr/local/bin/vdrrecren $1 '$2' 2>&1 >> /tmp/vdrrecren.log" >> /tmp/vdrrecren.log diff --git a/zeit.sh b/zeit.sh old mode 100644 new mode 100755 index f1008f0..41a4024 --- a/zeit.sh +++ b/zeit.sh @@ -1,6 +1,6 @@ #!/bin/bash -destdir=~/tmp/zeit +destdir=/dat/books/zeit user=mh256 pw=zeit0815 @@ -17,22 +17,24 @@ tmpfile_bl=/tmp/zeit_bl.tmp [ -d $destdir ] || mkdir -p $destdir cd $destdir + +# links zum Download des pdf und epub ermitteln wget --user=$user --password=$pw $url -O $tmpfile pdf_url=$(cat $tmpfile | grep Download | head -n 1 | sed -r 's/href=.(.*pdf).*/\1/') epub_url=$(cat $tmpfile | grep content.*Download | awk -F "\"" '{print $2}') - +# Nummer des Ausgabe zum umbenennen des epub ermitteln number=$(echo $pdf_url | sed -r 's/^.*DZ_ePaper_(.*)\.pdf/\1/' | awk -F_ '{ printf("%s-%s",$2,$1)}' ) - +# links zum download von Beilage und Zeitmagazin ermitteln wget --user=$user --password=$pw $url_zm -O $tmpfile_zm pdfzm_url=$(cat $tmpfile_zm | grep Download | head -n 1 | sed -r 's/href=.(.*pdf).*/\1/') wget --user=$user --password=$pw $url_bl -O $tmpfile_bl pdfbl_url=$(cat $tmpfile_bl | grep Download | head -n 1 | sed -r 's/href=.(.*pdf).*/\1/') - +# alles herunterladen wget --user=$user --password=$pw $epub_url -O die_zeit_20$number.epub wget --user=$user --password=$pw "$url_base/$pdf_url" wget --user=$user --password=$pw "$url_base/$pdfzm_url" wget --user=$user --password=$pw "$url_base/$pdfbl_url" - +# Temp-files loeschen rm $tmpfile $tmpfile_zm $tmpfile_bl