diff options
Diffstat (limited to 'vdradmind.pl')
-rwxr-xr-x | vdradmind.pl | 528 |
1 files changed, 372 insertions, 156 deletions
diff --git a/vdradmind.pl b/vdradmind.pl index a2f5f31..c39d55b 100755 --- a/vdradmind.pl +++ b/vdradmind.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl # vim:et:sw=4:ts=4: # -# VDRAdmin-AM 2005 - 2007 by Andreas Mair <mail@andreas.vdr-developer.org> +# VDRAdmin-AM 2005 - 2008 by Andreas Mair <mail@andreas.vdr-developer.org> # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -24,7 +24,7 @@ require 5.004; -my $VERSION = "3.6.1"; +my $VERSION = "3.6.2"; my $BASENAME; my $EXENAME; @@ -57,7 +57,7 @@ if ($@) { require File::Temp; use locale; -use Env qw(@PATH LANGUAGE); +use Env qw(@PATH LANGUAGE LANG); use CGI qw(:no_debug); use IO::Socket; use Template; @@ -68,6 +68,7 @@ use File::Temp (); use Shell qw(ps locale); use URI::Escape; +my $InetSocketModule = 'IO::Socket::INET'; my $can_use_net_smtp = 1; $can_use_net_smtp = undef unless (eval { require Net::SMTP }); my $can_use_smtpauth = 1; @@ -134,7 +135,6 @@ $CONFIG{LOCAL_NET} = "0.0.0.0/32"; $CONFIG{VIDEODIR} = "/video"; $CONFIG{VDRCONFDIR} = "$CONFIG{VIDEODIR}"; $CONFIG{EPGIMAGES} = "$CONFIG{VIDEODIR}/epgimages"; -$CONFIG{VDRVFAT} = 1; # $CONFIG{TEMPLATE} = "default"; @@ -179,18 +179,16 @@ $CONFIG{TM_TT_LIST} = 1; $CONFIG{TM_SORTBY} = "day"; $CONFIG{TM_DESC} = 0; -#$CONFIG{TM_ADD_SUMMARY} = 0; # $CONFIG{ST_FUNC} = 1; $CONFIG{ST_REC_ON} = 0; $CONFIG{ST_LIVE_ON} = 1; $CONFIG{ST_URL} = ""; +$CONFIG{ST_STREAMDEV_HOST} = ""; $CONFIG{ST_STREAMDEV_PORT} = 3000; $CONFIG{ST_VIDEODIR} = ""; # -$CONFIG{EPG_DIRECT} = 0; -$CONFIG{EPG_FILENAME} = "$CONFIG{VIDEODIR}/epg.data"; $CONFIG{EPG_PRUNE} = 0; $CONFIG{NO_EVENTID} = 0; $CONFIG{NO_EVENTID_ON} = ""; @@ -233,6 +231,10 @@ $CONFIG{PS_VIEW} = "ext"; $CONFIG{CMD_LINES} = 20; # +$CONFIG{GUI_POPUP_WIDTH} = 500; +$CONFIG{GUI_POPUP_HEIGHT} = 250; + +# my %FEATURES; $FEATURES{STREAMDEV} = 0; $FEATURES{REC_RENAME} = 0; @@ -330,7 +332,7 @@ $SIG{PIPE} = 'IGNORE'; my $DAEMON = 1; for (my $i = 0 ; $i < scalar(@ARGV) ; $i++) { $_ = $ARGV[$i]; - if (/-h|--help/) { + if (/^(-h|--help)/) { print("Usage $0 [OPTION]...\n"); print("A perl client for the Linux Video Disk Recorder.\n\n"); print(" -nf --nofork don't fork\n"); @@ -338,12 +340,13 @@ for (my $i = 0 ; $i < scalar(@ARGV) ; $i++) { print(" -d [dir] --cfgdir [dir] use [dir] for configuration files\n"); print(" -k --kill kill a forked vdradmind.pl\n"); print(" -p [name] --pid [name] name of pidfile\n"); +#TODO print(" -6 --ipv6 use IPv6\n"); print(" -h --help this message\n"); print("\nReport bugs to <mail\@andreas.vdr-developer.org>.\n"); exit(0); } - if (/--nofork|-nf/) { $DAEMON = 0; last; } - if (/--cfgdir|-d/) { + if (/^(--nofork|-nf)/) { $DAEMON = 0; last; } + if (/^(--cfgdir|-d)/) { $ETCDIR = $ARGV[ ++$i ]; $CONFFILE = "${ETCDIR}/vdradmind.conf"; $AT_FILENAME = "${ETCDIR}/vdradmind.at"; @@ -352,7 +355,7 @@ for (my $i = 0 ; $i < scalar(@ARGV) ; $i++) { $USER_CSS = "${ETCDIR}/user.css"; next; } - if (/--config|-c/) { + if (/^(--config|-c)/) { ReadConfig() if (-e $CONFFILE); LoadTranslation(); $CONFIG{VDR_HOST} = Question(gettext("What's your VDR hostname (e.g video.intra.net)?"), $CONFIG{VDR_HOST}); @@ -364,25 +367,30 @@ for (my $i = 0 ; $i < scalar(@ARGV) ; $i++) { $CONFIG{VIDEODIR} = Question(gettext("Where are your recordings stored?"), $CONFIG{VIDEODIR}); $CONFIG{VDRCONFDIR} = Question(gettext("Where are your VDR's configuration files located?"), $CONFIG{VDRCONFDIR}); - #$CONFIG{EPG_FILENAME} = Question(gettext("Where is your epg.data?"), $CONFIG{EPG_FILENAME}); - #$CONFIG{EPG_DIRECT} = ($CONFIG{EPG_FILENAME} and -e $CONFIG{EPG_FILENAME} ? 1 : 0); - WriteConfig(); print(gettext("Config file written successfully.") . "\n"); exit(0); } - if (/--kill|-k/) { + if (/^(--kill|-k)/) { exit(0) unless (-e $PIDFILE); my $killed = kill(2, getPID($PIDFILE)); unlink($PIDFILE); exit($killed > 0 ? 0 : 1); } - if (/--pid|-p/) { + if (/^(--pid|-p)/) { $PIDFILE = $ARGV[ ++$i ]; next; } - if (/--displaycall|-i/) { + if (/^(--ipv6|-6)/) { + if (eval { require IO::Socket::INET6 }) { + $InetSocketModule = 'IO::Socket::INET6'; + } else { + print("ERROR: Can't load module IO::Socket::INET6!\n"); + } + next; + } + if (/^(--displaycall|-i)/) { for (my $z = 0 ; $z < 5 ; $z++) { DisplayMessage($ARGV[ $i + 1 ]); sleep(3); @@ -390,12 +398,12 @@ for (my $i = 0 ; $i < scalar(@ARGV) ; $i++) { CloseSocket(); exit(0); } - if (/--message|-m/) { + if (/^(--message|-m)/) { DisplayMessage($ARGV[ $i + 1 ]); CloseSocket(); exit(0); } - if (/-u/) { + if (/^-u/) { # Don't use user.css $UserCSS = undef; @@ -444,11 +452,11 @@ my @reccmds = loadCommandsConf("$CONFIG{VDRCONFDIR}/reccmds.conf"); my @vdrcmds = loadCommandsConf("$CONFIG{VDRCONFDIR}/commands.conf"); my ($Socket) = - IO::Socket::INET->new(Proto => 'tcp', - LocalPort => $CONFIG{SERVERPORT}, - LocalAddr => $CONFIG{SERVERHOST}, - Listen => 10, - Reuse => 1 + $InetSocketModule->new(Proto => 'tcp', + LocalPort => $CONFIG{SERVERPORT}, + LocalAddr => $CONFIG{SERVERHOST}, + Listen => 10, + Reuse => 1 ); die("can't start server: $!\n") if (!$Socket); $CONFIG{CACHE_LASTUPDATE} = 0; @@ -464,7 +472,7 @@ my @TRUSTED_USER = ( @GUEST_USER, qw(prog_detail_form prog_detail_aktion at_timer_edit at_timer_new at_timer_save at_timer_test at_timer_delete epgsearch_upds epgsearch_edit epgsearch_save epgsearch_delete epgsearch_toggle timer_new_form timer_add timer_delete timer_toggle rec_delete rec_rename rec_edit config prog_switch rc_show rc_hitk grab_picture at_timer_toggle tv_show tv_switch - live_stream rec_stream rec_play rec_cut force_update vdr_cmds export_channels_m3u) + live_stream rec_stream rec_play rec_cut force_update vdr_cmds export_channels_m3u epgsearch_config epgsearch_bl_edit epgsearch_bl_save epgsearch_bl_delete) ); my $MyStreamBase = "./vdradmin."; @@ -583,6 +591,12 @@ while (true) { $real_aktion = "epgsearch_list" if ($q->param("favorites")); $real_aktion = "epgsearch_list" if ($q->param("exit")); $real_aktion = "epgsearch_upds" if ($q->param("upds")); + } elsif ($real_aktion eq "epgsearch_config_aktion") { + $real_aktion = "epgsearch_config"; + $real_aktion = "epgsearch_bl_delete" if ($q->param("delete")); + } elsif ($real_aktion eq "epgsearch_bl_aktion") { + $real_aktion = "epgsearch_bl_save"; + $real_aktion = "epgsearch_config" if ($q->param("exit")); } my @ALLOWED_FUNCTIONS; @@ -908,6 +922,20 @@ sub get_name_from_vdrid { } } +sub get_channel_from_vdrid { + my $vdr_id = shift; + if ($vdr_id) { + + # Kanalliste nach identischer vdr_id durchsuchen + my @C = grep($_->{vdr_id} == $vdr_id, @{$CHAN{$CHAN_FULL}->{channels}}); + + # Es darf nach Spec nur eine Übereinstimmung geben + if (scalar(@C) == 1) { + return $C[0]; + } + } +} + sub get_transponder_from_vdrid { my $vdr_id = shift; if ($vdr_id) { @@ -2162,7 +2190,8 @@ sub epgsearch_list { did_search => $do_test, title => $do_test ? ($q->param("favorites") ? gettext("Your favorites") : gettext("Search results")) : undef, matches => (@matches ? \@matches : undef), - templates => \@templates + templates => \@templates, + config_url => "$MyURL?aktion=epgsearch_config" }; return showTemplate("epgsearch_list.html", $vars); } @@ -2279,7 +2308,7 @@ sub ParseEpgSearchBlacklists { next if (length($_) == 0); last if (/^no blacklists defined$/); - push(@temp, ExtractEpgSearchConf($_)); + push(@temp, ExtractEpgSearchBlacklistConf($_)); } return @temp; @@ -2583,6 +2612,7 @@ sub validTime { } sub epgsearch_Param2Line { + my $mode_blacklist = $q->param("mode_blacklist"); my $weekdays_bits = 0; my $weekdays = 0; my $had_weekday = 0; @@ -2699,8 +2729,16 @@ sub epgsearch_Param2Line { . ($q->param("use_descr") ? "1" : "0") . ":" . ($q->param("use_duration") ? "1" : "0") . ":" . $min_duration . ":" - . $max_duration . ":" - . $q->param("has_action") . ":" + . $max_duration . ":"; + if ($mode_blacklist) { + $cmd .= ($q->param("use_days") ? "1" : "0") . ":" + . ($had_weekday > 1 ? $weekdays_bits : $weekdays) . ":" + . ($q->param("use_extepg") ? "1" : "0") . ":" + . $extepg_info . ":" + . $q->param("fuzzy_tolerance") . ":" + . $q->param("ignore_missing_epgcats"); + } else { # ! $mode_blacklist + $cmd .= $q->param("has_action") . ":" . ($q->param("use_days") ? "1" : "0") . ":" . ($had_weekday > 1 ? $weekdays_bits : $weekdays) . ":" . ($q->param("is_series") ? "1" : "0") . ":" @@ -2735,6 +2773,7 @@ sub epgsearch_Param2Line { . $searchtimer_from . ":" . $searchtimer_until . ":" . $q->param("ignore_missing_epgcats"); + } $cmd .= ":" . $q->param("unused") if ($q->param("unused")); #print("CMD: $cmd\n"); @@ -2796,6 +2835,173 @@ sub epgsearch_getDefTimerCheckMethode { return 0; } +sub epgsearch_config { + my @list; + for (ParseEpgSearchBlacklists(undef)) { + $_->{modurl} = $MyURL . "?aktion=epgsearch_bl_edit&id=" . $_->{id}; + $_->{delurl} = $MyURL . "?aktion=epgsearch_bl_delete&id=" . $_->{id}; + push(@list, $_); + } + my $vars = { usercss => $UserCSS, + url => $MyURL, + list => \@list + }; + return showTemplate("epgsearch_config.html", $vars); +} + +sub epgsearch_bl_edit { + my $id = $q->param("id"); + + my $blacklist; + my @ch_groups; + + if (defined $id) { + # edit blacklist + my @temp = ParseEpgSearchBlacklists($id); + $blacklist = pop @temp; + } else { + # new blacklist + $blacklist->{use_title} = 1; + $blacklist->{use_subtitle} = 1; + $blacklist->{use_descr} = 1; + } + + if ($blacklist->{use_channel} == 2) { + for my $cg (ParseEpgSearchChanGroups(undef)) { + $cg->{sel} = 1 if ($cg->{id} eq $blacklist->{channels}) ; + push(@ch_groups, $cg); + } + } else { + @ch_groups = ParseEpgSearchChanGroups(undef); + } + + my @extepg = ParseEpgSearchExtEpgInfos($blacklist->{extepg_infos}); + if ($blacklist->{comp_extepg_info}) { + foreach (@extepg) { + if ($blacklist->{comp_extepg_info} & (1 << ($_->{id} - 1))) { + $blacklist->{"comp_extepg_" . $_->{id}} = 1; + } + } + } + + epgsearch_getSettings(); + + my $vars = { usercss => $UserCSS, + url => $MyURL, + epgsearch => $blacklist, + channels => \@{$CHAN{$CHAN_FULL}->{channels}}, + ch_groups => \@ch_groups, + do_edit => (defined $id ? "1" : undef), + extepg => \@extepg, + mode_blacklist => 1 + }; + return showTemplate("epgsearch_new.html", $vars); +} + +sub epgsearch_bl_save { + my $cmd = (defined $q->param("id") ? "EDIB " . $q->param("id") + : "NEWB 0") + . ":" . epgsearch_Param2Line(); + SendCMD("plug epgsearch " . $cmd); + return (headerForward("$MyURL?aktion=epgsearch_config")); +} + +sub epgsearch_bl_delete { + my $id = $q->param("id"); + if (defined $id) { + SendCMD("plug epgsearch delb $id"); + } else { + for ($q->param) { + SendCMD("plug epgsearch delb $1") if (/xxxx_(.*)/); + } + } + return (headerForward("$MyURL?aktion=epgsearch_config")); +} + +sub ExtractEpgSearchBlacklistConf { + my $line = shift; + + my $timer; + ($timer->{id}, # 1 - unique search timer id + $timer->{pattern}, # 2 - the search term + $timer->{use_time}, # 3 - use time? 0/1 + $timer->{time_start}, # 4 - start time in HHMM + $timer->{time_stop}, # 5 - stop time in HHMM + $timer->{use_channel}, # 6 - use channel? 0 = no, 1 = Intervall, 2 = Channel group, 3 = FTA only + $timer->{channels}, # 7 - if 'use channel' = 1 then channel id[|channel id] in vdr format, + # one entry or min/max entry separated with |, if 'use channel' = 2 + # then the channel group name + $timer->{matchcase}, # 8 - match case? 0/1 + $timer->{mode}, # 9 - search mode: + # 0 - the whole term must appear as substring + # 1 - all single terms (delimiters are blank,',', ';', '|' or '~') + # must exist as substrings. + # 2 - at least one term (delimiters are blank, ',', ';', '|' or '~') + # must exist as substring. + # 3 - matches exactly + # 4 - regular expression + $timer->{use_title}, #10 - use title? 0/1 + $timer->{use_subtitle}, #11 - use subtitle? 0/1 + $timer->{use_descr}, #12 - use description? 0/1 + $timer->{use_duration}, #13 - use duration? 0/1 + $timer->{min_duration}, #14 - min duration in minutes + $timer->{max_duration}, #15 - max duration in minutes + $timer->{use_days}, #16 - use day of week? 0/1 + $timer->{which_days}, #17 - day of week (0 = sunday, 1 = monday...) + $timer->{use_extepg}, #18 - use extended EPG info? 0/1 #TODO + $timer->{extepg_infos}, #19 - extended EPG info values. This entry has the following format #TODO + # (delimiter is '|' for each category, '#' separates id and value): + # 1 - the id of the extended EPG info category as specified in + # epgsearchcats.conf + # 2 - the value of the extended EPG info category + # (a ':' will be tranlated to "!^colon^!", e.g. in "16:9") + $timer->{fuzzy_tolerance}, #20 - fuzzy tolerance value for fuzzy searching + $timer->{ignore_missing_epgcats}, #21 - ignoreMissingEPGCats + $timer->{unused}) = split(/:/, $line); + + #format selected fields + $timer->{time_start} =~ s/(\d\d)(\d\d)/$1:$2/ if($timer->{time_start}); + $timer->{time_stop} =~ s/(\d\d)(\d\d)/$1:$2/ if($timer->{time_stop}); + $timer->{min_duration} =~ s/(\d\d)(\d\d)/$1:$2/ if($timer->{min_duration}); + $timer->{max_duration} =~ s/(\d\d)(\d\d)/$1:$2/ if($timer->{max_duration}); + + if ($timer->{channels} && $timer->{use_channel} == 1) { + ($timer->{channel_from}, $timer->{channel_to}) = split(/\|/, $timer->{channels}, 2); + $timer->{channel_to} = $timer->{channel_from} unless ($timer->{channel_to}); + $timer->{channel_from_name} = get_name_from_uniqid($timer->{channel_from}); + $timer->{channel_to_name} = get_name_from_uniqid($timer->{channel_to}); + #TODO: links to channels + } + + if ($timer->{use_days}) { + if ($timer->{which_days} >= 0) { + $timer->{sunday} = 1 if ($timer->{which_days} == 0); + $timer->{monday} = 1 if ($timer->{which_days} == 1); + $timer->{tuesday} = 1 if ($timer->{which_days} == 2); + $timer->{wednesday} = 1 if ($timer->{which_days} == 3); + $timer->{thursday} = 1 if ($timer->{which_days} == 4); + $timer->{friday} = 1 if ($timer->{which_days} == 5); + $timer->{saturday} = 1 if ($timer->{which_days} == 6); + } else { + my $which_days = -$timer->{which_days}; + $timer->{sunday} = 1 if ($which_days & 1); + $timer->{monday} = 1 if ($which_days & 2); + $timer->{tuesday} = 1 if ($which_days & 4); + $timer->{wednesday} = 1 if ($which_days & 8); + $timer->{thursday} = 1 if ($which_days & 16); + $timer->{friday} = 1 if ($which_days & 32); + $timer->{saturday} = 1 if ($which_days & 64); + } + } + + if ($timer->{pattern}) { + $timer->{pattern} =~ s/\|/:/g; + $timer->{pattern} =~ s/\!\^pipe\^\!/\|/g; + } + + return $timer; +} + ############################################################################# # regulary timers ############################################################################# @@ -3050,6 +3256,7 @@ sub LoadTranslation { ); setlocale(LC_ALL, $CONFIG{LANG}); + $LANG = $CONFIG{LANG}; bind_textdomain_codeset("vdradmin", gettext("ISO-8859-1")) if($can_use_bind_textdomain_codeset); } @@ -3300,12 +3507,15 @@ sub ReadConfig { #v3.4.6beta $CONFIG{SKIN} = "default" if(($CONFIG{SKIN} eq "bilder") || ($CONFIG{SKIN} eq "copper") || ($CONFIG{SKIN} eq "default.png")); #v3.5.3 - $CONFIG{EPG_DIRECT} = 0; + delete $CONFIG{EPG_DIRECT}; + delete $CONFIG{EPG_FILENAME}; #v3.5.4rc if (defined $CONFIG{AT_TIMEOUT}) { $CONFIG{CACHE_TIMEOUT} = $CONFIG{AT_TIMEOUT} if ($CONFIG{AT_TIMEOUT} < $CONFIG{CACHE_TIMEOUT}); delete $CONFIG{AT_TIMEOUT}; } + #v3.6.2 + delete $CONFIG{VDRVFAT}; } else { print "$CONFFILE doesn't exist. Please run \"$0 --config\"\n"; @@ -3687,7 +3897,20 @@ sub prog_list { ); } } - $vdr_id = $channel[0]->{vdr_id} unless ($current); + + unless ($current) { + my $channel = get_channel_from_vdrid($vdr_id); + if ($channel) { + unshift(@channel, + { name => '[' . $channel->{name} .']' . (!$CONFIG{CHANNELS_WITHOUT_EPG} || ChannelHasEPG($channel->{vdr_id}) ? '' : ' (' . gettext("No EPG information available") . ')'), + vdr_id => $channel->{vdr_id}, + current => 1 + } + ); + } else { + $vdr_id = $channel[0]->{vdr_id}; + } + } # find the next/prev channel my $ci = 0; @@ -3705,7 +3928,12 @@ sub prog_list { if (my_strftime("%d", $event->{start}) != $day) { # new day - push(@show, { endd => 1 }) if (scalar(@show) > 0); + push(@show, + { endd => 1, + next_channel => $next_channel ? "$MyURL?aktion=prog_list&vdr_id=$next_channel" : undef, + prev_channel => $prev_channel ? "$MyURL?aktion=prog_list&vdr_id=$prev_channel" : undef, + } + ) if (scalar(@show) > 0); push(@show, { progname => $event->{channel_name}, longdate => my_strftime("%A, %x", $event->{start}), @@ -4321,8 +4549,6 @@ sub timer_new_form { my $displaysummary = $this_event->{summary}; $displaysummary =~ s/\|/\n/g if ($displaysummary); - my $displaytitle = $this_event->{title}; - $displaytitle =~ s/"/\"/g; my $vars = { url => $MyURL, active => $this_event->{active} & 1, @@ -4337,7 +4563,7 @@ sub timer_new_form { dor => ($this_event->{dor} && (length($this_event->{dor}) == 7 || length($this_event->{dor}) == 10 || length($this_event->{dor}) == 18)) ? $this_event->{dor} : my_strftime("%d", $this_event->{start}), prio => $this_event->{prio} ne "" ? $this_event->{prio} : $CONFIG{TM_PRIORITY}, lft => $this_event->{lft} ne "" ? $this_event->{lft} : $CONFIG{TM_LIFETIME}, - title => $displaytitle, + title => $this_event->{title}, summary => $displaysummary, pattern => $this_event->{pattern}, timer_id => $timer_id ? $timer_id : 0, @@ -4491,8 +4717,6 @@ sub rec_stream { my ($id) = $q->param('id'); my ($i, $title, $newtitle); my $data; - my $f; - my (@tmp, $dirname, $name, $parent, @files); my ($date, $time, $day, $month, $hour, $minute); my $c; @@ -4506,42 +4730,62 @@ sub rec_stream { ($day, $month) = split(/\./, $date); ($hour, $minute) = split(/:/, $time); - # escape characters - if ($CONFIG{VDRVFAT} > 0) { - for ($i = 0 ; $i < length($title) ; $i++) { - $c = substr($title, $i, 1); - unless ($c =~ /[öäüßÖÄÜA-Za-z0123456789_!@\$%&()+,.\-;=~ ]/) { - $newtitle .= sprintf("#%02X", ord($c)); - } else { - $newtitle .= $c; - } - } - } else { - for ($i = 0 ; $i < length($title) ; $i++) { - $c = substr($title, $i, 1); - if ($c eq "/") { - $newtitle .= "\x02"; - } elsif ($c eq "\\") { - $newtitle .= "\x01"; - } else { - $newtitle .= $c; - } + # VFAT off + $data = findVideoFiles($minute, $hour, $day, $month, encode_RecTitle($title, 0)); + unless ($data) { + # VFAT on + $data = findVideoFiles($minute, $hour, $day, $month, encode_RecTitle($title, 1)); + } + } + return (header("200", $CONFIG{REC_MIMETYPE}, $data)); +} + +sub encode_RecTitle { + my ($title, $use_vfat) = @_; + my ($c, $i, $newtitle); + + if ($use_vfat) { + # VFAT on + for ($i = 0 ; $i < length($title) ; $i++) { + $c = substr($title, $i, 1); + unless ($c =~ /[öäüßÖÄÜA-Za-z0123456789_!@\$%&()+,.\-;=~ ]/) { + $newtitle .= sprintf("#%02X", ord($c)); + } else { + $newtitle .= $c; } } - $title = $newtitle; - $title =~ s/ /_/g; - $title =~ s/~/\//g; - Log(LOG_DEBUG, "rec_stream: find $CONFIG{VIDEODIR}/ -follow -regex \"$CONFIG{VIDEODIR}/$title\_*/\\(\_/\\)?....-$month-$day\\.$hour.$minute\\...\\...\\.rec/...\\.vdr\""); - @files = `find $CONFIG{VIDEODIR}/ -follow -regex "$CONFIG{VIDEODIR}/$title\_*/\\(\_/\\)?....-$month-$day\\.$hour.$minute\\...\\...\\.rec/...\\.vdr" | sort -r`; - foreach (@files) { - chomp; - Log(LOG_DEBUG, "rec_stream: found ($_)\n"); - $_ =~ s/$CONFIG{VIDEODIR}/$CONFIG{ST_VIDEODIR}/; - $_ =~ s/\n//g; - $data = $CONFIG{ST_URL} . "$_\n$data"; + } else { + # VFAT off + for ($i = 0 ; $i < length($title) ; $i++) { + $c = substr($title, $i, 1); + if ($c eq "/") { + $newtitle .= "\x02"; + } elsif ($c eq "\\") { + $newtitle .= "\x01"; + } else { + $newtitle .= $c; + } } } - return (header("200", $CONFIG{REC_MIMETYPE}, $data)); + + return $newtitle; +} + +sub findVideoFiles { + my ($minute, $hour, $day, $month, $title) = @_; + my $data; + $title =~ s/ /_/g; + $title =~ s/~/\//g; + Log(LOG_DEBUG, "rec_stream: find $CONFIG{VIDEODIR}/ -follow -regex \"$CONFIG{VIDEODIR}/$title\_*/\\(\_/\\)?....-$month-$day\\.$hour.$minute\\...\\...\\.rec/...\\.vdr\""); + my @files = `find $CONFIG{VIDEODIR}/ -follow -regex "$CONFIG{VIDEODIR}/$title\_*/\\(\_/\\)?....-$month-$day\\.$hour.$minute\\...\\...\\.rec/...\\.vdr" | sort -r`; + foreach (@files) { + chomp; + Log(LOG_DEBUG, "rec_stream: found ($_)\n"); + $_ =~ s/$CONFIG{VIDEODIR}/$CONFIG{ST_VIDEODIR}/; + $_ =~ s/\n//g; + $data = $CONFIG{ST_URL} . "$_\n$data"; + } + return $data; } sub getReferer { @@ -4567,20 +4811,24 @@ sub live_stream { my $progname = $q->param("progname"); my ($data, $ifconfig, $ip); - if ($CONFIG{VDR_HOST} eq "localhost") { - $ifconfig = `/sbin/ifconfig eth0`; - if ($ifconfig =~ /inet.+:(\d+\.\d+\.\d+\.\d+)\s+Bcast/) { - $ip = $1; + if ($CONFIG{ST_STREAMDEV_HOST}) { + $ip = $CONFIG{ST_STREAMDEV_HOST}; + } else { + if ($CONFIG{VDR_HOST} eq "localhost") { + $ifconfig = `/sbin/ifconfig eth0`; + if ($ifconfig =~ /inet.+:(\d+\.\d+\.\d+\.\d+)\s+Bcast/) { + $ip = $1; + } else { + $ip = `hostname`; + } } else { - $ip = `hostname`; + $ip = $CONFIG{VDR_HOST}; } - } else { - $ip = $CONFIG{VDR_HOST}; } chomp($ip); $data = ""; $data .= "#EXTINF:0,$progname\n" if ($progname); - $data .= "http://$ip:$CONFIG{ST_STREAMDEV_PORT}/$channel"; + $data .= "http://$ip:$CONFIG{ST_STREAMDEV_PORT}/$channel\n"; return (header("200", $CONFIG{TV_MIMETYPE}, $data)); } @@ -5209,7 +5457,10 @@ sub prog_summary { title => gettext("No EPG information available"), progname => CGI::escapeHTML($channel->{name}), vdr_id => $channel->{vdr_id}, - proglink => sprintf("%s?aktion=prog_list&vdr_id=%s", $MyURL, $channel->{vdr_id}), + proglink => sprintf("%s?aktion=prog_list&vdr_id=%s", $MyURL, $channel->{vdr_id}), + switchurl => sprintf("%s?aktion=prog_switch&channel=%s", $MyURL, $channel->{vdr_id}), + streamurl => $FEATURES{STREAMDEV} ? sprintf("%s%s?aktion=live_stream&channel=%s&progname=%s", $MyStreamBase, $CONFIG{TV_EXT}, $channel->{vdr_id}, uri_escape($channel->{name})) : undef, + stream_live_on => $FEATURES{STREAMDEV} ? $CONFIG{ST_FUNC} && $CONFIG{ST_LIVE_ON} : undef, anchor => "id" . $channel->{vdr_id} } ); @@ -5578,9 +5829,9 @@ sub getRecInfo { my $vars; if ($VDRVERSION >= 10325) { $SVDRP->command("lstr $id"); - my ($channel_id, $subtitle, $text, $video, $audio); + my ($channel_name, $subtitle, $text, $video, $audio); while ($_ = $SVDRP->readoneline) { - #if(/^C (.*)/) { $channel_id = $1; } + if(/^C (.*)/) { $channel_name = get_name_from_uniqid($1); } #if(/^E (.*)/) { $epg = $1; } if (/^T (.*)/) { $title = $1; } if (/^S (.*)/) { $subtitle = $1; } @@ -5630,9 +5881,10 @@ sub getRecInfo { $displaysubtitle =~ s/\|/<br \/>\n/g; $vars = { url => $MyURL, - text => $displaytext ? $displaytext : undef, - title => $displaytitle ? $displaytitle : undef, - subtitle => $displaysubtitle ? $displaysubtitle : undef, + text => $displaytext || undef, + title => $displaytitle || undef, + subtitle => $displaysubtitle || undef, + channel_name => $channel_name || undef, srch1_url => $imdb_url, srch1_title => $imdb_url ? gettext($CONFIG{SRCH1_TITLE}) : undef, srch2_url => $srch2_url, @@ -5640,7 +5892,7 @@ sub getRecInfo { id => $id, video => $video, audio => $audio, - referer => $ref ? $ref : undef + referer => $ref || undef }; } else { my ($text); @@ -5752,42 +6004,32 @@ sub recRunCmd { ($day, $month) = split(/\./, $date); ($hour, $minute) = split(/:/, $time); - # escape characters - if ($CONFIG{VDRVFAT} > 0) { - for (my $i = 0 ; $i < length($title) ; $i++) { - $c = substr($title, $i, 1); - unless ($c =~ /[öäüßÖÄÜA-Za-z0123456789_!@\$%&()+,.\-;=~ ]/) { - $newtitle .= sprintf("#%02X", ord($c)); - } else { - $newtitle .= $c; - } - } - } else { - for (my $i = 0 ; $i < length($title) ; $i++) { - $c = substr($title, $i, 1); - if ($c eq "/") { - $newtitle .= "\x02"; - } elsif ($c eq "\\") { - $newtitle .= "\x01"; - } else { - $newtitle .= $c; - } - } + # VFAT off + my $folder = findVideoFolder($minute, $hour, $day, $month, encode_RecTitle($title, 0)); + unless ($folder) { + # VFAT on + $folder = findVideoFolder($minute, $hour, $day, $month, encode_RecTitle($title, 1)); } - $title = $newtitle; - $title =~ s/ /_/g; - $title =~ s/~/\//g; - $folder = `find $CONFIG{VIDEODIR}/ -follow -regex "$CONFIG{VIDEODIR}/$title\_*/\\(\_/\\)?....-$month-$day\\.$hour.$minute\\...\\...\\.rec"`; - Log(LOG_DEBUG, "recRunCmd: find $CONFIG{VIDEODIR}/ -follow -regex \"$CONFIG{VIDEODIR}/$title\_*/\\(\_/\\)?....-$month-$day\\.$hour.$minute\\...\\...\\.rec\""); - if ($folder) { - chomp($folder); - Log(LOG_DEBUG, "recRunCmd: found ($folder)"); + Log(LOG_DEBUG, "recRunCmd: executing ($cmd \"$folder\")"); `$cmd "$folder"`; } } } +sub findVideoFolder { + my ($minute, $hour, $day, $month, $title) = @_; + my $folder; + + $title =~ s/ /_/g; + $title =~ s/~/\//g; + $folder = `find $CONFIG{VIDEODIR}/ -follow -regex "$CONFIG{VIDEODIR}/$title\_*/\\(\_/\\)?....-$month-$day\\.$hour.$minute\\...\\...\\.rec"`; + Log(LOG_DEBUG, "findVideoFolder: find $CONFIG{VIDEODIR}/ -follow -regex \"$CONFIG{VIDEODIR}/$title\_*/\\(\_/\\)?....-$month-$day\\.$hour.$minute\\...\\...\\.rec\""); + chomp($folder) if ($folder); + + return $folder; +} + sub rec_edit { # determine referer (redirect to where we come from) @@ -6218,15 +6460,19 @@ sub export_channels_m3u { my $wanted = $q->param("wanted"); my @filenames = ( 'vdr_full_channels', 'vdr_selected_channels', 'vdr_tv_channels', 'vdr_radio_channels' ); my ($ip, $ifconfig); - if ($CONFIG{VDR_HOST} eq "localhost") { - $ifconfig = `/sbin/ifconfig eth0`; - if ($ifconfig =~ /inet.+:(\d+\.\d+\.\d+\.\d+)\s+Bcast/) { - $ip = $1; + if ($CONFIG{ST_STREAMDEV_HOST}) { + $ip = $CONFIG{ST_STREAMDEV_HOST}; + } else { + if ($CONFIG{VDR_HOST} eq "localhost") { + $ifconfig = `/sbin/ifconfig eth0`; + if ($ifconfig =~ /inet.+:(\d+\.\d+\.\d+\.\d+)\s+Bcast/) { + $ip = $1; + } else { + $ip = `hostname`; + } } else { - $ip = `hostname`; + $ip = $CONFIG{VDR_HOST}; } - } else { - $ip = $CONFIG{VDR_HOST}; } chomp($ip); @@ -6241,7 +6487,7 @@ sub export_channels_m3u { # Authentication ############################################################################# -sub subnetcheck { +sub subnetcheck { #TODO: IPv6 support my $ip = $_[0]; my $net = $_[1]; my ($ip1, $ip2, $ip3, $ip4, $net_base, $net_range, $net_base1, $net_base2, $net_base3, $net_base4, $bin_ip, $bin_net); @@ -6277,7 +6523,7 @@ sub false () { main::false(); } sub LOG_VDRCOM () { main::LOG_VDRCOM(); } sub CRLF () { main::CRLF(); } -my ($SOCKET, $EPGSOCKET, $query, $connected, $epg); +my ($SOCKET, $EPGSOCKET, $query, $connected); sub new { my $invocant = shift; @@ -6286,23 +6532,17 @@ sub new { bless($self, $class); $connected = false; $query = false; - $epg = false; return $self; } sub myconnect { my $this = shift; - if ($epg && $CONFIG{EPG_DIRECT}) { - main::Log(LOG_VDRCOM, "LOG_VDRCOM: open EPG $CONFIG{EPG_FILENAME}"); - open($EPGSOCKET, $CONFIG{EPG_FILENAME}) || main::HTMLError(sprintf($ERROR_MESSAGE{cant_open}, $CONFIG{EPG_FILENAME})); - return; - } main::Log(LOG_VDRCOM, "LOG_VDRCOM: connect to $CONFIG{VDR_HOST}:$CONFIG{VDR_PORT}"); $SOCKET = - IO::Socket::INET->new(PeerAddr => $CONFIG{VDR_HOST}, - PeerPort => $CONFIG{VDR_PORT}, - Proto => 'tcp' + $InetSocketModule->new(PeerAddr => $CONFIG{VDR_HOST}, + PeerPort => $CONFIG{VDR_PORT}, + Proto => 'tcp' ) || main::HTMLError(sprintf($ERROR_MESSAGE{connect_failed}, $CONFIG{VDR_HOST}, $CONFIG{VDR_PORT})) && return; @@ -6341,12 +6581,6 @@ sub getSupportedFeatures { sub close { my $this = shift; - if ($epg && $CONFIG{EPG_DIRECT}) { - main::Log(LOG_VDRCOM, "LOG_VDRCOM: closing EPG"); - close $EPGSOCKET; - $epg = false; - return; - } if ($connected) { main::Log(LOG_VDRCOM, "LOG_VDRCOM: closing connection"); command($this, "quit"); @@ -6360,19 +6594,9 @@ sub command { my $this = shift; my $cmd = join("", @_); - if ($cmd =~ /^lste/ && $CONFIG{EPG_DIRECT}) { - $epg = true; - main::Log(LOG_VDRCOM, sprintf("LOG_VDRCOM: special epg ")); - } else { - $epg = false; - } - if (!$connected || $epg) { + if (!$connected) { myconnect($this); } - if ($epg) { - $query = true; - return; - } main::Log(LOG_VDRCOM, sprintf("LOG_VDRCOM: send \"%s\"", $cmd)); $cmd = $cmd . CRLF; @@ -6390,14 +6614,6 @@ sub readoneline { my $this = shift; my $line; - if ($epg && $CONFIG{EPG_DIRECT}) { - $line = <$EPGSOCKET>; - $line =~ s/\n$//; - main::Log(LOG_VDRCOM, sprintf("LOG_VDRCOM: EPGread \"%s\"", $line)); - $query = true; - return ($line); - } - if ($SOCKET && $SOCKET->connected() && $query) { $line = <$SOCKET>; $line =~ s/\r\n$//; |