source /mod/webif/lib/setup
if {![exists -proc class]} { package require oo }
if {![exists -proc sqlite3.open]} { package require sqlite3 }
require settings.class system.class
set rsvdb [sqlite3.open /var/lib/humaxtv/rsv.db]
$rsvdb query {attach database '/var/lib/humaxtv/channel.db' as channel}
if {![file exists /var/lib/humaxtv/rsvp.db]} {
file copy /var/lib/humaxtv/rsv.db /var/lib/humaxtv/rsvp.db
set tdb [sqlite3.open /var/lib/humaxtv/rsvp.db]
$tdb query {drop table TBL_VERSION}
$tdb query {alter table TBL_RESERVATION rename to pending}
$tdb query {alter table pending add column action int}
$tdb query {delete from pending}
$tdb close
}
$rsvdb query {attach database '/var/lib/humaxtv/rsvp.db' as pending}
# This is required to upgrade old tables and will be removed in a future
# version.
catch { $rsvdb query {alter table pending add column action int} }
class rsv {
ulslot -1
ersvtype 0
hsvc 0
nsttime 0
szsttime "00000000000000"
nduration 0
erepeat 0
usevtid 0
szevtname {}
ulPreOffset 0
ulPostOffset 0
ulProgramId 0
ulSeriesId 0
ucVolume 0
ucInputMode 0
usChNum 0
ucRecKind 0
ucCRIDType 0
szCRID {}
szFPBRecPath {}
szRecordedProgCrid {}
szEventToRecord {}
aulEventToRecordInfo {}
bRecomRsv 0
usLastRecordedEvtId 0
eReady 0
szSvcName {}
usLcn 0
sort 0
action 0
}
rsv method aul {} {
if {![exists -proc binary]} { package require binary }
set aul {}
for {set i 0} {$i < [string length $aulEventToRecordInfo]} {incr i 16} {
binary scan [string range $aulEventToRecordInfo $i $($i + 15)] \
iiii service start end event_id
lappend aul [list $service $start $end $event_id]
}
return $aul
}
rsv method clear_ulslot {} {
set ulslot -1
}
rsv method isseries {} {
if {$ucRecKind == 4} { return 1 } else { return 0 }
}
rsv method _strip {str} {
if {[string range $str 1 2] eq "i7"} {
set str [string range $str 3 end]
}
if {[string first "\025" $str] == 0} {
set str [string range $str 1 end]
}
return $str
}
rsv method folder {} {
return [$self _strip $szFPBRecPath]
}
rsv method name {} {
set name [$self _strip $szevtname]
if {$name == ""} {
switch $ersvtype {
1 { set name "--- Unnamed reminder ---" }
2 { set name "--- Unnamed reminder ---" }
3 { set name "--- Unnamed recording ---" }
5 { set name "--- Wake-up ---" }
6 { set name "--- Sleep ---" }
7 { set name "--- Auto Update ---" }
11 { set name "--- DSO Event ---" }
default { set name "--- Unknown event type $ersvtype ---" }
}
}
return $name
}
rsv method padded {} {
if {$ulPreOffset > 0 || $ulPostOffset > 0} {
return 1
} else {
return 0
}
}
rsv method channel_name {} {
return [string range $szSvcName 1 end]
}
rsv method icon {} {
set rsvicon ""
switch $ersvtype {
1 { set rsvicon "175_1_00_Reservation_Watch.png" }
2 { set rsvicon "175_1_00_Reservation_Watch.png" }
3 { set rsvicon "175_1_11_Reservation_Record.png" }
5 { set rsvicon "745_1_10_Video_2Live.png" }
6 { set rsvicon "745_1_11_Video_1REC.png" }
7 { set rsvicon "345_6_08_ST_Ad_Hoc.png" }
}
return $rsvicon
}
rsv method RKIcon {} {
switch $ucRecKind {
2 { set RKIcon "178_1_26_Icon_Split.png" }
4 { set RKIcon "175_1_11_Series_Record.png" }
default {
switch $erepeat {
1 {set RKIcon "521_1_00_RP_Daily_C.png"}
2 {set RKIcon "521_1_00_RP_Weekly_C.png"}
3 {set RKIcon "521_1_00_RP_Weekdays_C.png"}
4 {set RKIcon "521_1_00_RP_Weekend_C.png"}
default {set RKIcon ""}
}
}
}
return $RKIcon
}
rsv method pendingicon {{width 30}} {
switch $action {
0 { set icon "add" }
1 { set icon "close" }
2 { set icon "ar" }
3 { set icon "pad" }
4 { set icon "folder" }
}
return ""
}
rsv method iconset {{height 20}} {
set iconlist {}
set icon [$self icon]
if {$icon ne ""} {
lappend iconlist ""
if {$ersvtype == 3} {
if {[$self padded]} {
set padding "<- [expr $ulPreOffset / 60], [expr $ulPostOffset / 60] ->"
lappend iconlist \
""
} else {
lappend iconlist \
""
}
}
}
set icon [$self RKIcon]
if {$icon ne ""} {
lappend iconlist ""
}
return $iconlist
}
rsv method set_delete {} {
set action 1
}
rsv method set_unpad {} {
set action 2
}
rsv method set_folder {name} {
set action 4
set szFPBRecPath $name
}
rsv method set_pad {{pre 60} {post 60}} {
set action 3
set ulPreOffset $pre
set ulPostOffset $post
}
rsv method remove_pending {} {
$::rsvdb query "delete from pending where ulslot = $ulslot"
}
rsv method fix_hsvc {} {
global rsvdb
set _hsvc [$rsvdb query {
select hSvc
from channel.TBL_SVC
where szSvcName = '%s'
or szSvcname = '\025%s'
limit 1
} $szSvcName $szSvcName]
if {[llength $_hsvc] == 1} {
set hsvc [lindex [lindex $_hsvc 0] 1]
} else {
set hsvc 0
}
return $hsvc
}
rsv method insert {{table pending} {force 0}} {
global rsvdb
# Duplicate check - all tables
if {!$force && $szCRID ne "" && $action == 0} {
foreach tab {pending TBL_RESERVATION} {
set rec [$rsvdb query "
select ulslot from $tab
where szCRID = '%s'
" $szCRID]
if {[llength $rec] > 0} {
throw 20 "Duplicate reservation."
return
}
}
}
# Find a spare slot.
if {$ulslot < 0} {
set slotlist [$rsvdb query "
select ulslot FROM $table
order by ulslot;
"]
if {[llength $slotlist] > 0} {
set slots [lmap i $slotlist {lindex $i 1}]
set max [lindex $i end]
for {set i 0} {$i < $max} {incr i} {
if {$i ni $slots} {
set ulslot $i
break
}
}
if {$ulslot < 0} { set ulslot $($max + 1) }
}
if {$ulslot < 0} { set ulslot 0 }
}
set fields [lsort [$self vars]]
foreach field {aulEventToRecordInfo szSvcName usLcn sort} {
set df [lsearch $fields $field]
set fields [lreplace $fields $df $df]
}
if {$table ne "pending"} {
set df [lsearch $fields "action"]
set fields [lreplace $fields $df $df]
}
set vals {}
foreach field $fields {
# Escape any quotes embedded in the data.
regsub -all {'} [$self get $field] {''} f
lappend vals "'$f'"
#lappend vals "'[$self get $field]'"
}
set query "insert into ${table}("
append query [join $fields ","]
append query ") values("
append query [join $vals ","]
append query ");"
$rsvdb query $query
}
proc {rsv list} {{table tbl_reservation}} {
set res [$::rsvdb query "
select $table.*,
channel.TBL_SVC.szSvcName, channel.TBL_SVC.usLcn,
case when ersvtype > 3 then 1 else 0 end as sort1,
case when nsttime + nduration < [clock seconds]
then 0 else 1 end as sort2
from $table
left join channel.TBL_SVC
on $table.hSvc = channel.TBL_SVC.hSvc
order by sort1, sort2 desc, nsttime
"]
set records {}
foreach rec $res {
lappend records [rsv new $rec]
}
return $records
}
proc {rsv lookuptab} {} {
set records {}
foreach tab {tbl_reservation pending} {
set res [$::rsvdb query "
select $tab.szCRID, channel.TBL_SVC.hSvc
from $tab left join channel.TBL_SVC
on $tab.hSvc = channel.TBL_SVC.hSvc
where ersvtype <= 3
"]
foreach rec $res {
lappend records "$rec(hSvc)/[file tail $rec(szCRID)]"
}
}
return $records
}
proc {rsv entry} {{table TBL_RESERVATION} crid svc} {
set res [$::rsvdb query "
select $table.*,
channel.TBL_SVC.szSvcName, channel.TBL_SVC.usLcn
from $table
left join channel.TBL_SVC
on $table.hSvc = channel.TBL_SVC.hSvc
where szCRID like '%%%s' and $table.hsvc = '%s'
" $crid $svc]
if {[llength $res] > 0} {
return [rsv new [lindex $res 0]]
}
return 0
}
proc {rsv fetch} {{table TBL_RESERVATION} ersvtype hsvc nsttime usevtid events} {
set res [$::rsvdb query "
select $table.*,
channel.TBL_SVC.szSvcName, channel.TBL_SVC.usLcn
from $table
left join channel.TBL_SVC
on $table.hSvc = channel.TBL_SVC.hSvc
where $table.ersvtype = '%s'
and $table.hsvc = '%s'
and $table.nsttime = '%s'
and $table.usevtid = '%s'
and $table.szEventToRecord = '%s'
" $ersvtype $hsvc $nsttime $usevtid $events]
if {[llength $res] > 0} {
return [rsv new [lindex $res 0]]
}
return 0
}
proc {rsv slot} {{table TBL_RESERVATION} slot} {
set res [$::rsvdb query "
select $table.*,
channel.TBL_SVC.szSvcName, channel.TBL_SVC.usLcn
from $table
left join channel.TBL_SVC
on $table.hSvc = channel.TBL_SVC.hSvc
where ulslot = %s" $slot]
if {[llength $res] > 0} {
return [rsv new [lindex $res 0]]
}
return 0
}
proc {rsv cleanup} {} {
catch {$::rsvdb close}
}
proc {rsv commit} {} {
$::rsvdb query {begin transaction}
foreach rec [rsv list pending] {
if {[$rec get action] == 0} {
$rec clear_ulslot
$rec insert TBL_RESERVATION 1
}
}
$::rsvdb query {delete from pending}
$::rsvdb query {commit transaction}
}
proc {rsv construct} {event type} {
global ccrid
$event get_channel_info
set args {}
set args(ersvtype) 3
set args(hsvc) [$event get channel_hsvc]
set args(nsttime) [$event get start]
set args(nduration) [$event get duration]
set args(usevtid) [$event get event_id]
set args(szevtname) "\025[$event get name]"
set args(eReady) 30
lassign [system padding] args(ulPreOffset) args(ulPostOffset)
set ccrid [$event get channel_crid]
# Fallback from series to event if there is no series CRID.
if {$type == 2 && [$event get series_crid] eq ""} {
set type 1
}
if {$type == 1} {
# Event
set args(ucCRIDType) 49
set args(ucRecKind) 1
set ecrid [$event get event_crid]
if {$ecrid ne ""} {
set args(szCRID) "$ccrid$ecrid"
set args(szEventToRecord) "1$args(szCRID)|"
# Handle split events
if {[string match {*#?} $args(szCRID)]} {
set args(ucRecKind) 2
set args(szCRID) [
string range $args(szCRID) 0 end-2]
# TODO - check to see how many parts there
# are...
append args(szEventToRecord) \
$args(szEventToRecord)
}
}
} elseif {$type == 3} {
# Reminder
set args(ersvtype) 2
set args(szsttime) [clock format $args(nsttime) \
-format {%Y%m%d%H%M%S}]
} else {
# Series
set args(ucCRIDType) 50
set args(ucRecKind) 4
set args(szCRID) "$ccrid[$event get series_crid]"
set args(szFPBRecPath) "$args(szevtname)"
set progs [lmap i [epg fetch dump -scrid [$event get series_crid]] {
if {[set ecrid [$i get event_crid]] eq ""} { continue }
list "1$::ccrid$ecrid"
}]
set args(szEventToRecord) "[join $progs "|"]|"
}
return [rsv new $args]
}