webif/webif/lib/ts.class
hummypkg 2e3ce0aed1 1.2.2-4 - faster decrypt
git-svn-id: file:///root/webif/svn/pkg/webif/trunk@2383 2a923420-c742-0410-a762-8d5b09965624
2015-04-10 22:01:51 +00:00

603 lines
12 KiB
Plaintext

if {![exists -proc class]} { package require oo }
if {![exists -proc pack]} { package require pack }
source /mod/webif/lib/setup
require system.class tvdb.class classdump
set tsgroup {ts nts hmt thm}
class ts {
file ""
base ""
title ""
synopsis ""
definition ""
channel_num 0
channel_name ""
start 0
end 0
flags ""
error ""
guidance ""
bookmarks 0
schedstart 0
scheddur 0
genre 0
resume 0
status ""
series ""
seriesnum 0
episodenum 0
episodetot 0
episodename ""
tvdb_method ""
tvdb_series {}
tvdb_data {}
}
ts method bfile {} {
return [file tail [file rootname $file]]
}
ts method dir {} {
return [file dirname $file]
}
ts method duration {{raw 0}} {
set d [expr $end - $start]
if {!$raw} { set d $($d / 60) }
return $d
}
ts method size {} {
return [file size $file]
}
ts method _parse {line} {
set vars [split $line "\t"]
lassign [split $line "\t"] \
title synopsis definition channel_num channel_name \
start end flags_list guidance bookmarks schedstart scheddur \
genre resume status
set flags [split [string range $flags_list 0 end-1] ,]
}
ts method lastmod {} {
return [file mtime "[file rootname $file].hmt"]
}
ts method inuse {} {
return [system inuse $file]
}
ts method bookmarks {{aslist 0}} {
set marks [split [string trim [exec /mod/bin/hmt -bookmarks $file]]]
if {$aslist} { return $marks }
return [join $marks " "]
}
ts method setbookmarks {marks} {
exec /mod/bin/hmt +setbookmarks=[join $marks :] $file
}
ts method flag {f} {
if {$f in $flags} {return 1} else {return 0}
}
ts method unlock {} {
set cmd [list /mod/bin/hmt -lock $file]
exec {*}$cmd
lremove flags "Locked"
return 1
}
ts method lock {} {
set cmd [list /mod/bin/hmt +lock $file]
exec {*}$cmd
ladd flags "Locked"
return 1
}
ts method set_shrunk {} {
set cmd [list /mod/bin/hmt +shrunk $file]
exec {*}$cmd
ladd flags "Shrunk"
return 1
}
ts method set_deduped {} {
set cmd [list /mod/bin/hmt +dedup $file]
exec {*}$cmd
ladd flags "Deduped"
return 1
}
ts method unset_deduped {} {
set cmd [list /mod/bin/hmt -dedup $file]
exec {*}$cmd
lremove flags "Deduped"
return 1
}
ts method unenc {} {
set cmd [list /mod/bin/hmt -protect $file]
exec {*}$cmd
lremove flags "Encrypted"
return 1
}
ts method enc {} {
set cmd [list /mod/bin/hmt +protect $file]
exec {*}$cmd
ladd flags "Encrypted"
return 1
}
ts method set_new {} {
set cmd [list /mod/bin/hmt +new $file]
exec {*}$cmd
ladd flags "New"
return 1
}
ts method set_watched {} {
set cmd [list /mod/bin/hmt -new $file]
exec {*}$cmd
lremove flags "New"
return 1
}
ts method setfile {f} { set file $f }
proc {ts parse} {file line} {
set e [ts new]
$e setfile $file
$e _parse $line
return $e
}
proc {ts exec} {file} {
set raw 0
set cmd [list /mod/bin/hmt]
lappend cmd "-p"
lappend cmd $file
#puts "CMD -$cmd-"
return [exec {*}$cmd]
}
ts method fileset {} {
global tsgroup
set root [file rootname $file]
set fset {}
foreach ext $tsgroup {
if {[file exists "$root.$ext"]} {
lappend fset "$root.$ext"
}
}
return $fset
}
proc {ts fetch} {file {checked 0}} {
# Check that this is a .ts file which has at least one sidecar
# file (.nts)
if {!$checked} {
if {[file extension $file] ne ".ts"} { return 0 }
if {![file exists "[file rootname $file].nts"]} { return 0 }
}
if {[file extension $file] ne ".ts"} {
set file "[file rootname $file].ts"
}
return [ts parse $file [ts exec $file]]
}
ts method delete {} {
foreach f [$self fileset] {
file tdelete $f
puts "Removed $f<br>"
}
return 1
}
ts method move {dst {touch 0} {force 0}} {
foreach f [$self fileset] {
set nf "$dst/[file tail $f]"
while {[file exists $nf]} {
set nf "$dst/_[file tail $nf]"
}
file rename $f $nf
if {$touch} {
exec /mod/bin/busybox/touch $nf
}
}
return 1
}
ts method copy {dst} {
foreach f [$self fileset] {
file copy $f "$dst/[file tail $f]"
}
return 1
}
ts method settitle {newtitle} {
if {[string length newtitle] > 48} { return }
exec /mod/bin/hmt "+settitle=${newtitle}" $file
set title $newtitle
}
ts method setsynopsis {newsynopsis} {
if {[string length newsynopsis] > 252} { return }
exec /mod/bin/hmt "+setsynopsis=${newsynopsis}" $file
set synopsis $newsynopsis
}
ts method setguidance {newguidance} {
if {[string length newguidance] > 48} { return }
if {$newguidance eq ""} {
exec /mod/bin/hmt "-guidance" $file
} else {
exec /mod/bin/hmt "+setguidance=${newguidance}" $file
}
set guidance $newguidance
}
ts method setgenre {newgenre} {
exec /mod/bin/hmt "+setgenre=-${newgenre}" $file
set genre $newgenre
}
ts method dlnaloc {{urlbase ""}} {
return [system dlnaurl [file normalize $file] $urlbase]
}
ts method cleanbmp {} {
set bfile [file rootname $file]
foreach f [glob -nocomplain "${bfile}*.bmp"] {
file delete $f
}
}
ts method mkbmps {{offset 0}} {
set bfile [file rootname $file]
if {[catch {
exec /mod/bin/ffmpeg -loglevel fatal -ss $offset -i $file \
-vf fps=fps=2 -frames 5 \
-pix_fmt argb -vf vflip -s 140x78 "${bfile}%d.bmp"
} msg]} {
puts "ERROR: $msg"
return 0
}
return 1
}
ts method mkbmp {{offset 0} {ext ""}} {
set bfile [file rootname $file]
if {[catch {
exec /mod/bin/ffmpeg -loglevel fatal -ss $offset -i $file \
-frames 1 -pix_fmt argb -vf vflip -s 140x78 "$bfile$ext.bmp"
} msg]} {
puts "ERROR: $msg"
return 0
}
return 1
}
ts method mkthm {{offset 0}} {
if {![$self mkbmp $offset]} { return 0 }
set bfile [file rootname $file]
if {[catch {
exec /bin/dd if=$bfile.bmp of=$bfile.thm~ bs=54 skip=1
} msg]} {
puts "ERROR: $msg"
return 0
}
exec /bin/echo -n " " >> $bfile.thm~
file rename -force $bfile.thm~ $bfile.thm
file tdelete $bfile.bmp
return 1
}
proc {ts renamegroup} {from to} {
global tsgroup
set dir [file dirname $from]
set root [file rootname $from]
# Catch from string without a . character in it
if {$root eq $from} { return }
foreach ext $tsgroup {
set f "$root.$ext"
if {![file exists $f]} continue
file rename $f "${dir}/${to}.${ext}"
}
exec /mod/bin/hmt "+setfilename=$to" "${dir}/${to}.hmt"
# set ndir [file normalize $dir]
#
# if {![catch {set db [sqlite3.open $::dmsfile]}]} {
# catch {
# set x [lindex [$db query {select mediaid from tblMedia
# where localUrl = '%s'} [file normalize $from]] 0]
# lassign $x key mediaid
# if {$mediaid ne ""} {
# $db query {update tblMedia set localUrl = '%s'
# where mediaid = %s} "${ndir}/{$to}.ts" $mediaid
# $db query {update tblMedia set title = '%s'
# where mediaid = %s} "{$to}.ts" $mediaid
# }
# }
# $db close
# }
}
proc {ts touchgroup} {target ref} {
global tsgroup
set dir [file dirname $target]
set root [file rootname $target]
# Catch from string without a . character in it
if {$root eq $target} { return }
foreach ext $tsgroup {
set f "$root.$ext"
if {![file exists $f]} continue
file touch $f $ref
}
}
proc {ts genrelist} {} {
return {
0 { Unclassified Unclassified }
16 { Film Movie }
32 { "News & Factual" News }
48 { Entertainment Special }
64 { Sport Sports }
80 { Children Children }
96 { Entertainment Special }
144 { Education Education }
160 { Lifestyle Leisure }
240 { Drama Show }
}
}
proc {ts resetnew} {dir} {
if {![file isdirectory $dir]} return
if {![file exists "$dir/.series"]} {
set fd [open "$dir/.series" "w"]
puts -nonewline $fd [string repeat "\x0" 276]
close $fd
}
set tot 0
set watched 0
foreach file [readdir -nocomplain $dir] {
if {![string match {*.ts} $file]} { continue }
incr tot
if {[set ts [ts fetch "$dir/$file"]] != 0} {
if {![$ts flag "New"]} { incr watched }
}
}
if {!$tot} {
file delete "$dir/.series"
return
}
set fd [open "$dir/.series"]
set bytes [read $fd]
close $fd
set recs [unpack $bytes -uintle 0 32]
set played [unpack $bytes -uintle 32 32]
#puts "Current: $played/$recs"
#hexdump $bytes
#puts "Calculated: $watched/$tot"
pack bytes $tot -intle 32 0
pack bytes $watched -intle 32 32
#hexdump $bytes
set fd [open "$dir/.series" "w"]
puts -nonewline $fd $bytes
close $fd
}
proc {ts iterate} {callback {verbose 0} {dir ""}} {{rootdev 0}} {
require system.class
if {$dir eq ""} {
set dir [system mediaroot]
file stat "$dir/" rootstat
set rootdev $rootstat(dev)
}
if {$verbose} { puts "Scanning directory ($dir)" }
if {$rootdev != 0} {
file stat "$dir/" st
if {$st(dev) != $rootdev} return
}
foreach entry [readdir -nocomplain $dir] {
if {[file isdirectory "$dir/$entry"]} {
ts iterate $callback $verbose "$dir/$entry"
continue
}
if {![string match {*.ts} $entry]} continue
if {[catch {set ts [ts fetch "$dir/$entry"]}]} continue
if {$ts == 0} continue
$callback $ts
}
}
#
# Attempt to extract the series/episode names using a variety of techniques
#
ts method series_name {} {
# For recorded series, use the folder name
set dir [file dirname $file]
if {[file exists "$dir/.series"]} {
set s [file tail $dir]
} else {
set s $title
}
foreach x {
{^new: *}
} {
regsub -nocase -all -- $x $s "" s
}
return $s
}
set ::ts::episode_prefixes {
{^new series\.* *}
{^cbeebies\.* *}
{^cbbc\.* *}
{^t4: *}
{^brand new series *[-:]* *}
{^\.+}
}
ts method tvdb_resolve {} {
# See if we can find a TVDB series for this recording.
set tvdb_series [set v [tvdb series [$self series_name]]]
if {[$v get seriesid] == 0} { return }
# Got one.
if {$seriesnum && $episodenum} {
# Easiest case - we can explicitly request the episode.
set tvdb_method "series and episode number"
return [$v episodebynum $seriesnum $episodenum]
}
# Now try to find the episode using the current episode name
set k [$v episodebyname $episodename]
if {[llength $k]} {
set tvdb_method "episode name ($episodename)"
return $k
}
if {$episodenum} {
# More problematic but can at least narrow the list of
# candidates.
set tvdb_method "episode number"
return [$v episodebyepnum $episodenum $synopsis]
}
# Most difficult - try and match based on synopsis alone
set tvdb_method "synopsis text"
return [$v episodebysynopsis $synopsis]
}
ts method episode_name {} {
set s $synopsis
######################################################################
# Attempt to determine the episode name from the synopsis
# Strip common prefixes
foreach prefix $::ts::episode_prefixes {
regsub -nocase -all -- $prefix $s "" s
}
# Strip anything following a colon.
regsub -all -- { *[:].*$} $s "" s
# If the resulting string is longer than 40 characters then
# split around . and take the left hand side if appropriate.
if {[string length $s] > 40} {
lassign [split $s "."] v w
set s $v
if {[string length $s] < 6 && [string length $w] < 6} {
append s "_$w"
}
}
# Shorten if too long.
if {[string length $s] > 40} { set s [string range $s 0 39] }
set episodename $s
######################################################################
# Check for embedded Series/Episode number.
# Thank you broadcasters for the variation!
# Least trustworthy first.
# Episode 5
regexp -nocase -- {Episode (\d+)} $synopsis x episodenum
# ^23/27.
regexp -nocase -- {^\s*(\d+)/(\d+)} $synopsis x episodenum episodetot
# (8/8)
regexp -nocase -- {\((\d+)/(\d+)\)} $synopsis x episodenum episodetot
# (Episode 5/10)
# (Ep5/10)
# (Ep 3 of 3)
# (Ep3)
regexp -nocase -- {Epi?s?o?d?e?\s*(\d+)\s*(of|/)?\s*(\d+)?} $synopsis \
x episodenum x episodetot
# (S2 Ep1)
# S.02 Ep.002
# S01 Ep52
# (S4 Ep 7)
# (S1, ep 2)
# (S8, Ep2)
# (S4 Ep22/24)
regexp -nocase -- {S\.*(\d+),?\s*Ep\.?\s*(\d+)(/(\d+))?} $synopsis \
x seriesnum episodenum x episodetot
foreach v {seriesnum episodenum episodetot} {
if {[set $v] eq ""} {
set $v 0
} else {
incr $v 0
}
}
# Now see if TVDB has anything to add
if {[system has tvdb]} {
set tvdb_data [$self tvdb_resolve]
if {[dict exists $tvdb_data name]} {
if {!$seriesnum} { set seriesnum $tvdb_data(series) }
if {!$episodenum} { set episodenum $tvdb_data(episode) }
return $tvdb_data(name)
}
}
return $s
}
ts method epstr {} {
set x s
if {$seriesnum eq 0} { append x "?" } else { append x $seriesnum }
append x e
if {$episodenum eq 0} { append x "??" } else { append x $episodenum }
if {$episodetot ne 0} { append x "/$episodetot" }
return $x
}