source /mod/webif/lib/setup if {![exists -proc class]} { package require oo } if {![exists -proc sqlite3.open]} { package require sqlite3 } require settings.class progressbar rsv.class mwildcard svc.class set ::epgpath /mnt/hd1/dvbepg/epg.dat set ::epgdbpath /mnt/hd1/epg.db set ::hdepgpath /media/drive1/epgsavedata if {![file exists $::epgpath] && [file exists $::hdepgpath]} { set ::epgpath $::hdepgpath set ::epgdbpath /media/drive1/epg.db } set ::channeldb 0 set ::qepg 0 catch { set ::channeldb [sqlite3.open /var/lib/humaxtv/channel.db] } if {[file exists $::epgdbpath]} { $::channeldb query {attach database '%s' as epg} $::epgdbpath set ::qepg 1 } # Maps the top nibble of descriptor 84 (content_type) to a description and # icon. set ::epg::genrelist { 0 { Unclassified Unclassified } 1 { Film Movie } 2 { "News & Factual" News } 3 { Entertainment Show } 4 { Sport Sports } 5 { Children Children } 6 { Entertainment Music } 7 { Art Art } 8 { Society Society } 9 { Education Education } 10 { Lifestyle Leisure } 11 { Unknown Unclassified } 12 { Unknown Unclassified } 13 { Unknown Unclassified } 14 { Unknown Unclassified } 15 { Drama Show } } # * service_id, event_id, start, duration, encrypted, name, text # * warning, content code, content type, # * event CRID, series CRID, rec CRID, warning mode class epg { service_id 0 event_id 0 start 0 duration 0 encrypted 0 name "" text "" warning "" warning_mode 0 content_code 0 content_type "" event_crid "" series_crid "" rec_crid "" channel 0 channel_num 0 channel_name "" channel_crid "" channel_hsvc 0 content_mgmt 0 sched_type -1 rsv 0 } epg method _parse {line} { lassign [split $line "\t"] \ service_id event_id start duration encrypted name text warning \ content_code content_type event_crid series_crid rec_crid \ warning_mode content_mgmt } epg method percent {} { set now [clock seconds] if {$start > $now} { return 0 } if {$start + $duration < $now} { return 100 } return [expr [expr $now - $start] * 100 / $duration] } epg method showing {} { set now [clock seconds] if {$start > $now} { return 0 } if {$start + $duration < $now} { return 0 } return 1 } epg method ended {} { if {$start + $duration < [clock seconds]} { return 1 } return 0 } epg method not_started {} { if {$start > [clock seconds]} { return 1 } return 0 } epg method elapsed {} { set percent [$self percent] if {$percent == 0} { return 0 } if {$percent == 100} { return $duration } return [expr $duration * $percent / 100] } epg method remaining {} { return [expr $duration - [$self elapsed]] } epg method end {} { return $($start + $duration) } epg method type_icon {} { set img "" if {[dict exists $::epg::genrelist $content_code]} { lassign $::epg::genrelist($content_code) x img } if {$img != "" && $img ne "Unclassified"} { return "/images/173_3_00_G3_$img.png" } else { return "" } } proc {epg channeliconpath} {name} { return "/img/channels/out/$name.png" } proc {epg channelicon} {name {width 0} {style ""}} { set str " 0} { append str " width=$width" } if {$style ne ""} { append str " style=\"$style\"" } append str " alt=\"\">" return $str } epg method channel_icon {{width 0} {style ""}} { set str " 0} { append str " width=$width" } if {$style ne ""} { append str " style=\"$style\"" } append str " alt=\"\">" return $str } epg method get_channel_info {} { if {$channel_num > 0} return set channel [svc load usSvcId $service_id] if {$channel != 0} { set channel_num [$channel get usLcn] set channel_name [$channel get szSvcName] set channel_crid [$channel get aucDefaultAuthority] set channel_hsvc [$channel get hSvc] } } epg method copy_channel_info {s} { set channel [$s get channel] set channel_num [$s get channel_num] set channel_name [$s get channel_name] set channel_crid [$s get channel_crid] set channel_hsvc [$s get channel_hsvc] } epg method get_rsv {} { $self get_channel_info if {$channel == 0} return if {$rsv == 0 && $event_crid ne ""} { set rsv [rsv entry $event_crid $channel_hsvc] } if {$rsv == 0 && $series_crid ne ""} { set rsv [rsv entry $series_crid $channel_hsvc] } } epg method process_sched {{debug 0}} { $self scheduled $debug } set rsvlookup "" epg method scheduled {{debug 0}} { global rsvlookup if {$sched_type >= 0} { return $sched_type } set sched_type 0 if {$rsvlookup eq ""} { set st [clock milliseconds] set rsvlookup [rsv lookuptab] if {$debug} { puts "mS $([clock milliseconds] - $st) --- $rsvlookup" } } set p 0 foreach key [list \ "$service_id:$event_id" \ "$channel_hsvc:$event_id" \ [string tolower "$service_id:$channel_crid$series_crid"] \ [string tolower "$channel_crid$series_crid:$channel_crid$event_crid"] \ ] { if {$debug} { puts "Check key ($key)" } if {[dict exists $rsvlookup $key]} { set p $rsvlookup($key) if {$debug} {puts "FOUND ($p)"} break } } switch $p { S { set sched_type 2 } E { set sched_type 1 } R { set sched_type 3 } X { set sched_type 4 } default { set sched_type 0 } } if {$debug} { puts "SCHED_TYPE: ($sched_type)" } return $sched_type } proc {epg update_lookup_tab} {svcid evtid {add true} {type "S"}} { global rsvlookup # Update the reservations look up table (if present) with single entry if {$rsvlookup == ""} return set key $svcid:$evtid if {$add} { # add new entry dict set rsvlookup $key $type } else { # remove existing entry if {[dict exists $rsvlookup $key]} { dict unset rsvlookup $key } } #puts "$svcid:$evtid $add $type == $rsvlookup" } epg method icon_set {{height 0}} { if {$height > 0} { set height "height=$height" } else { set height "" } set icon [$self type_icon] set set "" if {$icon != ""} { lappend set "\"$content_type\"" } if {$warning ne ""} { if {$warning_mode} { set icon "Guidance_red" } else { set icon "Guidance_blue" } lappend set "Guidance" } $self process_sched if {$sched_type == 1} { lappend set \ "" } if {$sched_type == 2} { lappend set \ "" } elseif {$series_crid ne ""} { lappend set \ "" } if {$rec_crid ne ""} { lappend set \ "" } if {[string match {/*#*} $event_crid]} { lappend set \ "" } if {$content_mgmt eq "1"} { lappend set \ "" } return $set } epg method cell {} { set percent [$self percent] puts "" puts [join [$self icon_set 14] ""] if {$series_crid ne ""} { set recopts 2 } else { set recopts 1 } puts " $name " puts "
" puts "" puts "[clock format $start -format %H:%M]" puts " ([clock format $duration -format %T])" if {$percent > 0 && $percent < 100} { puts "
[progressbar $percent]" puts "$percent% [clock format [$self elapsed] -format %T] / [clock format [$self remaining] -format %T]" } puts "
" puts "" } epg method next {} { set tm $($start + $duration + 60) set nextlist [epg dbfetch dump -service $service_id -time $tm] if {[llength nextlist] > 0} { return [lindex $nextlist 0] } else { return "" } } epg method previous {} { set tm $($start - 60) set prevlist [epg dbfetch dump -service $service_id -time $tm] if {[llength prevlist] > 0} { return [lindex $prevlist 0] } else { return "" } } epg method recommended {} { set rec "" if {$rec_crid ne ""} { catch { set rec [lindex [ epg dbfetch dump -crid $rec_crid] 0] } } return $rec } epg method othertimes {} { if {$event_crid eq ""} { return "" } set others "" foreach other [epg dbfetch dump -crid $event_crid] { if {[$other get service_id] == $service_id && [$other get event_id] == $event_id} { continue } lappend others $other } return $others } proc {epg parse} {line} { set e [epg new] $e _parse $line return $e } proc {epg cleanup} {} { global channeldb if {$channeldb != ""} { $channeldb close } } proc {epg exec} {mode args} { set raw 0 set cmd [list /mod/bin/epg -f $::epgpath] set extra "" foreach arg $args { if {[string first "-" $arg] == 0} { switch -- $arg { -raw { set raw 1 } -crid { lappend cmd -C $args($arg) } -scrid { lappend cmd -R $args($arg) } -type { lappend cmd -T $args($arg) } -service { lappend cmd -S $args($arg) } -event { lappend cmd -E $args($arg) } -time { lappend cmd -@ $args($arg) } -trange { lappend cmd -= $args($arg) } -day { lappend cmd -/ $args($arg) } -extra { set extra $args($arg) } default { error "Invalid option, $arg" } } } } if { $raw == 0 } { lappend cmd -p } lappend cmd $mode lappend cmd $extra #puts "CMD -$cmd-" return [exec {*}$cmd] } proc {epg dbfetch} {mode args} { set records {} set extra "" set params {} set debug 0 set select " select distinct *, usLcn as channel_num, substr(szSvcName, 2) as channel_name, aucDefaultAuthority as channel_crid, hSvc as channel_hsvc " set from " from epg.epg e join TBL_SVC c on e.service_id = c.usSvcId " set q "where 1 " set sort "order by channel_num, start" foreach arg $args { if {[string first "-" $arg] == 0} { set v $args($arg) switch -- $arg { -debug { set debug $v } -ljoin { set from " from TBL_SVC c left join epg.epg e on e.service_id = c.usSvcId " } -crid { append q \ "and e.event_crid = '$v' collate nocase " } -scrid { append q \ "and e.series_crid = '$v' collate nocase " } -type { append q \ "and e.content_code = $v " } -service { append q \ "and e.service_id = $v " } -event { append q \ "and e.event_id = $v " } -time { append q \ "and e.start < $v and e.end > $v " } -after { append q \ "and e.end >= $v " } -before { append q \ "and e.start < $v " } -sort { if {$v eq ""} { set sort "" } else { set sort "order by $v" } } -trange { lassign [split $v :] stt ett append q "and (e.start is null or (e.start > $stt and e.start < $ett) or (e.end > $stt and e.end < $ett) or (e.start <= $stt and e.end >= $ett) ) " } -fav { set v $(1 << ($v - 1)) append from \ "join TBL_FAV f using(hSvc) " append q "and f.eFavGroup = $v " set sort "order by f.favIdx, start" } -term { set v [mwildcard $v] append q "and (" append q "e.name like '%s' " lappend params "%$v%" if {$mode eq "searchall"} { append q \ "or e.text like '%s' " lappend params "%$v%" } append q ") " } -param { lappend params $v } -nocase { append q "collate nocase " } default { error "Invalid option, $arg" } } } } set query "$select $from $q $sort" if {$debug} { puts "QUERY -$query-" puts "PARAMS -$params-" } set records {} if {[catch { foreach rec [$::channeldb query $query {*}$params] { lappend records [epg new $rec] } } msg]} { puts "No cached EPG data, try again later ($msg)." } return $records } # This function is deprecated in favour of {epg dbfetch} and should not be # used. proc {epg fetch} {mode args} { set records "" foreach line [split [epg exec $mode {*}$args] "\n"] { lappend records [epg parse $line] } return $records } proc {epg favlist} {} { global channeldb set num $(1 << ([[settings] channel_group] - 1)) if {!$num} { return "" } return [lmap i [$channeldb query " select TBL_SVC.usSvcid from TBL_SVC join TBL_FAV using(hSvc) where TBL_FAV.eFavGroup == $num order by TBL_FAV.favIdx "] { lindex $i end }] } proc {epg channellist} {{field usLcn}} { global channeldb set channels {} lmap i [$channeldb query " select $field, szSvcName from TBL_SVC order by 1 "] { lappend channels [list \ [string range [lindex $i 3] 1 end] [lindex $i 1] ] } return $channels }