forked from hummypkg/webif
900 lines
18 KiB
Tcl
900 lines
18 KiB
Tcl
|
|
if {![exists -command class]} { package require oo }
|
|
if {![exists -command pack]} { package require pack }
|
|
if {![exists -command xconv]} { package require xconv }
|
|
if {![exists -command binary]} { package require binary }
|
|
|
|
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 ""
|
|
|
|
seriescached 1
|
|
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 seriesnum episodenum episodetot
|
|
|
|
set synopsis [xconv $synopsis]
|
|
|
|
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 storeepisode {{data {}}} {
|
|
if {[llength $data]} {
|
|
set d [join $data ","]
|
|
} else {
|
|
set d "$seriesnum,$episodenum,$episodetot"
|
|
}
|
|
exec /mod/bin/hmt +setseries=$d $file
|
|
}
|
|
|
|
ts method clearepdata {} {
|
|
set seriesnum 0
|
|
set episodenum 0
|
|
set episodetot 0
|
|
}
|
|
|
|
ts method flag {f} {
|
|
if {$f in $flags} {return 1} else {return 0}
|
|
}
|
|
|
|
ts method unflag {f} {
|
|
lremove flags $f
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
set ::ts::flagmap {
|
|
detectads Addetection
|
|
dedup Deduped
|
|
encrypted ODEncrypted
|
|
protect Encrypted
|
|
}
|
|
|
|
ts method setflag {flag {dummy 0}} {
|
|
if {!$dummy} {
|
|
set cmd [list /mod/bin/hmt +$flag $file]
|
|
if {[catch {exec {*}$cmd}]} {
|
|
throw 20 "Unknown flag."
|
|
}
|
|
}
|
|
if {[dict exists $::ts::flagmap $flag]} {
|
|
ladd flags $::ts::flagmap($flag)
|
|
} else {
|
|
ladd flags [string totitle $flag]
|
|
}
|
|
return 1
|
|
}
|
|
|
|
ts method unsetflag {flag {dummy 0}} {
|
|
if {!$dummy} {
|
|
set cmd [list /mod/bin/hmt -$flag $file]
|
|
if {[catch {exec {*}$cmd}]} {
|
|
throw 20 "Unknown flag."
|
|
}
|
|
}
|
|
if {[dict exists $::ts::flagmap $flag]} {
|
|
lremove flags $::ts::flagmap($flag)
|
|
} else {
|
|
lremove flags [string totitle $flag]
|
|
}
|
|
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_or_error} {file {checked 0}} {
|
|
if {[catch {set ts [ts fetch $file $checked]}] || $ts == 0} {
|
|
print "Could not load ts file $file"
|
|
return 0
|
|
}
|
|
return $ts
|
|
}
|
|
|
|
proc {ts fetch} {file {checked 0}} {
|
|
# Check that this is a .ts file which has at least one sidecar
|
|
# file (.hmt)
|
|
if {!$checked} {
|
|
if {[file extension $file] ne ".ts"} { return 0 }
|
|
if {![file exists "[file rootname $file].hmt"]} { 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] > 74} { return }
|
|
|
|
if {$newguidance eq ""} {
|
|
exec /mod/bin/hmt "-guidance" $file
|
|
} else {
|
|
exec /mod/bin/hmt "+setguidance=${newguidance}" $file
|
|
}
|
|
set guidance $newguidance
|
|
}
|
|
|
|
proc {ts genre} {genre} {
|
|
if {![string is integer $genre] || $genre < 0} {
|
|
set genre 0
|
|
}
|
|
if {$genre <= 15} {
|
|
set genre $($genre << 4)
|
|
}
|
|
return $genre
|
|
}
|
|
|
|
ts method setgenre {newgenre} {
|
|
set newgenre [ts genre $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]
|
|
set bmpfile "$bfile$ext.bmp"
|
|
set cmd [list /mod/bin/ffmpeg -loglevel fatal -ss $offset -i $file \
|
|
-frames 1 -pix_fmt argb -vf vflip -s 140x78 -y $bmpfile]
|
|
catch { exec {*}$cmd }
|
|
if {![catch { file stat $bmpfile stbmp }]} {
|
|
if {[dict get $stbmp size] != 0} { return 1 }
|
|
}
|
|
return 0
|
|
}
|
|
|
|
ts method mkthm {{offset 0}} {
|
|
if {![$self mkbmp $offset]} { return 0 }
|
|
set bfile [file rootname $file]
|
|
# Trim the bitmap header from the start of the 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
|
|
$self setflag thumbnail
|
|
return 1
|
|
}
|
|
|
|
# From MontysEvilTwin
|
|
# - https://hummy.tv/forum/threads/7787/page-2#post-106826
|
|
# ffmpeg -i "File 1.ts" -c:a mp3 -b:a 128k "File 1.mp3"
|
|
# ffmpeg -i "File 1.ts" -c:a copy "File 1.mp2"
|
|
# ffmpeg -i "File 1.ts" -c:a copy "File 1.loas"
|
|
ts method mkmp3 {{slow false} {tmp ""} {v 0} {br 128}} {
|
|
set rfile [file rootname $file]
|
|
|
|
if {$slow} {
|
|
set opts [list -c:a mp3 -b:a ${br}k]
|
|
set ext mp3
|
|
} else {
|
|
set opts [list -c:a copy]
|
|
if {$definition eq "HD"} {
|
|
set ext loas
|
|
} else {
|
|
set ext mp2
|
|
}
|
|
}
|
|
set cmd [list /mod/bin/ffmpeg \
|
|
-y -benchmark -vn -v $v \
|
|
-i $file {*}$opts \
|
|
]
|
|
|
|
if {$tmp eq ""} {
|
|
lappend cmd "${rfile}.$ext"
|
|
} else {
|
|
lappend cmd "$tmp.$ext"
|
|
}
|
|
|
|
set output [exec {*}$cmd]
|
|
|
|
if {$tmp ne ""} {
|
|
file rename "$tmp.$ext" "${rfile}.mp3"
|
|
} elseif {$ext ne "mp3"} {
|
|
file rename "${rfile}.$ext" "${rfile}.mp3"
|
|
}
|
|
|
|
exec /mod/bin/id3v2 \
|
|
--song $title \
|
|
--comment $synopsis \
|
|
--album $channel_name \
|
|
--year "[clock format $start -format {%Y}]" \
|
|
"${rfile}.mp3"
|
|
|
|
return $output
|
|
}
|
|
|
|
ts method mkmpg {{tmp ""}} {
|
|
set rfile [file rootname $file]
|
|
|
|
set cmd [list /mod/bin/ffmpeg \
|
|
-y -benchmark -v 0 \
|
|
-i $file \
|
|
-map 0:0 -map 0:1 \
|
|
-vcodec copy -acodec copy]
|
|
|
|
if {$tmp eq ""} {
|
|
lappend cmd "${rfile}.mpg"
|
|
} else {
|
|
lappend cmd "$tmp.mpg"
|
|
}
|
|
|
|
set output [exec {*}$cmd]
|
|
|
|
if {$tmp ne ""} {
|
|
file rename "$tmp.mpg" "${rfile}.mpg"
|
|
}
|
|
|
|
return $output
|
|
}
|
|
|
|
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 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 ""} {nospecial 0}} {{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
|
|
}
|
|
|
|
if {$nospecial && [system specialdir $dir]} return
|
|
|
|
foreach entry [readdir -nocomplain $dir] {
|
|
if {[file isdirectory "$dir/$entry"]} {
|
|
ts iterate $callback $verbose "$dir/$entry" $nospecial
|
|
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 *[-:]* *}
|
|
{^\.+}
|
|
{ *\(Part [0-9] of [0-9]\) *}
|
|
{, Part [0-9]}
|
|
}
|
|
|
|
ts method _tvdb_resolve {seriesid} {
|
|
# See if we can find a TVDB series for this recording.
|
|
|
|
set dir [file dirname $file]
|
|
|
|
set tvdb_series [set v [tvdb series "" $seriesid]]
|
|
if {[$v get seriesid] == 0} { return }
|
|
|
|
# Got one.
|
|
|
|
# Easiest case - we can explicitly request the episode.
|
|
if {$seriesnum && $episodenum} {
|
|
if {$seriescached} {
|
|
set tvdb_method "cached values"
|
|
} else {
|
|
set tvdb_method "series and episode number"
|
|
}
|
|
return [$v episodebynum $seriesnum $episodenum]
|
|
}
|
|
|
|
# Now try to find the episode using the current episode name
|
|
# (using series or episode number if available)
|
|
set k [$v episodebyname $episodename $seriesnum $episodenum]
|
|
if {[llength $k]} {
|
|
set tvdb_method "episode name ($episodename)"
|
|
return $k
|
|
}
|
|
|
|
# More problematic but can at least narrow the list of candidates
|
|
# using the episode or series numbers if we have them.
|
|
|
|
if {$episodenum} {
|
|
set tvdb_method "episode number"
|
|
return [$v episodebyepnum $episodenum $synopsis]
|
|
}
|
|
|
|
if {$seriesnum} {
|
|
set tvdb_method "series and synopsis"
|
|
return [$v episodebyseries $seriesnum $synopsis]
|
|
}
|
|
|
|
# Most difficult - try and match based on synopsis alone
|
|
set tvdb_method "synopsis text"
|
|
return [$v episodebysynopsis $synopsis]
|
|
}
|
|
|
|
proc {ts serieslist} {dir} {
|
|
set idfile "$dir/.tvdbseriesid"
|
|
if {![file exists $idfile]} { return {} }
|
|
return [lmap i [split [file read $idfile] "\n"] {
|
|
string trim $i
|
|
}]
|
|
}
|
|
|
|
ts method extract_numbers {} {
|
|
|
|
######################################################################
|
|
# 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
|
|
|
|
# (Part 5/10)
|
|
# (Pt. 5/10)
|
|
# (Part 5 of 10)
|
|
# (Pt. 5 of 10)
|
|
# (Pt5)
|
|
regexp -nocase -- {P(art|t\.?)\s*(\d+)\s*(of|/)?\s*(\d+)?} $synopsis \
|
|
x x episodenum x episodetot
|
|
|
|
foreach v {seriesnum episodenum episodetot} {
|
|
if {[set $v] eq ""} {
|
|
set $v 0
|
|
} else {
|
|
incr $v 0
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
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
|
|
|
|
if {$episodenum == 0} {
|
|
$self extract_numbers
|
|
set seriescached 0
|
|
}
|
|
|
|
# Now see if TVDB has anything to add
|
|
|
|
set fbase "[file dirname $file]/.tvdb"
|
|
|
|
if {![system has tvdb] || ![file exists "${fbase}seriesid"]} {
|
|
return $s
|
|
}
|
|
|
|
if {!$seriesnum && [file exists "${fbase}series"]} {
|
|
set seriesnum [string trim [file read "${fbase}series"]]
|
|
}
|
|
foreach seriesid [ts serieslist [$self dir]] {
|
|
set tvdb_data [$self _tvdb_resolve $seriesid]
|
|
if {![dict exists $tvdb_data name]} continue
|
|
set flag 0
|
|
if {!$seriesnum} {
|
|
set seriesnum $tvdb_data(series)
|
|
incr flag
|
|
}
|
|
if {!$episodenum} {
|
|
set episodenum $tvdb_data(episode)
|
|
incr flag
|
|
}
|
|
if {$flag} { $self storeepisode }
|
|
|
|
return $tvdb_data(name)
|
|
}
|
|
|
|
return $s
|
|
}
|
|
|
|
ts method epstr {{format "s%se%E/%n"}} {
|
|
set map {}
|
|
if {$seriesnum eq 0} {
|
|
set map(%s) "?"
|
|
set map(%S) "??"
|
|
} else {
|
|
set map(%s) $seriesnum
|
|
set map(%S) [format "%02d" $seriesnum]
|
|
}
|
|
if {$episodenum eq 0} {
|
|
set map(%e) "?"
|
|
set map(%E) "??"
|
|
} else {
|
|
set map(%e) $episodenum
|
|
set map(%E) [format "%02d" $episodenum]
|
|
}
|
|
if {$episodetot eq 0} {
|
|
set map(%n) "?"
|
|
set map(%N) "??"
|
|
} else {
|
|
set map(%n) $episodetot
|
|
set map(%N) [format "%02d" $episodetot]
|
|
}
|
|
return [string map $map $format]
|
|
}
|
|
|
|
ts method tsr {} {
|
|
set fd [open "[file rootname $file].nts"]
|
|
set bytes [read $fd 0x20]
|
|
close $fd
|
|
set tsr [unpack $bytes -uintle $(8 * 0x1f) 8]
|
|
return $tsr
|
|
}
|
|
|
|
ts method genrenib {} {
|
|
if {[catch {set v $($genre >> 4)}]} { set v 0 }
|
|
return $v
|
|
}
|
|
|
|
ts method genre_info {} {
|
|
set g [$self genrenib]
|
|
lassign $::epg::genrelist($g) txt img
|
|
if {$img eq "Unclassified"} {
|
|
set img "/images/173_3_26_G3_$img.png"
|
|
} else {
|
|
set img "/images/173_3_00_G3_$img.png"
|
|
}
|
|
return [list $txt $img]
|
|
}
|
|
|
|
proc {ts genrelist} {} {
|
|
require epg.class
|
|
set glist {}
|
|
foreach {k v} $::epg::genrelist {
|
|
lappend glist $($k << 4) $v
|
|
}
|
|
return $glist
|
|
}
|
|
|
|
# return the key that will decrypt the file in the mode, or nothing
|
|
ts method getkey {mode} {
|
|
# mode: dlna (active key), direct
|
|
|
|
set rfile [file rootname $file]
|
|
|
|
set keys {}
|
|
# the active key
|
|
set key [string range [system nugget cryptokey -key] 0 31]
|
|
if {$key ne ""} {
|
|
lappend keys $key
|
|
}
|
|
if { $mode ne "dlna" } {
|
|
# also try other keys, such as this - same as active?
|
|
set key [system customencryptionkey]
|
|
if {$key ne ""} {
|
|
ladd keys $key
|
|
}
|
|
|
|
# the native key
|
|
if {![catch {set key [system encryptionkey]}]} {
|
|
ladd keys $key
|
|
}
|
|
|
|
# support a file listing other keys in hex, one-per-line
|
|
# eg, for recordings imported from a broken box
|
|
try {
|
|
set fd [open "/mod/etc/keys" r]
|
|
foreach key [split [$fd read -nonewline] "\n"] {
|
|
ladd keys $key
|
|
}
|
|
} on error {} {
|
|
} finally {
|
|
catch {$fd close}
|
|
}
|
|
}
|
|
|
|
foreach key $keys {
|
|
if {[catch {
|
|
set ret [exec /mod/bin/stripts -q/ $key $rfile]
|
|
}]} continue
|
|
if {$ret eq "1"} {
|
|
return $key
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|