diff options
Diffstat (limited to 'Tools/master-timer')
-rw-r--r-- | Tools/master-timer/LIESMICH | 154 | ||||
-rw-r--r-- | Tools/master-timer/README | 54 | ||||
-rw-r--r-- | Tools/master-timer/THANKS | 18 | ||||
-rw-r--r-- | Tools/master-timer/Todo | 4 | ||||
-rwxr-xr-x | Tools/master-timer/convert-DTV2VDR.pl | 151 | ||||
-rwxr-xr-x | Tools/master-timer/convert-oldtorecord.pl | 61 | ||||
-rwxr-xr-x | Tools/master-timer/master-timer.pl | 2231 | ||||
-rw-r--r-- | Tools/master-timer/sample/channels-to-scan | 4 | ||||
-rw-r--r-- | Tools/master-timer/sample/config | 38 | ||||
-rw-r--r-- | Tools/master-timer/sample/convert-channel-list | 26 | ||||
-rw-r--r-- | Tools/master-timer/sample/deepblack | 251 | ||||
-rw-r--r-- | Tools/master-timer/sample/subtitle-movie | 11 | ||||
-rw-r--r-- | Tools/master-timer/sample/torecord | 116 |
13 files changed, 1881 insertions, 1238 deletions
diff --git a/Tools/master-timer/LIESMICH b/Tools/master-timer/LIESMICH index 9694875..8e53da9 100644 --- a/Tools/master-timer/LIESMICH +++ b/Tools/master-timer/LIESMICH @@ -1,106 +1,70 @@ - Master-Timer - ============ +Master-Timer +============ +(w) by Matthias Schniedermeyer (ms@citd.de) 1. Einleitung ------------- Master-Timer ist ein System zum automatischen Aufnehmen von Serien und Filmen. +Beim Aufruf werden die Konfigurationsdateien gelesen, die Datei "epg.data" im +aktuellen Verzeichnis nach passenden Sendungen durchsucht und die ermittelten +Timer per SVDRP in VDR programmiert. Danach beendet sich Master-Timer. -2. Voraussetzungen ------------------- +Entsprechend empfiehlt es sich, Master-Timer per cronjob aufzurufen. -VDR liefert die "epg.data". - -3. Konfigurationsdateien +2. Konfigurationsdateien ------------------------ -Alle Konfigurationsdateien liegen unter "<HOME>.master-timer" - -config: Eine Ansammlung von Key-Value Paaren. Alle sind "optional" und - erhalten dann die angegebenen Default-Werte - -(# = Kommentarzeilen) -marginstart (Default 600) - Anzahl der "Sicherheits" Sekunden die ein Timer frueher beginnen soll - -marginstop (Default 600) - Anzahl der "Sicherheits" Sekunden die ein Timer laenger dauern soll - -defaultprio (Default 50) - Die Prioritaet die fuer Timer verwendet wird wo keine Prioritaet - angegeben ist - -DVBCards (Default 1) - Anzahl der vorhandenen DVB-Karten (Derzeit nicht verwendet) - -Dest-Host (Default "localhost") - Host-name oder IP des Rechners auf dem VDR laeuft - -Dest-Port (Default "2001") - Port der VDR verwendet - -jointimers (Default 0) - Sollen aufeinanderfolgende Timer auf den gleichen Kanal zusammengefasst - werden (0 = "Nein", alles andere "Ja") - -debug (Default 0) - Debug-Level, die einzelnen Debug-Werte muessen aus folgenden Werten - zusammengezaehlt werden - 1 : Dump "torecord" - 2 : Dump all timers - 4 : Show when a timer will be deleted - 8 : Dump the "Done" REs - 16 : Verbose Config-Reading - -deepblack: Eine Liste von Titeln die man NIEMALS NIMMER sehen will - Jede Zeile = 1 Titel - -subtitle-movies: Eine Liste der "Subtitel" die ein Zeichen fuer einen Film sind - (Soweit die von den Sendern richtig ausgefuellt sind.) - Jede Zeile = 1 Subtitel - -torecord: Die Sachen die man Aufnehmen will - Jede Zeile = 1 Timer -# Format: (Every field is "optional". -# [Title RE|Subtitle RE|Description RE|Channel-Name|Timeframe|Prio|Timer-Title] -# -# To record something at least one of the "Title", "Subtitle" or "Description" -# Fields has to be provided. This 3 fields are "include" and the rest are -# "exclude" fields! -# -# More than one channel definition can be provided. The delimiter is ";" -# Additionaly you can make a "blacklist" of Channels when you prepent a "!" to the first Channel Definition -# The "!" is only tested for the FIRST Channel definition. -# You can only have a white or a blacklist (Mixing doesn't make sense!) -# -# ex. Record the series "Deep Space Nine" on Sci-Fantasy in the timeframe 09:00 - 14:00 -# Deep Space Nine|||Sci-Fantasy|0900-1400|99|DS9 -# -# Record all "Actionfilm"s with "Schwarzenegger" -# |Actionfilm|Schwarzenegger -# - - -done: The titles/subtitles which are already recorded/should not be recorded - (Programmed Timers which got inserted into "done" will be deleted - automaticaly) - -4. Notices ----------- - -- Recordings "overlapping" on the same channel, will be joined into one Timer -- Title/Subtitle/Descriptions are "fixed" for Channel that don't fill them - out "correctly" (Currently the "Bugs" from Pro-7/VOX/VIVA) - Pro7: Remove the Title from the Subtitle '<Title> / <Subtitle>' - VOX/VIVA: Subtitle is enclosed into "" and after ". " is the description - VIVA: When the Subtitle beginns with space the subtitle is moved to - description - All (except the second VIVA one) fixes are tried onto ALL Subtitles. - -5. Known-Bugs -------------- +Alle Konfigurationsdateien liegen unter "~/.master-timer". Es werden +regulaere Ausdruecke ohne Unterscheidung der Gross-/Kleinschreibung +benutzt. + +config: Die Hauptkonfigurationsdatei. + +deepblack: Eine Negativliste von Titeln, die man NIEMALS NIMMER sehen will. + Die epg-datensaetze werden beim Parsen einfach entfernt. + +subtitle-movies: Eine Liste der "Subtitel", die ein Zeichen fuer einen Film + sind (soweit die von den Sendern richtig ausgefuellt sind). Die + Einstellungen in dieser Datei werden fuer das Makro "MOVIE" in torecord + benutzt. + Kommentarzeilen sind nicht erlaubt. + +torecord: Liste der aufzunehmenden Filme. + +done: Liste der Titel/Subtitel, die bereits aufgenommen wurden. Timer, die + hier auftauchen, werden in VDR automatisch geloescht. + +channels-to-scan: Diese Kanaele werden vom Skript "scan-channels" durch- + geschaltet (zwecks Einlesen der EPG-Daten). Die Datei wird von Master- + Timer selbst nicht benutzt. + +3. Anmerkungen +-------------- + +- einige Sender fuellen die EPG-Felder nicht korrekt aus. Diese Fehler + werden von Master-Timer automatisch korrigiert. + + Pro7: Title aus dem Subtitle entfernen '<Title> / <Subtitle>' + Pro7: Timer zwischen 00:00 und 05:00 werden einen Tag in die Zukunft + verschoben (Als unguten Nebeneffekt hat dies zur Folge das zum + aktuellen Tag NICHT die epg-Daten das folgenden Tags (=Das was in + der Fernsehzeitschrift noch auf der gleichen Seite ist) mehr gesendet + werden. Wenn man also "Last Minute" etwas aufnehmen will, dann muss + man (leider) einen Timer "per Hand" in VDR einprogrammieren!) + VOX/VIVA: Subtitle ist in "" eingeschlossen nd nach ". " steht die description + VIVA: Wenn der Subtitle mit einem Space beginnt, dann wird der komplette + Subtitle in die Description verschoben + RTL2: Wenn der EPG-Datensatz eine Dauer von kleiner/gleich 1 Sekunde hat, + wird er einfach verworfen. + +Bis auf den jeweils 2ten VIVA&Pro-7 Bug werden die Fixes an jedem +epg-Datensatz ausprobiert. + +4. Bekannte Bugs +---------------- -- It isn't checked if there are enough DVB-Cards -- Overlapping Timers, on the same channel, are always joined -- JOINed timers which are "done" don't get deleted automaticaly +- Es wird nicht geprueft ob noch genug DVB-Karten vorhanden sind +- "Joined timers" werden nur automatisch geloescht wenn alle dazugehoerigen + Sendungen "done" sind. diff --git a/Tools/master-timer/README b/Tools/master-timer/README index c71e6e1..05cc41a 100644 --- a/Tools/master-timer/README +++ b/Tools/master-timer/README @@ -1,43 +1,49 @@ - Master-Timer (w) by Matthias Schniedermeyer (ms@citd.de) - ============ +Master-Timer +============ +(w) by Matthias Schniedermeyer (ms@citd.de) 1. Introduction --------------- -Master-Timer ist a system for recording Films/Series automaticaly +Master-Timer is a system designed for automatically recording movies. +Upon execution it reads its configuration files, scans the file "epg.data" +in the current directory for matching titles and programs them via SVDRP +into VDR. -2. Requierements ----------------- +You may for example run Master-Timer as a cron job. -epg.data - -3. Config-Files +2. Config files --------------- -For all files: One Entry per Line. Each line is a "Regular Expresion" - So you can use all Perl-Style REs you want. - The RE are matched with "i" so they are case insensitive! - (Except for the "done"-list, these must match excatly!) +Configuration files are located in "~/.master-timer". Each entry is a +regular expression so you can use all Perl style REs you want. They are +processed case insensitive. + +config: Main configuration file. -deepblack: Blacklist of "Titles" you NEVER EVER want to get to you eyes +deepblack: Blacklist of "titles" you NEVER EVER want to see. -subtitle-movies: A list of "Subtitles" which indicate a movie. - (For Channels that correctly fill out the Subtitle. - e.g. it won't work for *eRTL*) +subtitle-movies: A list of "Subtitles" which indicate a movie (used + by the "MOVIE" macro in torecord). + For channels that correctly fill out the subtitle e.g. it will not + work with *eRTL*. -torecord: The titles/subtitles/Description you want to record +torecord: The titles you want to record. done: The titles/subtitles which are already recorded/should not be recorded - (Programmed Timers which got inserted into "done" will be deleted - automaticaly) + Programmed timers which got inserted into "done" will be deleted + automatically. + +channels-to-scan: Used only by the separate "scan-channels" script which + switches through channels in order to get EPG data. 4. Notices ---------- -- Recordings "overlapping" on the same channel, will be joined into one Timer -- Title/Subtitle/Descriptions are "fixed" for Channel that don't fill them - out "correctly" (Currently the "Bugs" from Pro-7/VOX/VIVA) +- Recordings overlapping on the same channel will be joined into one timer +- Title/Subtitle/Descriptions are "fixed" for channels that don't fill them + out correctly (Pro-7/VOX/VIVA) Pro7: Remove the Title from the Subtitle '<Title> / <Subtitle>' VOX/VIVA: Subtitle is enclosed into "" and after ". " is the description VIVA: When the Subtitle beginns with space the subtitle is moved to @@ -48,5 +54,5 @@ done: The titles/subtitles which are already recorded/should not be recorded ------------- - It isn't checked if there are enough DVB-Cards -- Overlapping Timers, on the same channel, are always joined -- JOINed timers which are "done" don't get deleted automaticaly +- Overlapping timers on the same channel are always joined +- Joined timers which are "done" don't get deleted automatically diff --git a/Tools/master-timer/THANKS b/Tools/master-timer/THANKS new file mode 100644 index 0000000..04bb13b --- /dev/null +++ b/Tools/master-timer/THANKS @@ -0,0 +1,18 @@ +Klaus Schmidinger + - VDR + +Malte Kiesel + - Suggestions + - Bug Reports + - Documentation Updates for README/LIESMICH/torecord/deepblack/config + +Guido Fiala + - Suggestions + - Bug Repots + - finding bugs i found just before i read that part of his mails + (First the bug, then the errormessages! Otherwise i will search/find + the bug myself :-))) ) + +Axel Gruber + - Suggestions + - Bug Reports diff --git a/Tools/master-timer/Todo b/Tools/master-timer/Todo index 722ee96..1757ade 100644 --- a/Tools/master-timer/Todo +++ b/Tools/master-timer/Todo @@ -1,9 +1,5 @@ -- "Intelligenter" Kanal-Scanner (z.B. nur 1 Kanal fuer ein - Sender-"Gruppe") -- Filtern nach Serie/Film - "Komfortable" Anzeige, mit Black & Whitelisten, fuer Genres/Titeln usw. -- Unterstueztung von 1xVDR pro Karte - Abspielen (mit automatischen "killen" des "Frontend"-VDRs) von Aufzeichnungen - "View"-Timer d.h. Timer der nicht Aufnimmt sondern nur den Kanal aendert diff --git a/Tools/master-timer/convert-DTV2VDR.pl b/Tools/master-timer/convert-DTV2VDR.pl new file mode 100755 index 0000000..fb2a783 --- /dev/null +++ b/Tools/master-timer/convert-DTV2VDR.pl @@ -0,0 +1,151 @@ +#!/usr/bin/perl -w + +use strict; + +# The EPG-Entrys +my (%Entry, %channel, $mode); + +# 0 = VDR -> DTV +# 1 = DTV -> VDR +$mode = 0; + +read_channel_list(); +if ($mode) { + &read_dtv(); + &read_epgdata(); +} else { + &read_epgdata(); + &read_dtv(); +} +&print_VDR(); + +sub read_epgdata { + my ($channel, $duration, $title, $subtitle, $description, $time); + open (FI,"epg.data") or die ("Can't open file \"epg.data\"\n"); + + while (<FI>) { + # Begin Channel + if (/^C\s(\d+)\s+(.+)/) { + $channel=$2; + while (<FI>) { + # End Channel + if (/^c$/) { + last; + } + # Begin Timer + elsif (/^E\s(\d+)\s+(\d+)\s+(\d+)$/) { + # Undef this Variables because it is possibel that not every timer uses this values + undef $duration; + undef $subtitle; + undef $description; + + $time=$2; + $duration=$3; + } + # Title + elsif (/^T\s(.*)/) { + $title=$1; + } + # Subtitle + elsif (/^S\s(.*)/) { + $subtitle=$1; + } + # Description + elsif (/^D\s(.*)/) { + $description=$1; + } + # End Timer + elsif (/^e$/) { + if ($mode) { + # DTV -> VDR + $Entry{$channel}{$time}{subtitle}=$subtitle if ($subtitle); + if ($description) { + if ($Entry{$channel}{$time}{description}) { + $Entry{$channel}{$time}{description} = "DTV: '$Entry{$channel}{$time}{description}' VDR: '$description'"; + } else { + $Entry{$channel}{$time}{description} = "DTV: '' VDR: '$description'"; + } + } + } else { + # VDR -> DTV + $Entry{$channel}{$time}{title}=$title; + $Entry{$channel}{$time}{duration}=$duration; + $Entry{$channel}{$time}{subtitle}=$subtitle if ($subtitle); + $Entry{$channel}{$time}{description}=$description if ($description); + } + } + } + } + } + close (FI); +} + +sub read_dtv { + my ($channel, $time, $duration, $title, $category, $subtitle, $description); + open (FI,$ARGV[0]) or die "Can't open DTV-File"; + + while (<FI>) { + chomp; + ($channel, $time, $duration, $title, $category, $subtitle, $description) = split (/\|/); + if (!$channel{$channel}) { + next; + } + $channel = $channel{$channel}; + if ($mode) { + # DTV -> VDR + if (!$subtitle && $description =~ /^\"(.*?)\"\:\s(.*)/) { + $Entry{$channel}{$time}{subtitle} = $1; + $description = $2; + } + $Entry{$channel}{$time}{title} = $title; + $Entry{$channel}{$time}{duration} = $duration; + $Entry{$channel}{$time}{subtitle} = $subtitle if ($subtitle); + $Entry{$channel}{$time}{category} = $category if ($category); + $Entry{$channel}{$time}{description} = $description if ($description); + } else { + # VDR -> DTV + $Entry{$channel}{$time}{category} = $category if ($category); + if ($description) { + if (!$Entry{$channel}{$time}{subtitle} && $description =~ /^\"(.*?)\"\:\s(.*)/) { + $Entry{$channel}{$time}{subtitle} = $1; + $description = $2; + } + if ($Entry{$channel}{$time}{description}) { + $Entry{$channel}{$time}{description} = "DTV: '$description' VDR: '$Entry{$channel}{$time}{description}'"; + } else { + $Entry{$channel}{$time}{description} = "DTV: '$description' VDR: ''"; + } + } + } + } + close (FI); +} + +sub read_channel_list { + my ($old, $new); + open (FI,"$ENV{HOME}/.master-timer/convert-channel-list") or die ("Can't read channel-List"); + while (<FI>) { + chomp; + ($old, $new) = split (/\|/); + $channel{$old} = $new; + } + close (FI); +} + +sub print_VDR() { + my ($channel, $title, $time); + foreach $channel (sort keys %Entry) { + print "C 1 $channel\n"; + foreach $time (sort keys %{%Entry->{$channel}}) { + if ($Entry{$channel}{$time}{duration}) { + print "E 1 $time $Entry{$channel}{$time}{duration}\n"; + print "K $Entry{$channel}{$time}{category}\n" if ($Entry{$channel}{$time}{category}); + print "T $Entry{$channel}{$time}{title}\n"; + print "S $Entry{$channel}{$time}{subtitle}\n" if ($Entry{$channel}{$time}{subtitle}); + print "D $Entry{$channel}{$time}{description}\n" if ($Entry{$channel}{$time}{description}); + print "e\n"; + } + } + print "c\n"; + } +} diff --git a/Tools/master-timer/convert-oldtorecord.pl b/Tools/master-timer/convert-oldtorecord.pl new file mode 100755 index 0000000..853c20b --- /dev/null +++ b/Tools/master-timer/convert-oldtorecord.pl @@ -0,0 +1,61 @@ +#!/usr/bin/perl + +while (<>) + { + chomp; + if ($_ && !(/^\#/)) + { + ($title, $subtitle, $description, $channel, $timeframe, $prio, $timer_title, $margin, $machine) = split (/\|/,$_); + + if ($timer_title) { + print "[$timer_title]\n"; + } elsif ($title) { + print "[$title]\n"; + } elsif ($subtitle) { + print "[$subtitle]\n"; + } elsif ($description) { + print "[$description]\n"; + } else { + die ("Illegal Format"); + } + + # Accept torecord only if it is for the current machine + if ($title) + { + print "Title = $title\n"; + } + if ($subtitle) + { + print "Subtitle = $subtitle\n"; + } + if ($description) + { + print "Description = $description\n"; + } + if ($channel) + { + print "Channel = $channel\n"; + } + if ($timeframe) + { + print "Timeframe = $timeframe\n"; + } + if ($prio) + { + print "Prio = $prio\n"; + } + if ($timer_title) + { + print "Timertitle = $timer_title\n"; + } + if ($margin) + { + print "Margin = $margin\n"; + } + if ($machine) + { + print "Instance = $machine\n"; + } + print "\n"; + } + } diff --git a/Tools/master-timer/master-timer.pl b/Tools/master-timer/master-timer.pl index 3b98acc..5ddf909 100755 --- a/Tools/master-timer/master-timer.pl +++ b/Tools/master-timer/master-timer.pl @@ -5,6 +5,8 @@ use strict; use Socket; # For converting the Timers, read from VDR, back to Unix-Timestamps use Time::Local; +# For parsing the command line +use Getopt::Std; # Debugmode # You have to add the following numbers to build the debug-var @@ -13,7 +15,9 @@ use Time::Local; # 4 : Show when a timer will be deleted # 8 : Dump the "Done" REs # 16 : Verbose Config-Reading -my $debug = 0; +# 32 : Dump Program Variable +# 64 : Excessive deepblack/torecord debuging +my $debug = 6; # The Supervariable Program # %Program{$title}{$channel}{$time}{duration} @@ -23,26 +27,51 @@ my $debug = 0; # The Supervariable Timer # %Timer{$time}{$channel}{$title}{duration} # {subtitle} +# {description} # {prio} +# {lifetime} # {real_title} # {VDR} (Already programmed) # The Value of VDR is ">0" for the position in the Timer-List or "R" for a "Repeating" Timer. # A Value of >1.000.000 is a Master Timer-Timer which is already programmed into VDR +# The Supervariable torecord/deepblack +# $torecord{timercount} +# {titleRE} +# {subtitleRE} +# {descriptionRE} +# {title}[COUNT] +# {subtitle}[COUNT] +# {description}[COUNT] +# {timeframe}[COUNT] +# {blackchannel}[COUNT] or {channel}[COUNT] +# {weekday}[COUNT] +# {minlength}[COUNT] +# {maxlength}[COUNT] +# {prio}[COUNT] +# {timertitle}[COUNT] +# {marginstart}[COUNT] +# {marginstop}[COUNT] +# {instance}[COUNT] + # Variable-Definition my (%Program, @channels, %channels, %Timer); # Which Subtitles are Movies my ($subtitle_movie); +my ($test_subtitle_movie); # Blacklist -my ($title_deepblack); +my (%deepblack); # What is already recorded/Should not be recorded my ($title_done, $subtitle_done); # What to record -my ($title_torecord, $subtitle_torecord, $description_torecord, @title_torecord, @subtitle_torecord, @description_torecord, @channel_torecord, @timeframe_torecord, @prio_torecord, @timer_title_torecord, $num_torecord, @marginstart_torecord, @marginstop_torecord, @machine_torecord); +my (%torecord); + +# The Commandline +my (%Opts); # Default Priority for Timers (Config: defaultprio) my $default_prio = 50; @@ -63,1107 +92,1321 @@ my @Dest = ("localhost:2001"); # Config: Dest # Which VDR-Instance shall be used my $currentVDR = 1; -# Working-Variables -my ($title, $duration, $subtitle, $channel, $time, $description, $hit); -my (@time, @date); +# Where are the Config-Files +my $configdir = "$ENV{HOME}/.master-timer"; -sub sub_die - { - my ($error) = @_; - &closesocket(); - die "$error"; - } +# Should the description be transfered to VDR? +my $Description = 0; +# Working-Variables +my ($title, $duration, $subtitle, $channel, $time, $description, $category, $hit); +my (@time, @date); -if ($ARGV[0]) - { - $currentVDR = $ARGV[0]; - } +END { + &closesocket(); +} &init(); &dumpdone() if ($debug & 8); -&dumptorecord() if ($debug & 1); +&dumptorecord("torecord") if ($debug & 1); +&dumptorecord("deepblack") if ($debug & 1); +print "Subtitle-Movie \"$subtitle_movie\"\n" if($debug & 1); +# If we only have to dump the running series then exit after dumping them +if ($Opts{s}) { + &dumpepgdata; + exit 0; +} +&processdone(); &fetchVDRTimers(); &process_torecord(); print "Timers before joining\n" if ($debug & 2 && $jointimers); &dumptimers() if ($debug & 2); -if ($jointimers) - { - &jointimers(); - print "Timers after joining\n" if ($debug & 2); - &dumptimers() if ($debug & 2); - } + +if ($jointimers) { + &jointimers(); + print "Timers after joining\n" if ($debug & 2); + &dumptimers() if ($debug & 2); +} + +&dumpepgdata if ($debug & 32); &printtimers(); &transfertimers(); -&closesocket(); + +# +# End of Program +# # # Subfunctions # -sub dumpdone() - { - print "Start Done-dump\n"; - print "Titledone: \"$title_done\"\n"; - print "Subtitledone \"$subtitle_done\"\n"; - print "End Done-dump\n"; +sub dumpdone() { + print "Start Done-dump\n"; + print "Titledone: \"$title_done\"\n"; + print "Subtitledone \"$subtitle_done\"\n"; + print "End Done-dump\n"; +} + +sub dumpepgdata () { + print "Start EPG-Dump\n"; + foreach $title (sort keys %Program) { + foreach $channel (sort keys %{%Program->{$title}}) { + foreach $time (sort {$a <=> $b} keys %{%Program->{$title}->{$channel}}) { + print "Title: \"$title\" "; + if (!$Opts{s}) { + print "Subtitle: \"$Program{$title}{$channel}{$time}{subtitle}\" " if ($Program{$title}{$channel}{$time}{subtitle}); + print "Time: \"$time\""; + } + print "Channel: \"$channel\""; + print "\n"; + if ($Opts{s}) { + last; + } + } + } + } + print "End EPG-Dump\n"; +} + + +sub dumptorecord() { + my ($context) = shift; + my ($rContext); + + if ($context eq "torecord") { + $rContext = \%torecord; + } elsif ($context eq "deepblack") { + $rContext = \%deepblack; + } else { + die ("Illegal Context"); } -sub dumptorecord() - { - print "Start Torecord-dump\n"; - print "Regex-Title: $title_torecord\n"; - print "Regex-Subtitle: $subtitle_torecord\n"; - print "Regex-Description: $description_torecord\n"; - foreach my $num (0 .. $num_torecord) - { - print "Timer Number $num: "; - - print "Title: \"$title_torecord[$num]\" " if ($title_torecord[$num]); - print "Title: \"\" " unless ($title_torecord[$num]); - - print "Subtitle: \"$subtitle_torecord[$num]\" "if ($subtitle_torecord[$num]); - print "Subtitle: \"\" " unless ($subtitle_torecord[$num]); + print "Start $context-dump\n"; + print "Regex-Title: $$rContext{titleRE}\n"; + print "Regex-Subtitle: $$rContext{subtitleRE}\n"; + print "Regex-Description: $$rContext{descriptionRE}\n"; + foreach my $num (0 .. $$rContext{timercount}) { + print "Entry Number $num: "; + + print "Title: \"$$rContext{title}[$num]\" " if ($$rContext{title}[$num]); + print "Title: \"\" " unless ($$rContext{title}[$num]); + + print "Subtitle: \"$$rContext{subtitle}[$num]\" "if ($$rContext{subtitle}[$num]); + print "Subtitle: \"\" " unless ($$rContext{subtitle}[$num]); + + print "Description: \"$$rContext{description}[$num]\" " if ($$rContext{description}[$num]); + print "Description: \"\" " unless ($$rContext{description}[$num]); + + print "Category: \"$$rContext{category}[$num]\" " if ($$rContext{category}[$num]); + print "Category: \"\" " unless ($$rContext{category}[$num]); - print "Description: \"$description_torecord[$num]\" " if ($description_torecord[$num]); - print "Description: \"\" " unless ($description_torecord[$num]); + print "Timeframe: \"$$rContext{timeframe}[$num]\" " if ($$rContext{timeframe}[$num]); + print "Timeframe: \"\" " unless ($$rContext{timeframe}[$num]); - print "Timeframe: \"$timeframe_torecord[$num]\" " if ($timeframe_torecord[$num]); - print "Timeframe: \"\" " unless ($timeframe_torecord[$num]); + print "Weekday: \"$$rContext{weekday}[$num]\" " if ($$rContext{weekday}[$num]); + print "Weekday: \"\" " unless ($$rContext{weekday}[$num]); - print "Channel: \"". join (";",@{$channel_torecord[$num]})."\" " if ($channel_torecord[$num]); - print "Channel: \"\" " unless ($channel_torecord[$num]); + print "Channel: \"$$rContext{channel}[$num]\" " if ($$rContext{channel}[$num]); + print "Channel: \"\" " unless ($$rContext{channel}[$num]); - print "Prio: \"$prio_torecord[$num]\" " if ($prio_torecord[$num]); - print "Prio: \"\" " unless ($prio_torecord[$num]); + print "Blackchannel: \"$$rContext{blackchannel}[$num]\" " if ($$rContext{blackchannel}[$num]); + print "Blackchannel: \"\" " unless ($$rContext{blackchannel}[$num]); - print "Timertitle: \"$timer_title_torecord[$num]\" " if ($timer_title_torecord[$num]); - print "Timertitle: \"\" " unless ($timer_title_torecord[$num]); + print "Prio: \"$$rContext{prio}[$num]\" " if ($$rContext{prio}[$num]); + print "Prio: \"\" " unless ($$rContext{prio}[$num]); + + print "Timertitle: \"$$rContext{timertitle}[$num]\" " if ($$rContext{timertitle}[$num]); + print "Timertitle: \"\" " unless ($$rContext{timertitle}[$num]); - print "Marginstart: \"$marginstart_torecord[$num]\" " if ($marginstart_torecord[$num]); - print "Marginstart: \"\" " unless ($marginstart_torecord[$num]); + print "Marginstart: \"$$rContext{marginstart}[$num]\" " if ($$rContext{marginstart}[$num]); + print "Marginstart: \"\" " unless ($$rContext{marginstart}[$num]); - print "Marginstop: \"$marginstop_torecord[$num]\" " if ($marginstop_torecord[$num]); - print "Marginstop: \"\" " unless ($marginstop_torecord[$num]); + print "Marginstop: \"$$rContext{marginstop}[$num]\" " if ($$rContext{marginstop}[$num]); + print "Marginstop: \"\" " unless ($$rContext{marginstop}[$num]); - print "Machine: \"$machine_torecord[$num]\" " if ($machine_torecord[$num]); - print "Machine: \"\" " unless ($machine_torecord[$num]); + print "Minlength: \"$$rContext{minlength}[$num]\" " if ($$rContext{minlength}[$num]); + print "Minlength: \"\" " unless ($$rContext{minlength}[$num]); - print "\n"; - } - print "End Torecord-dump\n"; + print "Maxlength: \"$$rContext{maxlength}[$num]\" " if ($$rContext{maxlength}[$num]); + print "Maxlength: \"\" " unless ($$rContext{maxlength}[$num]); + + print "Instance: \"$$rContext{instance}[$num]\" " if ($$rContext{instance}[$num]); + print "Instance: \"\" " unless ($$rContext{instance}[$num]); + + print "\n"; } + print "End $context-dump\n"; +} -sub dumptimers() - { - print "Start Timers-dump\n"; - foreach $time (sort {$a <=> $b} keys %Timer) - { - foreach $channel (sort keys %{%Timer->{$time}}) - { - foreach $title (sort keys %{%Timer->{$time}->{$channel}}) - { - my ($prio, @time, @date, @time2); - my ($realtitle); - @time = &GetTime ($time); - @date = &GetDay ($time); - @time2 = &GetTime ($time + $Timer{$time}{$channel}{$title}{duration}); - $subtitle = $Timer{$time}{$channel}{$title}{subtitle}; - $prio = $Timer{$time}{$channel}{$title}{prio}; - $realtitle = $Timer{$time}{$channel}{$title}{real_title}; - print "2:$channels{$channel}{number}:$date[1]:$time[0]$time[1]:$time2[0]$time2[1]:$prio:99:$title:Title: \"$realtitle\"||Subtitle: \"$subtitle\":$Timer{$time}{$channel}{$title}{VDR}\n"; - } - } +sub dumptimers() { + print "Start Timers-dump\n"; + foreach $time (sort {$a <=> $b} keys %Timer) { + foreach $channel (sort keys %{%Timer->{$time}}) { + foreach $title (sort keys %{%Timer->{$time}->{$channel}}) { + my ($prio, $lifetime, @time, @date, @time2); + my ($realtitle); + @time = &GetTime ($time); + @date = &GetDay ($time); + @time2 = &GetTime ($time + $Timer{$time}{$channel}{$title}{duration}); + $subtitle = $Timer{$time}{$channel}{$title}{subtitle}; + $prio = $Timer{$time}{$channel}{$title}{prio}; + $lifetime = $Timer{$time}{$channel}{$title}{lifetime}; + $realtitle = $Timer{$time}{$channel}{$title}{real_title}; + print "2:$channels{$channel}{number}:$date[1]:$time[0]$time[1]:$time2[0]$time2[1]:$prio:$lifetime:$title:Title: \"$realtitle\"||Subtitle: \"$subtitle\":$Timer{$time}{$channel}{$title}{VDR}\n"; } - print "End Timers-dump\n"; + } } + print "End Timers-dump\n"; +} -sub printtimers() - { - foreach $time (sort {$a <=> $b} keys %Timer) - { - foreach $channel (sort keys %{%Timer->{$time}}) - { - foreach $title (sort keys %{%Timer->{$time}->{$channel}}) - { - my ($prio, @time, @date, @time2); - if ($Timer{$time}{$channel}{$title}{VDR} eq 0) - { - my ($realtitle); - @time = &GetTime ($time); - @date = &GetDay ($time); - @time2 = &GetTime ($time + $Timer{$time}{$channel}{$title}{duration}); - $subtitle = $Timer{$time}{$channel}{$title}{subtitle}; - $prio = $Timer{$time}{$channel}{$title}{prio}; - $realtitle = $Timer{$time}{$channel}{$title}{real_title}; - - print "2:$channels{$channel}{number}:$date[1]:$time[0]$time[1]:$time2[0]$time2[1]:$prio:99:$title:Title: \"$realtitle\"||Subtitle: \"$subtitle\"\n"; - } - } - } +sub printtimers() { + foreach $time (sort {$a <=> $b} keys %Timer) { + foreach $channel (sort keys %{%Timer->{$time}}) { + foreach $title (sort keys %{%Timer->{$time}->{$channel}}) { + my ($prio, $lifetime, @time, @date, @time2); + if ($Timer{$time}{$channel}{$title}{VDR} eq 0) { + my ($realtitle); + @time = &GetTime ($time); + @date = &GetDay ($time); + @time2 = &GetTime ($time + $Timer{$time}{$channel}{$title}{duration}); + $subtitle = $Timer{$time}{$channel}{$title}{subtitle}; + $prio = $Timer{$time}{$channel}{$title}{prio}; + $lifetime = $Timer{$time}{$channel}{$title}{lifetime}; + $realtitle = $Timer{$time}{$channel}{$title}{real_title}; + + print "2:$channels{$channel}{number}:$date[1]:$time[0]$time[1]:$time2[0]$time2[1]:$prio:$lifetime:$title:Title: \"$realtitle\"||Subtitle: \"$subtitle\"\n"; + } } + } } +} -sub transfertimers() - { - foreach $time (sort {$a <=> $b} keys %Timer) - { - foreach $channel (sort keys %{%Timer->{$time}}) - { - foreach $title (sort keys %{%Timer->{$time}->{$channel}}) - { - my ($prio, @time, @date, @time2, $realtitle, $result); - if ($Timer{$time}{$channel}{$title}{VDR} eq 0) - { - @time = &GetTime ($time); - @date = &GetDay ($time); - @time2 = &GetTime ($time + $Timer{$time}{$channel}{$title}{duration}); - $subtitle = $Timer{$time}{$channel}{$title}{subtitle}; - $prio = $Timer{$time}{$channel}{$title}{prio}; - $realtitle = $Timer{$time}{$channel}{$title}{real_title}; - - ($result) = GetSend ("newt 2:$channels{$channel}{number}:$date[1]:$time[0]$time[1]:$time2[0]$time2[1]:$prio:99:$title:Title: \"$realtitle\"||Subtitle: \"$subtitle\""); - print "Timer: $result" if ($debug & 2); - } - } +sub transfertimers() { + foreach $time (sort {$a <=> $b} keys %Timer) { + foreach $channel (sort keys %{%Timer->{$time}}) { + foreach $title (sort keys %{%Timer->{$time}->{$channel}}) { + my ($prio, $lifetime, $description, @time, @date, @time2, $realtitle, $result); + if ($Timer{$time}{$channel}{$title}{VDR} eq 0) { + @time = &GetTime ($time); + @date = &GetDay ($time); + @time2 = &GetTime ($time + $Timer{$time}{$channel}{$title}{duration}); + $subtitle = $Timer{$time}{$channel}{$title}{subtitle}; + $prio = $Timer{$time}{$channel}{$title}{prio}; + $lifetime = $Timer{$time}{$channel}{$title}{lifetime}; + if ($Description) { + $description = "||Description :\"$Timer{$time}{$channel}{$title}{description}\""; + } else { + $description = ""; } + $realtitle = $Timer{$time}{$channel}{$title}{real_title}; + + ($result) = GetSend ("newt 2:$channels{$channel}{number}:$date[1]:$time[0]$time[1]:$time2[0]$time2[1]:$prio:$lifetime:$title:Title: \"$realtitle\"||Subtitle: \"$subtitle\"$description"); + print "Timer: $result" if ($debug & 2); + } } + } } +} # Convert the Unix-Time-Stamp into "month" and "Day of month" -sub GetDay - { - my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(shift); - $mon++; - $mon = sprintf ("%02i",$mon); - $mday = sprintf ("%02i",$mday); - return ($mon, $mday); - } +sub GetDay { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(shift); + $mon++; + $mon = sprintf ("%02i",$mon); + $mday = sprintf ("%02i",$mday); + return ($mon, $mday); +} +# Convert the Unix-Time-Stramp into Weekday +sub GetWDay { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(shift); + return ($wday); +} # Convert the Unix-Time-Stramp into "hour" and "minute" -sub GetTime - { - my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(shift); - $hour = sprintf ("%02i",$hour); - $min = sprintf ("%02i",$min); - return ($hour, $min); - } +sub GetTime { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(shift); + $hour = sprintf ("%02i",$hour); + $min = sprintf ("%02i",$min); + return ($hour, $min); +} # Workaround some EPG-Bugs -sub correct_epg_data - { - if ($subtitle) - { - # For Pro-7. Remove $title from $subtitle - $subtitle =~ s/$title\s\/\s//; +sub correct_epg_data { + if ($subtitle) { + # For Pro-7. Remove $title from $subtitle + $subtitle =~ s/\Q$title\E\s\/\s//; - # For VOX & VIVA. The Format it '"<Subtitle>". <Description>' - if ($subtitle =~ /^\"(.*?)\"\.\s(.*)/) - { - # Lets see if there are Channels that where the VOX/VIVA scheme matches, but also have a description - if ($description) - { - sub_die ("Subtitle: \"$subtitle\"\nDescription\"$description\"\n"); - } - $subtitle = $1; - $description = $2; - } - elsif ($channel eq "VIVA") - { - if ($subtitle =~ /^\s(.*)/) - { - $subtitle = ""; - $description = $1; - } - } + # For VOX & VIVA. The Format it '"<Subtitle>". <Description>' + if ($subtitle =~ /^\"(.*?)\"\.\s(.*)/) { + # Lets see if there are Channels that where the VOX/VIVA scheme matches, but also have a description + if ($description) { + my $one = $1; + my $two = $2; + if ($description =~ /^DTV\:\s\'(.*)\' VDR:\s\'\'$/) { + $description = "DTV: '$1' VDR: '$two'"; + $subtitle = $one; + } else { + die ("Title: \"$title\" Channel: \"$channel\" Subtitle: \"$subtitle\"\nDescription: \"$description\"\n"); + } } - - # Workaround for the broken PRO-7/Kabel-1 EPG-Date. If Time is between 00.00 and 05.00 the time is shifted forward by a day - if ($channel eq "Pro-7" || $channel eq "Kabel-1") - { - my (@time); - @time = GetTime ($time); - if ($time[0] >= 0 && ($time[0] <= 4 || ($time[0] == 5 && $time[1] == 0))) - { - $time += 24*60*60; - } + $subtitle = $1; + $description = $2; + } + elsif ($channel eq "VIVA") { + if ($subtitle =~ /^\s(.*)/) { + $subtitle = ""; + $description = $1; } + } + } + + # Workaround for the broken PRO-7/Kabel-1 EPG-Date. If Time is between 00.00 and 05.00 the time is shifted forward by a day + if ($channel eq "Pro-7" || $channel eq "Kabel-1") { + my (@time); + @time = GetTime ($time); + if ($time[0] >= 0 && ($time[0] <= 4 || ($time[0] == 5 && $time[1] == 0))) { + $time += 24*60*60; + } + } } # Add a Recording into the "to record"-List -sub addtimer - { - my ($hit, $title, $realtitle, $subtitle, $channel, $time, $duration, $prio, $VDR, $time2, $title2, $channel2, $marginstart, $marginstop); - ($title, $realtitle, $subtitle, $channel, $time, $duration, $prio, $VDR, $marginstart, $marginstop) = @_; -# print "Title: \"$title\" Realtitle: \"$realtitle\" Subtitle: \"$subtitle\" Channel: \"$channel\" Time: \"$time\" Duration: \"$duration\" Prio: \"$prio\" VDR: \"$VDR\"\n"; - - $hit = 1; - - foreach $time2 (sort keys %Timer) - { - foreach $title2 (sort keys %{%Timer->{$time2}->{$channel}}) - { - my ($ctime, $ctime2); - $ctime = $time2; - $ctime2 = $time2 + $Timer{$time2}{$channel}{$title2}{duration}; - - if (($time >= $ctime) && ($time <= $ctime2)) - { - undef $hit; - } - } +sub addtimer { + my ($title, $realtitle, $subtitle, $channel, $time, $duration, $prio, $lifetime, $description, $VDR, $time2, $title2, $channel2, $marginstart, $marginstop); + ($title, $realtitle, $subtitle, $description, $channel, $time, $duration, $prio, $lifetime, $VDR, $marginstart, $marginstop) = @_; +# print "Title: \"$title\" Realtitle: \"$realtitle\" Subtitle: \"$subtitle\" Channel: \"$channel\" Time: \"$time\" Duration: \"$duration\" Prio: \"$prio\" VDR: \"$VDR\"\n"; + + foreach $time2 (sort keys %Timer) { + foreach $title2 (sort keys %{%Timer->{$time2}->{$channel}}) { + my ($ctime, $ctime2); + $ctime = $time2; + $ctime2 = $time2 + $Timer{$time2}{$channel}{$title2}{duration}; + + if (($time >= $ctime) && ($time <= $ctime2)) { + return; } + } + } + $time -= $marginstart; + $duration += $marginstart + $marginstop; + $Timer{$time}{$channel}{$title}{duration}=$duration; + $Timer{$time}{$channel}{$title}{subtitle}=$subtitle; + $Timer{$time}{$channel}{$title}{description}=$description; + $Timer{$time}{$channel}{$title}{prio}=$prio; + $Timer{$time}{$channel}{$title}{lifetime}=$lifetime; + $Timer{$time}{$channel}{$title}{VDR}=$VDR; + $Timer{$time}{$channel}{$title}{real_title}=$realtitle; +} - if ($hit) - { - $time -= $marginstart; - $duration += $marginstart + $marginstop; - $Timer{$time}{$channel}{$title}{duration}=$duration; - $Timer{$time}{$channel}{$title}{subtitle}=$subtitle; - $Timer{$time}{$channel}{$title}{prio}=$prio; - $Timer{$time}{$channel}{$title}{VDR}=$VDR; - $Timer{$time}{$channel}{$title}{real_title}=$realtitle; - } - } +sub deltimer() { + my ($time, $channel, $title, $delete_from_VDR); + ($time, $channel, $title, $delete_from_VDR) = @_; -sub deltimer() - { - my ($time, $channel, $title, $delete_from_VDR); - ($time, $channel, $title, $delete_from_VDR) = @_; - -# if ($delete_from_VDR) -# { -# if ($Timer{$time}{$channel}{$title}{VDR}) -# { -# if ($Timer{$time}{$channel}{$title}{VDR} =~ s/ ^R/) -# { -# print "Error: A Repeating-Timer can't be deleted from VDR: \"$title\"\n"; -# } -# elsif ($Timer{$time}{$channel}{$title}{VDR} < 1000000) -# { -# print "A User-Programmed Timer has been deleted from VDR: \"$title\"\n"; -# } -# else -# { -# -# } -# } +# if ($delete_from_VDR) { +# if ($Timer{$time}{$channel}{$title}{VDR}) { +# if ($Timer{$time}{$channel}{$title}{VDR} =~ s/ ^R/) { +# print "Error: A Repeating-Timer can't be deleted from VDR: \"$title\"\n"; +# } +# elsif ($Timer{$time}{$channel}{$title}{VDR} < 1000000) { +# print "A User-Programmed Timer has been deleted from VDR: \"$title\"\n"; +# } +# else { +# # } +# } +# } + + delete $Timer{$time}{$channel}{$title}{duration}; + delete $Timer{$time}{$channel}{$title}{subtitle}; + delete $Timer{$time}{$channel}{$title}{prio}; + delete $Timer{$time}{$channel}{$title}{VDR}; + delete $Timer{$time}{$channel}{$title}{real_title}; + delete $Timer{$time}{$channel}{$title}; + delete $Timer{$time}{$channel} if (keys %{ $Timer{$time}{$channel} } == 1); + delete $Timer{$time} if (keys %{ $Timer{$time} } == 1); +} - delete $Timer{$time}{$channel}{$title}{duration}; - delete $Timer{$time}{$channel}{$title}{subtitle}; - delete $Timer{$time}{$channel}{$title}{prio}; - delete $Timer{$time}{$channel}{$title}{VDR}; - delete $Timer{$time}{$channel}{$title}{real_title}; - delete $Timer{$time}{$channel}{$title}; - delete $Timer{$time}{$channel} if (keys %{ $Timer{$time}{$channel} } == 1); - delete $Timer{$time} if (keys %{ $Timer{$time} } == 1); - } +sub delprogram() { + my ($title, $channel, $time); + ($title, $channel, $time) = @_; -sub jointimers - { - # - # FIXME: 2 Timers on the same channel will always be joined. - # It should be checked if there is another DVB-Card available. - # - # FIXME2: When one timer is already programmed in VDR, delete that timer in VDR. - my ($running, $counter, @times, $channel, $title, $channel2, $title2); - $running = 1; - outer: while ($running) - { - $counter = 0; - @times = sort {$a <=> $b} keys %Timer; - - # We only need to check till the second last timer. The last one can't have a overlapping one. - while ($counter < $#times) - { - foreach $channel (sort keys %{%Timer->{$times[$counter]}}) - { - foreach $title (sort keys %{%Timer->{$times[$counter]}->{$channel}}) - { - if ($times[$counter + 1] < ($times[$counter] + $Timer{$times[$counter]}{$channel}{$title}{duration})) - { - foreach $channel2 (sort keys %{%Timer->{$times[$counter + 1]}}) - { - foreach $title2 (sort keys %{%Timer->{$times[$counter + 1]}->{$channel}}) - { - if ($channel eq $channel2) - { - my ($duration, $subtitle, $prio, $realtitle, $duration2, $subtitle2, $prio2, $realtitle2); - # Values from Lower-Timer - $duration = $Timer{$times[$counter]}{$channel}{$title}{duration}; - $subtitle = $Timer{$times[$counter]}{$channel}{$title}{subtitle}; - $prio = $Timer{$times[$counter]}{$channel}{$title}{prio}; - $realtitle = $Timer{$times[$counter]}{$channel}{$title}{real_title}; - - # Values from Higher-Timer - $duration2 = $Timer{$times[$counter + 1]}{$channel2}{$title2}{duration}; - $subtitle2 = $Timer{$times[$counter + 1]}{$channel2}{$title2}{subtitle}; - $prio2 = $Timer{$times[$counter + 1]}{$channel2}{$title2}{prio}; - $realtitle2 = $Timer{$times[$counter + 1]}{$channel2}{$title2}{real_title}; - - # Use the Higher Priority for the new Timer - $prio = ($prio > $prio2) ? $prio : $prio2; - - # Delete the two "Obsolet" Timers - &deltimer ($times[$counter], $channel, $title); - &deltimer ($times[$counter + 1], $channel2, $title2); - - # And set the new one - &addtimer ("$title + $title2", "$realtitle\~$realtitle2", "$subtitle\~$subtitle2", $channel, $times[$counter], $duration2 + ($times[$counter + 1 ] - $times[$counter]),$prio,0,0,0); - - # Now a Value is "missing", so we will redo the whole thing. (This will do three-times JOIN correct) - redo outer; - } - } - } - } - } + delete $Program{$title}{$channel}{$time}; + delete $Program{$title}{$channel} if (keys %{ $Program{$title}{$channel} } == 1); + delete $Program{$title} if (keys %{ $Program{$title} } == 1); +} + +sub jointimers { + # + # FIXME: 2 Timers on the same channel will always be joined. + # It should be checked if there is another DVB-Card available. + # + # FIXME2: When one timer is already programmed in VDR, delete that timer in VDR. + my ($running, $counter, @times, $channel, $title, $channel2, $title2); + $running = 1; + outer: while ($running) { + $counter = 0; + @times = sort {$a <=> $b} keys %Timer; + + # We only need to check till the second last timer. The last one can't have a overlapping one. + while ($counter < $#times) { + foreach $channel (sort keys %{%Timer->{$times[$counter]}}) { + foreach $title (sort keys %{%Timer->{$times[$counter]}->{$channel}}) { + if ($times[$counter + 1] < ($times[$counter] + $Timer{$times[$counter]}{$channel}{$title}{duration})) { + foreach $channel2 (sort keys %{%Timer->{$times[$counter + 1]}}) { + foreach $title2 (sort keys %{%Timer->{$times[$counter + 1]}->{$channel}}) { + if ($channel eq $channel2) { + my ($duration, $subtitle, $description, $prio, $lifetime, $realtitle, $duration2, $subtitle2, $description2, $prio2, $lifetime2, $realtitle2); + # Values from Lower-Timer + $duration = $Timer{$times[$counter]}{$channel}{$title}{duration}; + $subtitle = $Timer{$times[$counter]}{$channel}{$title}{subtitle}; + $description = $Timer{$times[$counter]}{$channel}{$title}{description}; + $prio = $Timer{$times[$counter]}{$channel}{$title}{prio}; + $lifetime = $Timer{$times[$counter]}{$channel}{$title}{lifetime}; + $realtitle = $Timer{$times[$counter]}{$channel}{$title}{real_title}; + + # Values from Higher-Timer + $duration2 = $Timer{$times[$counter + 1]}{$channel2}{$title2}{duration}; + $subtitle2 = $Timer{$times[$counter + 1]}{$channel2}{$title2}{subtitle}; + $description2 = $Timer{$times[$counter + 1]}{$channel2}{$title2}{description}; + $prio2 = $Timer{$times[$counter + 1]}{$channel2}{$title2}{prio}; + $lifetime2 = $Timer{$times[$counter + 1]}{$channel2}{$title2}{lifetime}; + $realtitle2 = $Timer{$times[$counter + 1]}{$channel2}{$title2}{real_title}; + + # Use the Higher Priority/Lifetime for the new Timer + $prio = ($prio > $prio2) ? $prio : $prio2; + $lifetime = ($lifetime > $lifetime2) ? $lifetime : $lifetime2; + + # Delete the two "Obsolet" Timers + &deltimer ($times[$counter], $channel, $title); + &deltimer ($times[$counter + 1], $channel2, $title2); + + # And set the new one + &addtimer ("$title + $title2", "$realtitle\~$realtitle2", "$subtitle\~$subtitle2", "$description\~$description2", $channel, $times[$counter], $duration2 + ($times[$counter + 1 ] - $times[$counter]),$prio,$lifetime,0,0,0); + + # Now a Value is "missing", so we will redo the whole thing. (This will do three-times JOIN correct) + redo outer; + } } - $counter++; + } } - undef $running; + } } + $counter++; + } + undef $running; } +} -sub process_torecord - { - my ($first_hit, $prio, $timer_title); - foreach $title (sort keys %Program) - { - foreach $channel (sort keys %{%Program->{$title}}) - { - foreach $time (sort {$a <=> $b} keys %{%Program->{$title}->{$channel}}) - { - undef $hit; - - # First look if any of the Title/Subtitle/Description REs match - if ($title =~ /$title_torecord/i) - { - $hit = 1; - } - elsif ($Program{$title}{$channel}{$time}{subtitle} && $Program{$title}{$channel}{$time}{subtitle} =~ /$subtitle_torecord/i) - { - $hit = 1; - } - elsif ($Program{$title}{$channel}{$time}{description} && $Program{$title}{$channel}{$time}{description} =~ /$description_torecord/i) - { - $hit = 1; - } - - # Now look if we have a "exact" hit - if ($hit) - { - my ($counter); - undef $hit; - foreach $counter (0 .. $num_torecord) - { - - if ($title_torecord[$counter]) - { - if (!($title =~ /$title_torecord[$counter]/i)) - { - next; - } - } - - if ($subtitle_torecord[$counter]) - { - if (!($Program{$title}{$channel}{$time}{subtitle} =~ /$subtitle_torecord[$counter]/i)) - { - next; - } - elsif (!$title_torecord[$counter] && !$description_torecord[$counter]) - { - next; - } - } - - if ($description_torecord[$counter]) - { - if ($Program{$title}{$channel}{$time}{description}) - { - if (!($Program{$title}{$channel}{$time}{description} =~ /$description_torecord[$counter]/i)) - { - next; - } - } - elsif (!$title_torecord[$counter] && !$subtitle_torecord[$counter]) - { - next; - } - } - - if ($channel_torecord[$counter]) - { - my ($hit); - # Blacklist-Mode - if ($channel_torecord[$counter][0] =~ /^!/) - { - $hit = 1; - foreach (0 .. $#{$channel_torecord[$counter]}) - { - # Strip a possibel "!" Charactar - $channel_torecord[$counter][$_] =~ /^!?(.*)/; - if ($channel =~ /^$1$/) - { - undef $hit; - last; - } - } - } - # Whitelist-Mode - else - { - undef $hit; - foreach (0 .. $#{$channel_torecord[$counter]}) - { - # Strip a possibel "!" Charactar - $channel_torecord[$counter][$_] =~ /^!?(.*)/; - if ($channel =~ /^$1$/) - { - $hit = 1; - last ; - } - } - } - if (!$hit) - { - next; - } - } - - if ($timeframe_torecord[$counter]) - { - my (@time, $time2, $ctime, $ctime2); - @time = GetTime($time); - $time2 = "$time[0]$time[1]"; - - ($ctime, $ctime2) = split (/\-/,$timeframe_torecord[$counter]); - - if (!$ctime) - { - $ctime = "0"; - } - if (!$ctime2) - { - $ctime2 = "2400"; - } - - if ($ctime < $ctime2) - { - if (!($time2 >= $ctime && $time2 <= $ctime2)) - { - next; - } - } - else - { - if (!(($time2 >= $ctime && $time2 <= "2400") || ($time2 >= "0" && $time2 <= $ctime2))) - { - next; - } - } - } - - if ($prio_torecord[$counter]) - { - $prio = $prio_torecord[$counter]; - } - else - { - $prio = 50; - } - - # What Title to use for the timer - if ($timer_title_torecord[$counter]) - { - $timer_title = $timer_title_torecord[$counter] - } - elsif ($title_torecord[$counter]) - { - $timer_title = $title_torecord[$counter] - } - else - { - $timer_title = $title; - } - - my ($subtitle); - if ($Program{$title}{$channel}{$time}{subtitle}) - { - $subtitle = $Program{$title}{$channel}{$time}{subtitle}; - } - else - { - $subtitle = ""; - } - - &addtimer ($timer_title,$title,$subtitle,$channel,$time,$Program{$title}{$channel}{$time}{duration},$prio,0,$marginstart_torecord[$counter],$marginstop_torecord[$counter]); - last; - } - } - } +sub process_torecord { + my ($subtitle, $description, $prio, $lifetime, $timertitle, $counter); + foreach $title (sort keys %Program) { + foreach $channel (sort keys %{%Program->{$title}}) { + foreach $time (sort {$a <=> $b} keys %{%Program->{$title}->{$channel}}) { + + $counter = &testtimer("torecord", $title, $channel, $time); + if ($counter ne "Nothing") { + + # What Priority + if ($torecord{prio}[$counter]) { + $prio = $torecord{prio}[$counter]; + } + else { + $prio = 50; + } + + # What Lifetime + if ($torecord{lifetime}[$counter]) { + $lifetime = $torecord{lifetime}[$counter]; + } + else { + $lifetime = 50; + } + + # What Title to use for the timer + if ($torecord{timertitle}[$counter]) { + $timertitle = $torecord{timertitle}[$counter] } + elsif ($torecord{title}[$counter]) { + $timertitle = $torecord{title}[$counter] + } + else { + $timertitle = $title; + } + + # What subtitle to use + if ($Program{$title}{$channel}{$time}{subtitle}) { + $subtitle = $Program{$title}{$channel}{$time}{subtitle}; + } + else { + $subtitle = ""; + } + + # What Description to use + if ($Program{$title}{$channel}{$time}{description}) { + $description = $Program{$title}{$channel}{$time}{description}; + } + else { + $description = ""; + } + + &addtimer ($timertitle,$title,$subtitle,$description,$channel,$time,$Program{$title}{$channel}{$time}{duration},$prio,$lifetime,0,$torecord{marginstart}[$counter],$torecord{marginstop}[$counter]); + } } + } } +} -# Open the connection to VDR -sub initsocket - { - my ($Dest, $Port) = split (/\:/,$Dest[$currentVDR - 1],2); - my $iaddr = inet_aton($Dest); - my $paddr = sockaddr_in($Port, $iaddr); - - socket(SOCKET, PF_INET, SOCK_STREAM, getprotobyname('tcp')); - connect(SOCKET, $paddr) or sub_die ("Can't connect to VDR\n"); - select(SOCKET); $| = 1; - select(STDOUT); - - while (<SOCKET>) { - last if substr($_, 3, 1) ne "-"; - } +# Test if a torecord/deepblack Entry matches the current EPG-Data-Field +sub testtimer { + my ($context) = shift; + my ($title) = shift; + my ($channel) = shift; + my ($time) = shift; + my ($counter, $rContext); + + if ($context eq "torecord") { + $rContext = \%torecord; + } elsif ($context eq "deepblack") { + $rContext = \%deepblack; + } else { + die ("Illegal Context"); } -# Send a command to VDR and read back the result -sub GetSend - { - my ($command, @retval); - - while ($command = shift) - { - print SOCKET "$command\r\n"; - while (<SOCKET>) { - (@retval) = (@retval, $_); - last if substr($_, 3, 1) ne "-"; + if ($debug & 64) { + print "\n"; + print "Context: \"$context\"\nTitle: \"$title\"\n"; + print "Subtitle: \"$Program{$title}{$channel}{$time}{subtitle}\"\n" if ($Program{$title}{$channel}{$time}{subtitle}); + print "Description \"$Program{$title}{$channel}{$time}{description}\"\n" if ($Program{$title}{$channel}{$time}{description}); + print "Category \"$Program{$title}{$channel}{$time}{category}\"\n" if ($Program{$title}{$channel}{$time}{category}); + print "Channel: $channel\n"; + print "Time: $time\n"; + print "Duration: $Program{$title}{$channel}{$time}{duration}\n"; + } + + # First look if any of the Title/Subtitle/Description REs match + if ($title =~ /$$rContext{titleRE}/i) { + print "Title hit\n" if ($debug & 64); + } + elsif ($Program{$title}{$channel}{$time}{subtitle} && $Program{$title}{$channel}{$time}{subtitle} =~ /$$rContext{subtitleRE}/i) { + print "SubTitle hit\n" if ($debug & 64); + }elsif ($Program{$title}{$channel}{$time}{subtitle} && $test_subtitle_movie && $Program{$title}{$channel}{$time}{subtitle} =~ /$subtitle_movie/) { + print "SubTitle-Movie hit\n" if ($debug & 64); + } + elsif ($Program{$title}{$channel}{$time}{description} && $Program{$title}{$channel}{$time}{description} =~ /$$rContext{descriptionRE}/i) { + print "Description hit\n" if ($debug & 64); + } else { + # No "Fast"-hit. Exiting + return "Nothing"; + } + + # Now look if we have a "exact" hit + print "In Exact Hit Loop\n" if ($debug & 64); + foreach my $counter (0 .. $$rContext{timercount}) { + + print "Before Title Match\n" if ($debug & 64); + if ($$rContext{title}[$counter]) { + print "In Title Match \"$$rContext{title}[$counter]\"\n" if ($debug & 64); + if (!($title =~ /$$rContext{title}[$counter]/i)) { + print "Title rejected\n" if ($debug & 64); + next; + } + } + + print "Before Subtitle Match\n" if ($debug & 64); + if ($$rContext{subtitle}[$counter]) { + print "In Subtitle Match \"$$rContext{subtitle}[$counter]\"\n" if ($debug & 64); + if ($Program{$title}{$channel}{$time}{subtitle}) { + if ($$rContext{subtitle}[$counter] =~ /^movie$/i) { + if (!($Program{$title}{$channel}{$time}{subtitle} =~ /$subtitle_movie/i)) { + print "Subtitle rejected 1\n" if ($debug & 64); + next; + } + } + elsif ($$rContext{subtitle}[$counter] =~ /^\!movie$/i) { + if (($Program{$title}{$channel}{$time}{subtitle} =~ /$subtitle_movie/i)) { + print "Subtitle rejected 2\n" if ($debug & 64); + next; + } + } + elsif (!($Program{$title}{$channel}{$time}{subtitle} =~ /$$rContext{subtitle}[$counter]/i)) { + print "Subtitle rejected 3\n" if ($debug & 64); + next; + } + } else { + # We had a Subtitle, but epg.data did not have a subtitle for this record so no chance to record this + print "Subtitle rejected 4\n" if ($debug & 64); + next; + } + } + + print "Before Description Match\n" if ($debug & 64); + if ($$rContext{description}[$counter]) { + print "In Description Match \"$$rContext{description}[$counter]\"\n" if ($debug & 64); + if ($Program{$title}{$channel}{$time}{description}) { + if (!($Program{$title}{$channel}{$time}{description} =~ /$$rContext{description}[$counter]/i)) { + print "Description rejected 1\n" if ($debug & 64); + next; + } + } + elsif (!$$rContext{title}[$counter] && !$$rContext{subtitle}[$counter]) { + print "Description rejected 2\n" if ($debug & 64); + next; + } + } + + print "Before Category Match\n" if ($debug & 64); + if ($$rContext{category}[$counter]) { + print "In Category Match \"$$rContext{category}[$counter]\"\n" if ($debug & 64); + if ($Program{$title}{$channel}{$time}{category}) { + my ($left, $right); + ($left, $right) = split (/\//, $$rContext{category}[$counter]); + if ($left) { + print "In Category Match Left \"$left\"\n" if ($debug & 64); + if (!($Program{$title}{$channel}{$time}{category} =~ /^$left\//)) { + print "Category rejected 1\n" if ($debug & 64); + next; + } + } + if ($right) { + print "In Category Match Right \"$right\"\n" if ($debug & 64); + if (!($Program{$title}{$channel}{$time}{category} =~ /\/$right$/)) { + print "Category rejected 2\n" if ($debug & 64); + next; + } + } + } else { + # We had a Category, but the epg.data not. So discard this Entry + print "Category rejected 3\n" if ($debug & 64); + next; + } + } + + print "Before Channel Match\n" if ($debug & 64); + if ($$rContext{channel}[$counter]) { + print "In Channel Match Whitelist-Mode \"$$rContext{channel}[$counter]\"\n" if ($debug & 64); + if (!($channel =~ /$$rContext{channel}[$counter]/)) { + print "Channel rejected\n" if ($debug & 64); + next; + } + } + + if ($$rContext{blackchannel}[$counter]) { + print "In Channel Match Blacklist-Mode \"$$rContext{blackchannel}[$counter]\"\n" if ($debug & 64); + if ($channel =~ /$$rContext{blackchannel}[$counter]/) { + print "Channel rejected\n" if ($debug & 64); + next; + } + } + + print "Before Timeframe Match\n" if ($debug & 64); + if ($$rContext{timeframe}[$counter]) { + print "In Timeframe Match \"$$rContext{timeframe}[$counter]\"\n" if ($debug & 64); + my (@time, $time2, $ctime, $ctime2); + @time = GetTime($time); + $time2 = "$time[0]$time[1]"; + + ($ctime, $ctime2) = split (/\-/,$$rContext{timeframe}[$counter]); + + if (!$ctime) { + $ctime = "0"; + } + if (!$ctime2) { + $ctime2 = "2400"; + } + + if ($ctime < $ctime2) { + if (!($time2 >= $ctime && $time2 <= $ctime2)) { + print "Timeframe rejected 1\n" if ($debug & 64); + next; + } + } + else { + if (!(($time2 >= $ctime && $time2 <= "2400") || ($time2 >= "0" && $time2 <= $ctime2))) { + print "Timeframe rejected 2\n" if ($debug & 64); + next; } } + } + + print "Before Weekday Match\n" if ($debug & 64); + if ($$rContext{weekday}[$counter]) { + print "In Weekday Match \"$$rContext{weekday}\"\n" if ($debug & 64); + my ($wday); + $wday = getWDay($time); + $$rContext{weekday}[$counter] =~ /(.)(.)(.)(.)(.)(.)(.)/; + if ($$wday eq "-") { + print "Weekday rejected\n" if ($debug & 64); + next; + } + } + + print "Before Minlength Match\n" if ($debug & 64); + if ($$rContext{minlength}[$counter]) { + print "In Minlength Match \"$$rContext{minlength}[$counter]\"\n" if ($debug & 64); + if ($Program{$title}{$channel}{$time}{duration} < $$rContext{minlength}[$counter]) { + print "Minlength rejected\n" if ($debug & 64); + next; + } + } - foreach my $retval (@retval) - { - $retval =~ s/\x0d//g; + print "Before Maxlength Match\n" if ($debug & 64); + if ($$rContext{maxlength}[$counter]) { + print "In Maxlength Match \"$$rContext{maxlength}[$counter]\"\n" if ($debug & 64); + if ($Program{$title}{$channel}{$time}{duration} > $$rContext{maxlength}[$counter]) { + print "Maxlength rejected\n" if ($debug & 64); + next; } - return (@retval); + } + + # All test passed. Accept this timer + print "All Tests passed entry accepted/blacklisted\n" if ($debug & 64); + return ($counter); + } + # Foreach ran out without a hit + return "Nothing"; +} + +# Open the connection to VDR +sub initsocket { + my ($Dest, $Port) = split (/\:/,$Dest[$currentVDR - 1],2); + my $iaddr = inet_aton($Dest); + my $paddr = sockaddr_in($Port, $iaddr); + my $Timeout = 10; # max. seconds to wait for response + + $SIG{ALRM} = sub { die("Timeout while connecting to VDR"); }; + alarm($Timeout); + + socket(SOCKET, PF_INET, SOCK_STREAM, getprotobyname('tcp')); + connect(SOCKET, $paddr) or die ("Can't connect to VDR\n"); + select(SOCKET); $| = 1; + select(STDOUT); + + while (<SOCKET>) { + last if substr($_, 3, 1) ne "-"; } + alarm(0); +} + +# Send a command to VDR and read back the result +sub GetSend { + my ($command, @retval); + + while ($command = shift) { + print SOCKET "$command\r\n"; + while (<SOCKET>) { + s/\x0d//g; + (@retval) = (@retval, $_); + last if substr($_, 3, 1) ne "-"; + } + } + return (@retval); +} # Close the socket to VDR -sub closesocket - { - print SOCKET "Quit\r\n"; - close(SOCKET); - } +sub closesocket { + print SOCKET "Quit\r\n"; + close(SOCKET); +} # Fetch the timers-List from VDR via SVDR and process it. -sub fetchVDRTimers - { - my (@timers, $timer, $position, $active, $channel, $day, $start, $end, $prio, $ttl, $title, $subtitle, $minute, $duration); - my ($utime, $utime2); - - # First fetch the timers-list from VDR - @timers = GetSend ("lstt"); - - foreach $timer (@timers) - { -# $timer =~ s/\x0d//g; - chomp $timer; - # a Valid Timer-line beginns with "250" - if ($timer =~ s/250-|250\s//) - { - # Extract the Position in front of the line - ($position, $timer) = split (/\s/,$timer,2); - -# print "Position: \"$position\" Timer: \"$timer\"\n"; - # Split the : seperated values - ($active, $channel, $day, $start, $end, $prio, $ttl, $title, $subtitle) = split (/\:/,$timer,9); - - my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); - - # If the string is exactly 7 char wide, then its a "repeating"-timer - if ($active >= 1) - { - if ($day =~ /(.)(.)(.)(.)(.)(.)(.)/) - { - my (@days); - @days = ($1, $2, $3, $4, $5, $6, $7); - ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); - - $start =~ /(\d\d)(\d\d)/; - $hour = $1; - $minute = $2; - $utime = timelocal 0, $minute, $hour, $mday, $mon, $year; - $end =~ /(\d\d)(\d\d)/; - $hour = $1; - $minute = $2; - $utime2 = timelocal 0, $minute, $hour, $mday, $mon, $year; - if ($end < $start) - { - $utime2 += 24*60*60; - } - $duration = $utime2 - $utime; - - # "Normalize" the timestamp to monday - $utime = $utime - ($wday * 24 * 60 *60); - - foreach my $num (0 .. $#days) - { - if ($days[$num] ne "-") - { - my $utime3; - # Todays before today will be shifted in the next week - if (($num + 1) < $wday) - { - $utime3 = $utime + (($num + 7 + 1) * 24 * 60 * 60); - } - else - { - $utime3 = $utime + (($num + 1) * 24 * 60 * 60); - } - &addtimer ($title,$title,$subtitle,$channels[$channel],$utime3,$duration,$prio,"R$position",0,0); - } - } - } - - # When the Day-Value is between 1 and 31, then its a "One time" Timer - elsif (($day >= 1) && ($day <= 31)) - { - if ($active == "2") - { - $position += 1000000; - } - # When the Day is before the Current-Day, then the Timer is for the next month - if ($day < $mday) - { - $mon++; - if ($mon == 12) - { - $mon = 0; - $year ++; - } - } - $start =~ /(\d\d)(\d\d)/; - $hour = $1; - $minute = $2; - $utime = timelocal 0, $minute, $hour, $day, $mon, $year; - $end =~ /(\d\d)(\d\d)/; - $hour = $1; - $minute = $2; - $utime2 = timelocal 0, $minute, $hour, $day, $mon, $year; - if ($end < $start) - { - $utime2 += 24*60*60; - } - $duration = $utime2 - $utime; - - &addtimer ($title,$title,$subtitle,$channels[$channel],$utime,$duration,$prio,$position,0,0); - } +sub fetchVDRTimers { + my (@timers, $timer, $position, $active, $channel, $day, $start, $end, $prio, $lifetime, $title, $subtitle, $minute, $duration); + my ($utime, $utime2); + + # First fetch the timers-list from VDR + @timers = GetSend ("lstt"); + + foreach $timer (@timers) { + chomp $timer; + # a Valid Timer-line beginns with "250" + if ($timer =~ s/250-|250\s//) { + # Extract the Position in front of the line + ($position, $timer) = split (/\s/,$timer,2); + +# print "Position: \"$position\" Timer: \"$timer\"\n"; + # Split the : seperated values + ($active, $channel, $day, $start, $end, $prio, $lifetime, $title, $subtitle) = split (/\:/,$timer,9); + + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); + + # If the string is exactly 7 char wide, then its a "repeating"-timer + if ($active >= 1) { + if ($day =~ /(.)(.)(.)(.)(.)(.)(.)/) { + my (@days); + @days = ($1, $2, $3, $4, $5, $6, $7); + ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); + + $start =~ /(\d\d)(\d\d)/; + $hour = $1; + $minute = $2; + $utime = timelocal 0, $minute, $hour, $mday, $mon, $year; + $end =~ /(\d\d)(\d\d)/; + $hour = $1; + $minute = $2; + $utime2 = timelocal 0, $minute, $hour, $mday, $mon, $year; + if ($end < $start) { + $utime2 += 24*60*60; + } + $duration = $utime2 - $utime; + + # "Normalize" the timestamp to monday + $utime = $utime - ($wday * 24 * 60 *60); + + foreach my $num (0 .. $#days) { + if ($days[$num] ne "-") { + my $utime3; + # Days before today will be shifted in the next week + if (($num + 1) < $wday) { + $utime3 = $utime + (($num + 7 + 1) * 24 * 60 * 60); } + else { + $utime3 = $utime + (($num + 1) * 24 * 60 * 60); + } + &addtimer ($title,$title,$subtitle,"",$channels[$channel],$utime3,$duration,$prio,$lifetime,"R$position",0,0); + } + } + } + + # When the Day-Value is between 1 and 31, then its a "One time" Timer + elsif (($day >= 1) && ($day <= 31)) { + if ($active == "2") { + $position += 1000000; + } + # When the Day is before the Current-Day, then the Timer is for the next month + if ($day < $mday) { + $mon++; + if ($mon == 12) { + $mon = 0; + $year ++; + } } + $start =~ /(\d\d)(\d\d)/; + $hour = $1; + $minute = $2; + $utime = timelocal 0, $minute, $hour, $day, $mon, $year; + $end =~ /(\d\d)(\d\d)/; + $hour = $1; + $minute = $2; + $utime2 = timelocal 0, $minute, $hour, $day, $mon, $year; + if ($end < $start) { + $utime2 += 24*60*60; + } + $duration = $utime2 - $utime; + + &addtimer ($title,$title,$subtitle,"",$channels[$channel],$utime,$duration,$prio,$lifetime,$position,0,0); + } } + } } +} # Parse file "epg.data" -sub initepgdata - { - open (FI,"epg.data") or sub_die ("Can't open file \"epg.data\"\n"); - - while (<FI>) - { - # Begin Channel - if (/^C\s(\d+)\s+(.+)/) - { - $channel = $2; - while (<FI>) - { - # End Channel - if (/^c$/) - { - last; - } - # Begin Timer - elsif (/^E\s(\d+)\s+(\d+)\s+(\d+)$/) - { - # Undef this Variables because it is possibel that not every timer uses this values - undef $duration; - undef $subtitle; - undef $description; - - $time=$2; - $duration=$3; - } - # Title - elsif (/^T\s(.*)/) - { - $title = $1; - } - # Subtitle - elsif (/^S\s(.*)/) - { - $subtitle=$1; - } - # Description - elsif (/^D\s(.*)/) - { - $description=$1; - } - # End Timer - elsif (/^e$/) - { - # Only accept timers that are in the future - if ($time < time) - { - next; - } - - # Work around the diffrent Bugs in the data - &correct_epg_data(); - - # Check if the title is in the DEEP-Blacklist - if ($title =~ /$title_deepblack/i) - { - next; - } - - # Check if the Title & Subtitle is in the Done-List - if ($title =~ /$title_done/) - { - if ($subtitle) - { - if ($subtitle =~ /$subtitle_done/) - { - next; - } - } - } - - $Program{$title}{$channel}{$time}{duration}=$duration; - if ($subtitle) - { - $Program{$title}{$channel}{$time}{subtitle}=$subtitle; - } - if ($description) - { - $Program{$title}{$channel}{$time}{description}=$description; - } - } - } +sub initepgdata { + open (FI,"epg.data") or die ("Can't open file \"epg.data\"\n"); + + while (<FI>) { + # Begin Channel + if (/^C\s(\d+)\s+(.+)/) { + $channel=$2; + while (<FI>) { + # End Channel + if (/^c$/) { + last; + } + # Begin Timer + elsif (/^E\s(\d+)\s+(\d+)\s+(\d+)$/) { + # Undef this Variables because it is possibel that not every timer uses this values + undef $duration; + undef $subtitle; + undef $description; + undef $category; + + $time=$2; + $duration=$3; + } + # Title + elsif (/^T\s(.*)/) { + $title=$1; + } + # Subtitle + elsif (/^S\s(.*)/) { + $subtitle=$1; } + # Description + elsif (/^D\s(.*)/) { + $description=$1; + } + elsif (/^K\s(.*)/) { + $category=$1; + } + # End Timer + elsif (/^e$/) { + # Only accept timers that are in the future + if ($time < time) { + next; + } + # Only accept timers that are at least 2 Seconds long + if ($duration <= 1) { + next; + } + + # Work around the different Bugs in the data + &correct_epg_data(); + + # Check if the Title & Subtitle is in the Done-List (Only if Subtitle exists) + if ($subtitle && $title =~ /$title_done/ && $subtitle =~ /$subtitle_done/) { + next; + } + + $Program{$title}{$channel}{$time}{duration}=$duration; + if ($subtitle) { + $Program{$title}{$channel}{$time}{subtitle}=$subtitle; + } + if ($description) { + $Program{$title}{$channel}{$time}{description}=$description; + } + if ($category) { + $Program{$title}{$channel}{$time}{category}=$category; + } + # Check if the title is in the DEEP-Blacklist + if (&testtimer("deepblack", $title, $channel, $time) ne "Nothing") { + print "Deepblack: \"$title\"" if ($debug & 64); + print " $subtitle" if ($debug & 64 && $subtitle); + print "\n" if ($debug & 64); + &delprogram ($title, $channel, $time); + } + } + } } - close (FI); - } + } + close (FI); +} # What is a Movie (When correctly stored into Subtitle) -sub initmovie - { - my (@list,$list); - open (FI,"$ENV{HOME}/.master-timer/subtitle-movie") or return; - @list = <FI>; - close(FI); - - foreach $list (@list) - { - chomp $list; - } - $subtitle_movie = join ('|',@list); +sub initmovie { + my (@list,$list); + open (FI,"${configdir}/subtitle-movie") or return; + @list = <FI>; + close(FI); + + foreach $list (@list) { + chomp $list; } + $subtitle_movie = join ('|',@list); +} -# What should be blacklistet -sub initblacklist - { - my (@list,$list); - if (open (FI,"$ENV{HOME}/.master-timer/deepblack")) - { - @list = <FI>; - close(FI); - - foreach $list (@list) - { - chomp $list; - } - $title_deepblack = join ('|',@list); - } - else - { - $title_deepblack = "^\$"; +# What is already recorded/Should not be recorded +sub initdone { + my (@list,$list, %title_done, %subtitle_done, $title_temp, $subtitle_temp); + open (FI,"${configdir}/done") or return; + @list = <FI>; + close (FI); + + foreach $list (@list) { + chomp $list; + ($title_temp,$subtitle_temp) = split (/\|/,$list); + if ($title_temp) { + $title_done{"^\Q$title_temp\E\$"} = 1; + } + if ($subtitle_temp) { + $subtitle_done{"^\Q$subtitle_temp\E\$"} = 1; + } + } + $title_done = join ('|',sort keys %title_done); + $subtitle_done = join ('|',sort keys %subtitle_done); +} + +sub processdone { + # Now delete Timers in VDR that are already in the done-List + my ($list, @list, $position, $timer, $active, $g, $title, $subtitle, $counter, @todel); + $counter = 0; + @list = GetSend ("LSTT"); + + foreach $timer (@list) { + chomp $timer; + if ($timer =~ s/250-|250\s//) { + ($position, $timer) = split (/\s/,$timer,2); + # Split the : seperated values + ($active, $g, $g, $g, $g, $g, $g, $title, $subtitle) = split (/\:/,$timer,9); + if ($active == 2) { + # Title: "Shakespeare in Love"||Subtitle: "Romanze" + my ($ctitle, $csubtitle); + if ($subtitle && $subtitle =~ /^Title\:\s\"(.*)\"\|\|Subtitle\:\s\"(.*)\"/) { + $title = $1; + $subtitle = $2; + if ($subtitle) { + my (@titles, @subtitles, $num, $hit); + undef $hit; + @titles = split (/\~/,$title); + @subtitles = split (/\~/,$subtitle); + foreach $num (0 .. $#titles) { + if ($titles[$num] =~ /$title_done/ && $subtitles[$num] =~ /$subtitle_done/) { + $hit = 1; + } + else { + undef $hit; + last; + } + } + + if ($hit) { + my ($result); + print "Delete Timer: $title $subtitle\n" if ($debug & 4); + $position -= $counter; + ($result) = GetSend ("DELT $position"); + print "Result: $result" if ($debug & 4); + if ($result =~ /^250/) { + $counter++; + } + } + } + } } + } } +} -# What is already recorded/Should not be recorded -sub initdone - { - my (@list,$list, %title_done, %subtitle_done, $title_temp, $subtitle_temp); - if (open (FI,"$ENV{HOME}/.master-timer/done")) - { - @list = <FI>; - close (FI); - - foreach $list (@list) - { - chomp $list; - ($title_temp,$subtitle_temp) = split (/\|/,$list); - if ($title_temp) - { - $title_done{"^$title_temp\$"} = 1; - } - if ($subtitle_temp) - { - $subtitle_done{"^$subtitle_temp\$"} = 1; - } +# What should be recorded +sub inittorecord { + my ($context) = shift; + my ($rContext); + my (@title_list, @subtitle_list, @description_list, $line); + my (%Input); + my $counter = 0; + + if ($context eq "torecord") { + $rContext = \%torecord; + open (FI,"${configdir}/${context}") or die ("Can't open file \"$context\"\n"); + } elsif ($context eq "deepblack") { + $rContext = \%deepblack; + open (FI,"${configdir}/${context}") or return; + } else { + die ("Illegal Context"); + } + + + outer: while (<FI>) { + chomp if ($_); + if ($_ && !(/^\#/) && /^\[.*\]$/) { + $line = $.; + undef %Input; + while (<FI>) { + chomp; + if ($_ && !(/^\#/)) { + if (/^\[.*?\]$/) { + last; } - $title_done = join ('|',sort keys %title_done); - $subtitle_done = join ('|',sort keys %subtitle_done); - - # Ein paar Zeichen Escapen - $title_done =~ s/\?/\\\?/g; - $title_done =~ s/\+/\\\+/g; - $subtitle_done =~ s/\?/\\\?/g; - $subtitle_done =~ s/\+/\\\+/g; - - # Now delete Timers in VDR that are already in the done-List - my ($position, $timer, $active, $g, $title, $subtitle, $counter, @todel); - $counter = 0; - @list = GetSend ("LSTT"); - - foreach $timer (@list) - { -# $timer =~ s/0x0d//g; - chomp $timer; - if ($timer =~ s/250-|250\s//) - { - ($position, $timer) = split (/\s/,$timer,2); - # Split the : seperated values - ($active, $g, $g, $g, $g, $g, $g, $title, $subtitle) = split (/\:/,$timer,9); - if ($active == 2) - { - # Title: "Shakespeare in Love"||Subtitle: "Romanze" - my ($ctitle, $csubtitle); - if ($subtitle && $subtitle =~ /^Title\:\s\"(.*)\"\|\|Subtitle\:\s\"(.*)\"/) - { - $title = $1; - $subtitle = $2; - if ($subtitle) - { - my (@titles, @subtitles, $num, $hit); - undef $hit; - @titles = split (/\~/,$title); - @subtitles = split (/\~/,$subtitle); - foreach $num (0 .. $#titles) - { - if ($titles[$num] =~ /$title_done/ && $subtitles[$num] =~ /$subtitle_done/) - { - $hit = 1; - } - else - { - undef $hit; - last; - } - } - - if ($hit) - { - my ($result); - print "Delete Timer: $title $subtitle\n" if ($debug & 4); - $position -= $counter; - ($result) = GetSend ("DELT $position"); - print "Result: $result" if ($debug & 4); - if ($result =~ /^250/) - { - $counter++; - } - } - } - } - } - } + + my ($key, $value); + ($key, $value) = split (/\s+=\s+/); + + if ($key =~ /^title$/i) { + if ($Input{title}) { + $Input{title} .= "|$value"; + } else { + $Input{title} = $value; + } + print "Titel = $value\n" if ($debug & 16); + } + elsif ($key =~ /^subtitle$/i) { + if ($Input{subtitle}) { + $Input{subtitle} .= "|$value"; + } else { + $Input{subtitle} = $value; + } + print "Subtitel = $value\n" if ($debug & 16); + } + elsif ($key =~ /^description$/i) { + if ($Input{description}) { + $Input{description} .= "|$value"; + } else { + $Input{description} = $value; + } + print "Description = $value\n" if ($debug & 16); + } + elsif ($key =~ /^category$/i) { + $Input{category} = $value; + print "Category = $value\n" if ($debug & 16); + } + elsif ($key =~ /^channel$/i) { + if ($Input{channel}) { + $Input{channel} .= "|^$value\$"; + } else { + $Input{channel} = $value; + } + print "Channel = $value\n" if ($debug & 16); + } + elsif ($key =~ /^timeframe$/i) { + $Input{timeframe} = $value; + print "Timeframe = $value\n" if ($debug & 16); } + elsif ($key =~ /^weekday$/i) { + $Input{weekday} = $value; + print "Weekday = $value\n" if ($debug & 16); + } + elsif ($key =~ /^minlength$/i) { + $Input{minlength} = $value; + print "Minlength = $value\n" if ($debug & 16); + } + elsif ($key =~ /^maxlength$/i) { + $Input{maxlength} = $value; + print "Maxlength = $value\n" if ($debug & 16); + } + elsif ($key =~ /^prio$/i) { + $Input{prio} = $value; + print "Prio = $value\n" if ($debug & 16); + } + elsif ($key =~ /^lifetime$/i) { + $Input{lifetime} = $value; + print "Lifetime = $value\n" if ($debug & 16); + } + elsif ($key =~ /^timertitle$/i) { + $Input{timertitle} = $value; + print "Timertitel = $value\n" if ($debug & 16); + } + elsif ($key =~ /^margin$/i) { + $Input{margin} = $value; + print "Margin = $value\n" if ($debug & 16); + } + elsif ($key =~ /^instance$/i) { + $Input{instance} = $value; + print "Instance = $value\n" if ($debug & 16); + } else { + print "Unkown Key: \"$key\" with Value: \"$value\"\n"; + } + } } - } -# What should be recorded -sub inittorecord - { - my (@list, $list, $title, $subtitle, $description, $channel, $timeframe, $prio, $timer_title, $margin, $machine, @title_list, @subtitle_list, @description_list); - my $counter = 0; - open (FI,"$ENV{HOME}/.master-timer/torecord") or sub_die ("Can't open file \"torecord\"\n"); - @list = <FI>; - close(FI); - - foreach $list (0 .. $#list) - { - chomp $list[$list]; - if ($list[$list] && !($list[$list] =~ /^\#/)) - { - ($title, $subtitle, $description, $channel, $timeframe, $prio, $timer_title, $margin, $machine) = split (/\|/,$list[$list]); - - # Accept torecord only if it is for the current machine - if ((!$machine && $currentVDR == 1) || $machine == $currentVDR) - { - if ($title) - { - $title_torecord[$counter] = $title; - $title_list[$#title_list + 1] = $title; - } - if ($subtitle) - { - $subtitle_torecord[$counter] = $subtitle; - $subtitle_list[$#subtitle_list + 1] = $subtitle; - } - if ($description) - { - $description_torecord[$counter] = $description; - $description_list[$#description_list + 1] = $description; - } - if ($channel) - { - my (@temp); - @temp = split (/\;/,$channel); - foreach (0 .. $#temp) - { - $channel_torecord[$counter][$_] = $temp[$_]; - } - } - if ($timeframe) - { - $timeframe_torecord[$counter] = $timeframe; - } - if ($prio) - { - $prio_torecord[$counter] = $prio; - } - else - { - $prio_torecord[$counter] = $default_prio; - } - if ($timer_title) - { - $timer_title_torecord[$counter] = $timer_title; - } - if ($margin) - { - my ($start, $stop); - ($start, $stop) = split (/;/,$margin, 2); - $marginstart_torecord[$counter] = $start if ($start); - $marginstop_torecord[$counter] = $stop if ($stop); - } - # Set Default-Margins if not margins defined - $marginstart_torecord[$counter] = $marginstart if (!$marginstart_torecord[$counter]); - $marginstop_torecord[$counter] = $marginstop if (!$marginstop_torecord[$counter]); - $counter++; - } + # Accept entry only if it is for the current instance or for "no" instance + if (($Opts{s} && $Input{instance} && $Input{instance} eq "s") || !$Input{instance} || ($Input{instance} ne "s" && $Input{instance} == $currentVDR)) { + # Accept entry only if at least a Title/Subtitle/Description is provied + if (!$Input{title} && !$Input{subtitle} && !$Input{description}) { + print "No Title/Subtitle/Description Field. $context entry ignored. Block beginning at Line $line\n"; + redo outer; + } + + if ($Input{title}) { + $$rContext{title}[$counter] = $Input{title}; + $title_list[$#title_list + 1] = $Input{title}; + } + if ($Input{subtitle}) { + if ($Input{subtitle} =~ /^movie$/i || $Input{subtitle} =~ /^\!movie$/i) { + $test_subtitle_movie = 1; + } + $$rContext{subtitle}[$counter] = $Input{subtitle}; + $subtitle_list[$#subtitle_list + 1] = $Input{subtitle}; + } + if ($Input{description}) { + $$rContext{description}[$counter] = $Input{description}; + $description_list[$#description_list + 1] = $Input{description}; + } + if ($Input{category}) { + $$rContext{category}[$counter] = $Input{category}; + } + if ($Input{channel}) { + if ($Input{channel} =~ /\!/) { + $Input{channel} =~ s/\!//g; + $$rContext{blackchannel}[$counter] = $Input{channel}; + } else { + $$rContext{channel}[$counter] = $Input{channel}; } + } + if ($Input{timeframe}) { + $$rContext{timeframe}[$counter] = $Input{timeframe}; + } + if ($Input{weekday}) { + $$rContext{weekday}[$counter] = $Input{weekday}; + } + if ($Input{minlength}) { + if ($Input{minlength} =~ /^(\d+)m$/) { + $Input{minlength} = $1 * 60 + } elsif ($Input{minlength} =~ /^(\d+)h$/) { + $Input{minlength} = $1 * 60 * 60 + } + $$rContext{minlength}[$counter] = $Input{minlength}; + } + if ($Input{maxlength}) { + if ($Input{maxlength} =~ /^(\d+)m$/) { + $Input{maxlength} = $1 * 60 + } elsif ($Input{maxlength} =~ /^(\d+)h$/) { + $Input{maxlength} = $1 * 60 * 60 + } + $$rContext{maxlength}[$counter] = $Input{maxlength}; + } + if ($Input{prio}) { + $$rContext{prio}[$counter] = $Input{prio}; + } + if ($Input{lifetime}) { + $$rContext{lifetime}[$counter] = $Input{lifetime}; + } + else { + $$rContext{prio}[$counter] = $default_prio; + } + if ($Input{timertitle}) { + $$rContext{timertitle}[$counter] = $Input{timertitle}; + } + if ($Input{margin}) { + my ($start, $stop); + ($start, $stop) = split (/;/,$Input{margin}, 2); + $$rContext{marginstart}[$counter] = $start if ($start); + $$rContext{marginstop}[$counter] = $stop if ($stop); + } + # Set Default-Margins if no margins defined + $$rContext{marginstart}[$counter] = $marginstart if (!$$rContext{marginstart}[$counter]); + $$rContext{marginstop}[$counter] = $marginstop if (!$$rContext{marginstop}[$counter]); + $counter++; + if ($Input{instance}) { + $$rContext{instance}[$counter] = $Input{instance}; + } } + redo outer; + } + } + + $$rContext{timercount} = $counter - 1; + + $$rContext{titleRE} = join ('|',@title_list); + if ($$rContext{titleRE} && $$rContext{titleRE} =~ /\|.\|/) { + $$rContext{titleRE} = "."; + } + $$rContext{subtitleRE} = join ('|',@subtitle_list); + if ($$rContext{subtitleRE} && $$rContext{subtitleRE} =~ /\|.\|/) { + $$rContext{subtitleRE} = "."; + } + $$rContext{descriptionRE} = join ('|',@description_list); + if ($$rContext{descriptionRE} && $$rContext{descriptionRE} =~ /\|.\|/) { + $$rContext{descriptionRE} = "."; + } + + if (!$$rContext{titleRE}) { + $$rContext{titleRE} = "^Dieseshierwirdgarantiertnieundnimmeraufirgendetwassinnvollesmatchen\$"; + } + if (!$$rContext{subtitleRE}) { + $$rContext{subtitleRE} = "^Dieseshierwirdgarantiertnieundnimmeraufirgendetwassinnvollesmatchen\$"; + } + if (!$$rContext{descriptionRE}) { + $$rContext{descriptionRE} = "^Dieseshierwirdgarantiertnieundnimmeraufirgendetwassinnvollesmatchen\$"; + } +} + +# Parse "LSTC"-Command of VDR +sub initchannellist { + my ($counter, $chan, $garbage, $card, @temp_channels, $temp, $i); - $num_torecord = $counter - 1; + @temp_channels = GetSend ("LSTC"); - $title_torecord = join ('|',@title_list); - $subtitle_torecord = join ('|',@subtitle_list); - $description_torecord = join ('|',@description_list); + foreach $i (0 .. $#temp_channels) { + $temp = $temp_channels[$i]; + chomp $temp; - if (!$title_torecord) - { - $title_torecord = "^Dieseshierwirdgarantiertnieundnimmeraufirgendetwassinnvollesmatchen\$"; + if ($temp =~ s/250-|250\s//) { + ($counter, $temp) = split (/\s/,$temp,2); + ($chan, $garbage,$garbage, $garbage, $garbage, $garbage, $garbage, $card, $garbage) = split (/\:/,$temp); + $channels[$counter] = $chan; + $channels{$chan}{number} = $counter; + $channels{$chan}{card} = $card; + $counter++; + } + } +} + +sub initconfigfile { + open (FI,"${configdir}/config") or return; + while (<FI>) { + s/\#.*//; + chomp; + if ($_) { + my ($key, $value); + ($key, $value) = split (/\s+=\s+/); + if ($key =~ /^debug$/i) { + $debug = $value; + print "Debug-Level = $value\n" if ($debug & 16); } - if (!$subtitle_torecord) - { - $subtitle_torecord = "^Dieseshierwirdgarantiertnieundnimmeraufirgendetwassinnvollesmatchen\$"; + elsif ($key =~ /^marginstart$/i) { + print "Marginstart = $value\n" if ($debug & 16); + $marginstart = $value; } - if (!$description_torecord) - { - $description_torecord = "^Dieseshierwirdgarantiertnieundnimmeraufirgendetwassinnvollesmatchen\$"; + elsif ($key =~ /^marginstop$/i) { + print "Marginstop = $value\n" if ($debug & 16); + $marginstop = $value; } - } - -# Parse the "channels.conf" of VDR -sub initchannellist - { - my ($counter, $chan, $garbage, $card, @temp_channels, $temp, $i); - - @temp_channels = GetSend ("LSTC"); - - foreach $i (0 .. $#temp_channels) - { - $temp = $temp_channels[$i]; -# $temp =~ s/\x0d//g; - chomp $temp; - - if ($temp =~ s/250-|250\s//) - { - ($counter, $temp) = split (/\s/,$temp,2); - ($chan, $garbage,$garbage, $garbage, $garbage, $garbage, $garbage, $card, $garbage) = split (/\:/,$temp); - $channels[$counter] = $chan; - $channels{$chan}{number} = $counter; - $channels{$chan}{card} = $card; - $counter++; - } + elsif ($key =~ /^DVBCards$/i) { + print "DVB_Cards = $value\n" if ($debug & 16); + $DVB_cards = $value; + } + elsif ($key =~ /^defaultprio$/i) { + print "Default Priority = $value\n" if ($debug & 16); + $default_prio = $value; + } + elsif ($key =~ /^Dest$/i) { + print "Destination Host/IP:Port = $value\n" if ($debug & 16); + @Dest = split (/\s+/,$value); + } + elsif ($key =~ /^jointimers$/i) { + print "Join Timers = $value\n" if ($debug & 16); + $jointimers = $value; + } + elsif ($key =~ /^description$/i) { + print "Description = $value\n" if ($debug & 16); + $Description = $value; + } + else { + print "Unkown Key: \"$key\" with Value: \"$value\"\n"; } + } } + print "End Config\n" if ($debug & 16); +} -sub initconfigfile - { - open (FI,"$ENV{HOME}/.master-timer/config") or return; - while (<FI>) - { - s/\#.*//; - chomp; - if ($_) - { - my ($key, $value); - ($key, $value) = split (/\s+=\s+/); - if ($key =~ /^debug$/i) - { - $debug = $value; - print "Debug-Level = $value\n" if ($debug & 16); - } - elsif ($key =~ /^marginstart$/i) - { - print "Marginstart = $value\n" if ($debug & 16); - $marginstart = $value; - } - elsif ($key =~ /^marginstop$/i) - { - print "Marginstop = $value\n" if ($debug & 16); - $marginstop = $value; - } - elsif ($key =~ /^DVBCards$/i) - { - print "DVB_Cards = $value\n" if ($debug & 16); - $DVB_cards = $value; - } - elsif ($key =~ /^defaultprio$/i) - { - print "Default Priority = $value\n" if ($debug & 16); - $default_prio = $value; - } - elsif ($key =~ /^Dest$/i) - { - print "Destination Host/IP:Port = $value\n" if ($debug & 16); - @Dest = split (/\s+/,$value); - } - elsif ($key =~ /^jointimers$/i) - { - print "Join Timers = $value\n" if ($debug & 16); - $jointimers = $value; - } - else - { - print "Unkown Key: \"$key\" with Value: \"$value\"\n"; - } - } - } - print "End Config\n" if ($debug & 16); +sub initcommandline() { + my $Usage = qq{ +Usage: $0 [options] [Instance]... + +Options: -d hostname:Port hostname/ip:Port (localhost:2001) + -c configdir Directory where all config files are located + (~/.master-timer) + -i instance Which VDR-Instance, from the config-file, should be + used + -s Print all series from epg.data and exit + -v debuglevel Level of debug-messages to print + -h This Help-Page +}; + + # Only process commandline if not already processed + if (!$Opts{done}) { + die $Usage if (!getopts("d:p:c:i:sv:h",\%Opts)); } + die $Usage if ($Opts{h}); + # Mark the options as already processed + $Opts{done} = 1; -sub init - { - &initconfigfile(); - &initsocket(); - &initmovie(); - &initblacklist(); - &initdone(); - &initchannellist(); - &initepgdata(); - &inittorecord(); + if ($Opts{v}) { + $debug = $Opts{v}; + } + if ($Opts{i}) { + $currentVDR = $Opts{i}; + } + if ($Opts{d}) { + @Dest = ($Opts{d}); } + if ($Opts{c}) { + $configdir = $Opts{c}; + } +} + +sub init { + &initcommandline(); + &initconfigfile(); + # Process commandline a second time, so that configs from the config-file are overwritten + &initcommandline(); + &initsocket(); + &initmovie(); + &initdone(); + &initchannellist(); + &inittorecord("deepblack"); + &initepgdata(); + &inittorecord("torecord"); +} diff --git a/Tools/master-timer/sample/channels-to-scan b/Tools/master-timer/sample/channels-to-scan index 6acf157..22f473d 100644 --- a/Tools/master-timer/sample/channels-to-scan +++ b/Tools/master-timer/sample/channels-to-scan @@ -3,6 +3,4 @@ 3 4 5 -13 -18 -21 +49 diff --git a/Tools/master-timer/sample/config b/Tools/master-timer/sample/config index d01c8a8..3180943 100644 --- a/Tools/master-timer/sample/config +++ b/Tools/master-timer/sample/config @@ -1,14 +1,32 @@ -# How Many Seconds "too early" should the timer begin +# Master-Timer config file. Values shown here are defaults. + +# How many seconds "too early" should the timer begin marginstart = 600 -# How Many Seocnds "too long" should the timer end + +# How many seconds "too long" should the timer end marginstop = 600 -# When the Prio isn't provied in the config-File use this value + +# When the Prio isn't provided in the config file use this value defaultprio = 50 -# How many DVB-Cards are installed in the Computer (Not used yet) -DVBCards = 3 -# IP/Hostname:Port of the Destinations (Space is used for delimiter) -Dest-Host = localhost:2001 -# Should Timers on the same channels be joined when they overlapp (0 = off) -jointimers = 1 -# Debug-Level + +# How many DVB cards are installed in the computer (not used yet) +DVBCards = 1 + +# IP/Hostname:Port of the destination (space is used for delimiter) +Dest = localhost:2001 + +# Should timers on the same channels be joined when they overlap (0 = off) +jointimers = 0 + +# Should the description be transfered to VDR? +description = 0 + +# Debug level +# 1 : Dump "torecord" +# 2 : Dump all timers +# 4 : Show when a timer will be deleted +# 8 : Dump the "Done" REs +# 16 : Verbose config reading +# 32 : Dump program variables +# 64 : Excessive deepblack/torecord debuging debug = 0 diff --git a/Tools/master-timer/sample/convert-channel-list b/Tools/master-timer/sample/convert-channel-list new file mode 100644 index 0000000..a97f3c5 --- /dev/null +++ b/Tools/master-timer/sample/convert-channel-list @@ -0,0 +1,26 @@ +Kabel 1|Kabel 1 +MTV|MTV Central +PRW 13TH Street|13th Street +PRW Discovery Channel|Discovery Channel +PRW Disney Channel|Disney Channel +PRW FOX KIDS|Fox Kids +PRW Junior|Junior +PRW K-Toon|K-Toon +PRW Krimi & Co|Krimi &Co +PRW Planet|Planet +PRW Sci-Fantasy|Premiere Sci-Fi +PRW Studio Universal|Studio Universal +PRW Sunset|Sunset +Premiere Action|Premiere Action +Premiere Comedy|Premiere Comedy +Premiere STAR|Premiere Star +Premiere World 1|Premiere 1 +Premiere World 2|Premiere 2 +Premiere World 3|premiere 3 +Pro Sieben|Pro-7 +RTL|RTL +RTL 2|RTL2 +Sat.1|Sat.1 +Super RTL|Super RTL +Viva|VIVA +Vox|VOX diff --git a/Tools/master-timer/sample/deepblack b/Tools/master-timer/sample/deepblack index 63b4f9e..12884fe 100644 --- a/Tools/master-timer/sample/deepblack +++ b/Tools/master-timer/sample/deepblack @@ -1,79 +1,172 @@ -Für alle Fälle Stefanie -'MAX' - Das ganze Leben! -10 vor 11 -17:30 live -18:30 -24 Stunden -Andreas Türck -Arabella -^BIZZ$ -Big Brother -Britt - Der Talk um Eins -Bärbel Schäfer -Call TV -Chicago Hope - Endstation Hoffnung -Chicago Hope -DIE REDAKTION -Dauerwerbesendungen -Die Harald Schmidt Show -Die Oliver Geissen Show -Die Quiz Show -Doppelter Einsatz -Dr. Stefan Frank - Der Arzt, dem die Frauen vertrauen -EXCLUSIV -EXTRA -Ehekriege -Ein Bayer auf Rügen -Emergency Room -Explosiv - Das Magazin -GIRLSCAMP -Glücksrad -Gute Zeiten, schlechte Zeiten -Hallo, Onkel Doc! -Hans Meiser -Hercules -Hinter Gittern - Der Frauenknast -Infomercials -Jeder gegen Jeden -K1 DIE REPORTAGE -K1 Das Magazin -K1 Nachrichten -Kickers -Kochduell -Nachrichten -Nicole - Entscheidung am Nachmittag -OP ruft Dr. Bruckner -PREMIERE WORLD - Das Programm -PROSIEBEN REPORTAGE -Peter Imhof -Programm ab -Programm von -Punkt 12 -Punkt 6 -Punkt 9 -RTL II News -RTL SHOP -RTL aktuell -RTL-Nachtjournal -SAT.1-FRÜHSTÜCKSFERNSEHEN -Spiegel TV-Reportage -UEFA Champions -fussball -fßball -Vera am Mittag -Wolffs Revier -Zapping -alphateam -peep! -s.a.m. -taff. -^blitz$ -SK Kölsch -^Becker$ -Kommissar Rex -Fit For Fun TV -Nur die Liebe zählt -Unsere kleine Farm -Die Waltons -^Die Zwei$ -^Sieben$ +# [<Anytext>] +# This marks the beginning of a deepblack-entry +# Title = <text> +# This matches a title +# Subtitle = <text> +# This matches a subtitle +# Description = <text> +# This matches a description +# Category = <left>/<right> +# This matches a DTV-Category +# Channel = <Channel> +# Restricts a deepblack-entry to a specific channel. +# A single "!" at start of channel list negates the selection. +# Timeframe = <begin>-<end> +# Restricts a deepblack-entry to a specific timeframe. +# No timers with start time in the timeframe will be programmed. +# minlength = <Number> +# Restricts a deepblack-entry to a specific minimum length +# (postfix "m" for minutes, "h" for hours.) +# maxlength = <Number> +# Restricts a deepblack-entry to a specific maximum length +# (postfix "m" for minutes, "h" for hours.) +# weekday = MTWTFSS +# Restricts a deepblack-entry to a specific weekday +# instance = <Number> +# Only apply this deepblack-entry for a specific Instance +# "s" is a special value used for "-s"-Mode +# +# The "Title", "Subtitle", "Description", "Channel"-Lines can be +# supplied any number of times for a specific entry +# +# To deepblack something at least one of the "Title", "Subtitle" or +# "Description" (If you don't have anything "better" use "Title = ." +# for this matches everything) fields has to be provided. +# These three fields are "include" and the rest are "exclude" fields. + +[Blacklist all Talkshows] +Title = . +Category = Talk + +[Blacklist all Lifestyles] +Title = . +Category = /Lifestyles + +[Blacklist Sport/Tennis] +Title = . +Category = Sport/Tennis + +[Record only ZDF and Pro7] +Title = . +Channel = !ZDF +Channel = ProSieben + +[Blacklist a timeframe] +Title = . +Timeframe = 1000-1400 + +[Blacklist everything with less than 5 minutes duration] +Title = . +maxlength = 5m + +[Sinnlose Serien] +Title = Für alle Fälle Stefanie +Title = Chicago Hope - Endstation Hoffnung +Title = Chicago Hope +Title = Doppelter Einsatz +Title = Dr. Stefan Frank - Der Arzt, dem die Frauen vertrauen +Title = Ehekriege +Title = Ein Bayer auf Rügen +Title = Emergency Room +Title = Gute Zeiten, schlechte Zeiten +Title = Hallo, Onkel Doc! +Title = Hercules +Title = Hinter Gittern - Der Frauenknast +Title = OP ruft Dr. Bruckner +Title = Wolffs Revier +Title = alphateam +Title = SK Kölsch +Title = ^Becker$ +Title = Kommissar Rex +Title = Nur die Liebe zählt +Title = Unsere kleine Farm +Title = Die Waltons +Title = ^Die Zwei$ + +[Glueckspiele] +Title = Die Quiz Show +Title = Glücksrad +Title = Jeder gegen Jeden +Title = Kochduell + +[Infotainment und Boulevardzeug] +Title = 'MAX' - Das ganze Leben! +Title = ^BIZZ$ +Title = Big Brother +Title = GIRLSCAMP +Title = Call TV +Title = DIE REDAKTION +Title = EXCLUSIV +Title = EXTRA +Title = Explosiv - Das Magazin +Title = K1 DIE REPORTAGE +Title = K1 Das Magazin +Title = PROSIEBEN REPORTAGE +Title = Fit For Fun TV +Title = peep! +Title = s.a.m. +Title = taff. +Title = ^blitz$ +Title = Die Harald Schmidt Show +Title = Spiegel TV-Reportage + +[Nachrichten] +Title = 10 vor 11 +Title = 17:30 live +Title = 18:30 +Title = 24 Stunden +Title = Punkt 12 +Title = Punkt 6 +Title = Punkt 9 +Title = RTL II News +Title = RTL aktuell +Title = RTL-Nachtjournal +Title = K1 Nachrichten +Title = Nachrichten + +[Talkshows] +Title = Andreas Türck +Title = Arabella +Title = Britt - Der Talk um Eins +Title = Bärbel Schäfer +Title = Die Oliver Geissen Show +Title = Peter Imhof +Title = Vera am Mittag +Title = Hans Meiser +Title = Nicole - Entscheidung am Nachmittag +Title = Franklin + +[So richtig Sinnloses] +Title = Dauerwerbesendungen +Title = Infomercials +Title = Kickers +Title = RTL SHOP +Title = SAT.1-FRÜHSTÜCKSFERNSEHEN +Title = Zapping + +[PREMIERE WORLD - Das Programm] +Title = PREMIERE WORLD - Das Programm +Title = Programm ab +Title = Programm von + +[Fussball] +Title = fussball +Title = fußball +Title = UEFA Champions + +#Sonstiges +[^Sieben$] +Title = ^Sieben$ + +[Starporträt Kevin Spacey] +Title = Starporträt Kevin Spacey + + +[All Movies for -s] +Subtitle = MOVIE +Instance = s + +[All >= 65m for -s] +Title = . +minlength = 65m +Instance = s diff --git a/Tools/master-timer/sample/subtitle-movie b/Tools/master-timer/sample/subtitle-movie index 3b5a0ab..9bd3579 100644 --- a/Tools/master-timer/sample/subtitle-movie +++ b/Tools/master-timer/sample/subtitle-movie @@ -3,6 +3,7 @@ ^Actionkomödie$ ^Actionthriller$ ^Agentenfilm$ +^Beziehungskomödie$ ^Biografie$ ^Biographie$ ^Computeranimation$ @@ -12,19 +13,24 @@ ^Familiendrama$ ^Fantasy$ ^Fantasykomödie$ +^Fantasy-Komödie$ ^Gangsterfilm$ ^Gerichtsfilm$ ^Gesellschaftsdrama$ +^Historiendrama$ ^Horrorfilm$ ^Horrorkomödie$ +^Jugenddrama$ ^Kinderfilm$ ^Komödie$ ^Kriegsfilm$ ^Krimikomödie$ ^Kriminalfilm$ ^Liebesfilm$ +^Liebeskomödie$ ^Melodram$ ^Melodrama$ +^Monumentalfilm$ ^Musical$ ^Politthriller$ ^Psychothriller$ @@ -32,10 +38,15 @@ ^Romanze$ ^Satire$ ^Science-Fiction$ +^Science-Fiction-Komödie$ ^Spielfilm$ ^TV Movie$ ^TV-Drama$ +^Teil .$ +^Teil 0.$ ^Thriller$ +^Tragikomödie$ ^Western$ +^Westernkomödie$ ^Zeichentrick$ ^Zeichentrickkomödie$ diff --git a/Tools/master-timer/sample/torecord b/Tools/master-timer/sample/torecord index 0306830..0c97b91 100644 --- a/Tools/master-timer/sample/torecord +++ b/Tools/master-timer/sample/torecord @@ -1,32 +1,90 @@ -# Format: (Every field is "optional". -# [Title RE|Subtitle RE|Description RE|Channel-Name|Timeframe|Prio|Timer-Title|Marginstart;Marginstop|VDR-Instance] +# [<Anytext>] +# This marks the beginning of a timer entry +# Title = <text> +# This matches a title +# Subtitle = <text> +# This matches a subtitle. +# You may use the magic "MOVIE" or "!MOVIE" which matches +# all entries from file "subtitle-movie". +# Description = <text> +# This matches a description +# Category = <left>/<right> +# This matches a DTV-Category +# Channel = <Channel> +# Restricts a time to a specific channel. +# A single "!" at start of channel list negates the selection. +# Timeframe = <begin>-<end> +# Restricts timer to a specific timeframe. +# Only timers with start time in the timeframe will be programmed. +# minlength = <Number> +# Restricts timer entry to a specific minimum length +# (postfix "m" for minutes, "h" for hours.) +# maxlength = <Number> +# Restricts a timer entry to a specific maximum length +# (postfix "m" for minutes, "h" for hours.) +# weekday = MTWTFSS +# Restricts a timer to a specific weekday +# Timertitle = <text> +# The title used for this timer. +# If this is not provided "Title" will be used. +# If "Title" is not provided the EPG title will be used. +# Margin = <Number>;<Number> +# Seconds added to the beginning and end of the timer. +# Positive numbers will lengthen the recording. +# instance = <Number> +# The instance of VDR for which this timer is. +# If this is not provided the timer is valid for ALL instances. # -# To record something at least one of the "Title", "Subtitle" or "Description" -# Fields has to be provided. This 3 fields are "include" and the rest are -# "exclude" fields! -# -# More than one channel definition can be provided. The delimiter is ";" -# Additionaly you can make a "blacklist" of Channels when you prepent a "!" to the first Channel Definition -# The "!" is only tested for the FIRST Channel definition. -# You can only have a white or a blacklist (Mixing doesn't make sense!) -# -# ex. Record the series "Deep Space Nine" on Sci-Fantasy in the timeframe 09:00 - 14:00 with 60 Seconds Marginstart and -60 Seconds Marginstop -# Deep Space Nine|||Sci-Fantasy|0900-1400|99|DS9|60;-60 +# The "Title", "Subtitle", "Description", "Channel"-Lines can be +# supplied any number of times for a specific entry # -# Record all "Actionfilm"s with "Schwarzenegger" -# |Actionfilm|Schwarzenegger -# -Babylon 5|||!Pro-7||99|60;-60|1 -Deep Space Nine|||||99|DS9|60;-60|2 -Seven Days|||||99| -Stargate|||||99| -Futurama||||2100-2300|50| -Ally McBeal|||||99| -Snoops|||||50| -^Friends$|||||99|Friends| -Pensacola|||||50| -seaQuest|||||50| -||Paltrow|Sci Fantasy;13th Street;Star Kino;Cine Action;Cine Comedy;Romantic Movies;Studio Universal;Premiere||99| -||Aniston|||99| -Matrix +# To record something at least one of the "Title", "Subtitle" or "Description" +# fields has to be provided. These three fields are "include" and the rest are +# "exclude" fields! + +[Dies ist ein Test-Timer] +Title = Titel +Subtitle = Subtitel +Description = Description +Category = Serie/Krimi +Channel = Pro-7 +Channel = VIVA +Timeframe = 1230-1830 +Prio = 50 +Lifetime = 50 +minlength = 10m +maxlength = 3h +weekday = ---T--- +Timertitle = Test +Margin = 600;600 +instance = 2 + +# Record Babylon 5 only if NOT playing on Pro 7; +# recording starts one minute too early and ends +# one minute too early (to skip following ads). +[Babylon 5] +Title = Babylon 5 +Channel = !Pro-7 +Prio = 99 +Margin = 60;-60 + +[DS9] +Title = Deep Space Nine +Prio = 99 +Timertitle = DS9 +Margin = 60;-60 + +[Seven Days] +Title = Seven Days +Prio = 99 + +[Stargate] +Title = Stargate +Prio = 99 + +[Aniston] +Description = Aniston +Prio = 99 +[Matrix] +Title = Matrix |