# # channelprefs.itcl -- v1.05 -- 10/19/2006 (added channel blacklist function) # -- v1.04 -- 07/12/2005 (ignore problem logging status message, change just to index.itcl) # -- v1.03 -- 07/07/2005 (added support for 6.2 (by skipping unsupported functions), removed caching) # -- v1.02 -- 02/12/2005 (fixed callsign in index.itcl, removed {}s from channel descriptions) # -- v1.01 -- 02/03/2005 (use TWP path for backup, create backups subdir if not exists) # -- v1.00 -- 02/02/2005 (added channel-changing, more error-catching, turned caching back on) # -- v0.985 -- 01/13/2005 (no changes to this module, just to index.itcl) # -- v0.983 -- 01/12/2005 (don't save data for chan>999, grab SignalType from data) # -- v0.981 -- 01/10/2005 (changes: reformatted the satellite info) # -- v0.98 -- 01/06/2005 (changes: started adding source info) # -- v0.97 -- 11/11/2004 (changes: replaced open_file proc with inline open logic) # -- v0.96 -- 11/11/2004 (changes: added missing open_file proc) # -- v0.95 -- 11/10/2004 (changes: added Save and Restore processing, cached chandesc) # -- v0.93 -- 11/08/2004 (changes: don't assume s2-p2 logo exists, use words instead of #s in path, # add SelectAll checkboxes) # # Purpose: display and manipulate current values of Favorite and Record flag for each channel # shows logo and a description for each channel to help decide # user can subset channel list by All/Receive/Favorite # user can request a refresh of the TWP channelindex data (useful to catch TWP up with DTV) # user can save a copy of the channel settings and restore it later # user can click on channel number and (if on LiveTV), the TiVo will change to that channel # # Created by SteveT -- based heavily on other TivoWebPlus 1.1 modules, especially index, ui and backup # # Prerequisite: TWP 1.1, plus index.itcl must be modified to capture $signaltype and append $channel and $signaltype # to channeltablestation and channeltablestation_alt # # To-Do: Change the "All" list to match the TiVo's. Somehow it knows to leave off DTV service, etc. # Determine the reason for the duplicate stationfsid's and remove dup skip (may be related to previous) # Merge the four hard-coded procs into one or two # Speed up updates # Hook Rcv and Fav flags together on-screen. If user turns off Rcv, turn off Fav. If user clicks Fav, turn on Rcv. # Allow user to specify file name and path in backup and restore, and improve error messages related to file probs # proc action_channelprefs {chan path env} { global channeltablestation channeltablenum global channeltablestation_alt channeltablenum_alt global logotablename logotableindex global db global black_nums black_calls black_names # global channelprefs_savechandesc ## used to cache descs # global channelprefs_savesignaltext ## used to cache signaltext set savefilename "$::source_dir/backups/channelprefs_save" ## remove the leading slash if {[string index $path 0] == "/"} { set path [string range $path 1 end] } puts $chan [html_start "Channel Prefs"] ## debugging only #puts $chan [html_link "/logs/tivoweb.log/" "Show tivoweb.log"] #puts $chan [html_link "/restart/1" "Reload TivoWeb, path=$path"] ## always build a little header table for the channelprefs menu puts $chan [html_table_start "" [html_link "http://geocities.com/mindrover_st/ChannelPrefs.html" "Channel Prefs v1.05" \ "title=\"ChannelPrefs home page\"" "target=_new"] "COLSPAN=7"] puts -nonewline $chan [td [html_link "/channelprefs/all" "All" "title=\"Show all known channels in list\""]] puts -nonewline $chan [td [html_link "/channelprefs/rcv" "Receive" "title=\"Show only "Channels You Receive"\""]] if { $::lang == "en" } { puts -nonewline $chan [td [html_link "/channelprefs/fav" "Favourite" "title=\"Show only "Favourite Channels"\""]] } else { puts -nonewline $chan [td [html_link "/channelprefs/fav" "Favorite" "title=\"Show only "Favorite Channels"\""]] } set hovertext "Save current TiVo settings to file. Note that this does not save changes made to the web page" set hovertext "$hovertext that have not been Updated to the TiVo." puts -nonewline $chan [td [html_link "/channelprefs/backup" "Backup" "title=\"$hovertext\" "]] if { [file exists $savefilename] || $path == "backup" } { set hovertext "Restore flags from previous backup. Note that this only loads this web page with the old values," set hovertext "$hovertext you must press Update to apply the changes to the TiVo." puts -nonewline $chan [td [html_link "/channelprefs/restore" "Restore" "title=\"$hovertext\" "]] } else { puts -nonewline $chan [td "Restore" ] } set hovertext "Rebuild TWP's channel cache. This should only be needed if channels have been added or removed," set hovertext "$hovertext or if you've customized channels since TWP was last started" set hovertext "$hovertext (via the TiVo UI)." puts -nonewline $chan [td [html_link "/channelprefs/reindex" "ReIndex" "title=\"$hovertext\" "]] set hovertext "Remove blacklisted channels." puts -nonewline $chan [td [html_link "/channelprefs/blacklist" "Blacklist" "title=\"$hovertext\" "]] puts -nonewline $chan [html_table_end] ##--- if submitted by update button, process changed values ------------------------------------- if { $path == "update" } { ## env has all the variables from the form eval $env set AnyChanged "N" ## wlist will have all the original rcv flags set wlist [lsort [info vars "sv_rcv_*"]] foreach rcv_var $wlist { ## get value of each saved variable set sv_rcv [ expr \$$rcv_var ] ## split each varname, 3rd part is stationfsid set vals [split $rcv_var "_"] set stationfsid [lindex $vals 2] ## build cb rcv variable name and check for existence (it will only exist if it was ON when submitted) if { [ info exists cb_rcv_$stationfsid ] } { set cb_rcv "on" } else { set cb_rcv "" } ## build cb fav variable name and check for existence (it will only exist if it was ON when submitted) if { [ info exists cb_fav_$stationfsid ] } { set cb_fav "on" } else { set cb_fav "" } ## if fav is on then make sure rcv is on, and ## if rcv is off then make sure fav is off. if {$cb_rcv == "" && $cb_fav == "on"} { if {$sv_rcv == "on"} { set cb_fav "" } else { set cb_rcv "on" } } ## if new and saved rcv values differ, process as needed if { $cb_rcv == "on" && $sv_rcv == "" } { AddToRcv $chan $stationfsid set AnyChanged "Y" } elseif { $cb_rcv == "" && $sv_rcv == "on" } { RmvFromRcv $chan $stationfsid set AnyChanged "Y" } ## get value of saved favorite flag set fav_var "sv_fav_$stationfsid" set sv_fav [ expr \$$fav_var ] ## if new and saved favorite values differ, process as needed if { $cb_fav == "on" && $sv_fav == "" } { AddToFavorites $chan $stationfsid set AnyChanged "Y" } elseif { $cb_fav == "" && $sv_fav == "on" } { RmvFromFavorites $chan $stationfsid set AnyChanged "Y" } } if { $AnyChanged == "Y" } { if {$::version < 6} { event send $TmkEvent::EVT_DATA_CHANGED $TmkDataChanged::CHANNEL_LIST 0 } puts $chan "
Changes Processed
" } else { puts $chan "
No Changes Requested
" } ##--- call init-channelindex if ReIndex clicked ----------------------------------------------- } elseif { $path == "reindex" } { puts $chan "

Rebuilding TivoWebPlus's Channel Cache from MFS, please wait......

" init_channelindex puts $chan "COMPLETE

" ##--- call proc to save flags to file if Save clicked ----------------------------------------- } elseif { $path == "backup" } { SaveFlagsToFile $chan $savefilename ##--- clicked ----------------------------------------- } elseif { $path == "blacklist" } { set channelnumlist [array names channeltablenum] ## now loop through the channels foreach channum [lsort -real $channelnumlist] { if { $channum > 999 } { continue } ## find each channel's data in either the two received lists or the not-rcved lists (_alt) if { [catch {set stationfsid $channeltablenum($channum)}] != 1 } { #set rcv 1 catch {set data $channeltablestation($stationfsid) } } else { #set rcv 0 set stationfsid $channeltablenum_alt($channum) catch {set data $channeltablestation_alt($stationfsid) } } if {[info exists data]} { set channel [lindex $data 5] ## if channel already written once, skip this duplicate if { [info exists dupcheck($channel)] } { continue } else { set dupcheck($channel) "1" } set favorite [lindex $data 1] set channum [join [split $channum .] -] set callsign [lindex $data 2] set channame [lindex $data 3] # set signal_text to SignalType (more stuff added later if available) #set signal_text [lindex $data 6] if { [info exists black_nums] && [llength $black_nums] > 0 } { foreach black_num $black_nums { if { $channum == $black_num } { puts $chan "Found BlackNum
" puts $chan "stationfsid : $stationfsid
" puts $chan "callsign : $callsign
" puts $chan "channum : $channum
" puts $chan "channame : $channame
" RmvFromRcv $chan $stationfsid puts $chan "
" } } } if { [info exists black_calls] && [llength $black_calls] > 0 } { foreach black_call $black_calls { if { $callsign == $black_call } { puts $chan "Found BlackCall
" puts $chan "stationfsid : $stationfsid
" puts $chan "callsign : $callsign
" puts $chan "channum : $channum
" puts $chan "channame : $channame
" RmvFromRcv $chan $stationfsid puts $chan "
" } } } if { [info exists black_names] && [llength $black_names] > 0 } { foreach black_name $black_names { if { [regexp -nocase "^$black_name$" [strim $channame]] } { puts $chan "Found BlackName
" puts $chan "stationfsid : $stationfsid
" puts $chan "callsign : $callsign
" puts $chan "channum : $channum
" puts $chan "channame : $channame
" RmvFromRcv $chan $stationfsid puts $chan "
" } } } } } ##--- process all, fav, rcv and restore ------------------------------------------------------- ##--- stop processing if page called directly with no path (show menu only) ----------------- } elseif { $path != "" } { ## add checkall client-side function to page puts $chan " " ## put everything in a form, so submit button will collect checkboxes puts $chan [html_form_start "POST" "/channelprefs/update" "name=\"form\""] puts $chan [html_table_start "width=96%" "" ""] set th_rcv "Rcv" set th_fav "Fav" set temp_row [th $th_rcv][th $th_fav][th "Logo"][th "Number"][th "Callsign"][th "Name"] set temp_row $temp_row[th "Description"][th "Signal"] puts $chan [tr "ALIGN=CENTER" $temp_row ] ## include _alt array if showing all or restore options if { $path == "all" || $path == "restore"} { set channelnumlist "[array names channeltablenum] [array names channeltablenum_alt]" } else { set channelnumlist [array names channeltablenum] } ## if requested, execute the saved file to populate the savefile_rcv and savefile_fav arrays if { $path == "restore" } { source $savefilename } ## now loop through the channels foreach channum [lsort -real $channelnumlist] { if { $channum > 999 } { continue } ## find each channel's data in either the two received lists or the not-rcved lists (_alt) if { [catch {set stationfsid $channeltablenum($channum)}] != 1 } { set rcv 1 catch {set data $channeltablestation($stationfsid) } } else { set rcv 0 set stationfsid $channeltablenum_alt($channum) catch {set data $channeltablestation_alt($stationfsid) } } if {[info exists data]} { set channel [lindex $data 5] ## if channel already written once, skip this duplicate if { [info exists dupcheck($channel)] } { continue } else { set dupcheck($channel) "1" } set favorite [lindex $data 1] ## skip not-fav if fav-only requested if { $path == "fav" && $favorite == 0 } { continue } ## set values for checkboxes and hidden values if {$rcv > 0} { set sv_rcv "on" } else { set sv_rcv "" } if {$favorite > 0} { set sv_fav "on" } else { set sv_fav "" } ## set checkboxes to restored values if specified if { $path == "restore"} { if {[info exists savefile_rcv($channum)]} { set cb_rcv $savefile_rcv($channum) } else { set cb_rcv "" } if {[info exists savefile_fav($channum)]} { set cb_fav $savefile_fav($channum) } else { set cb_fav "" } } else { set cb_rcv $sv_rcv set cb_fav $sv_fav } ## set html for checkboxes and hidden values set td_rcv [td [html_form_checkbox "cb_rcv_$stationfsid" $cb_rcv][html_form_hidden "sv_rcv_$stationfsid" $sv_rcv]] set td_fav [td [html_form_checkbox "cb_fav_$stationfsid" $cb_fav][html_form_hidden "sv_fav_$stationfsid" $sv_fav]] ## format and write channel row out to html set channum [join [split $channum .] -] set callsign [lindex $data 2] set td_callsign [td [html_link "/channel/$stationfsid" $callsign "title=\"See channel details for $channum\""]] set channame [lindex $data 3] set td_channame [td [html_link "/object/$channel" $channame "title=\"See MFS details for channel $channum\""]] set logoindex [lindex $data 4] if {$::version < 6} { set td_channum [td [html_link "/channelprefs_change/$channum" $channum "title=\"Change LiveTV to channel $channum\"" "target=_new"]] } else { set td_channum [td $channum] } ## try now-showing logo 1st, then channel logo 2nd, then none set logoname [lindex $logotablename(2) [lsearch $logotableindex(2) $logoindex]] if { $logoname != "" } { set logostr [img "alt=\"\"" "$logoname-s2-p2.png"] } else { set logoname [lindex $logotablename(1) [lsearch $logotableindex(1) $logoindex]] if { $logoname != "" } { set logostr [img "alt=\"\"" "$logoname-s1-p1.png"] } else { set logostr "" } } # set signal_text to SignalType (more stuff added later if available) set signal_text [lindex $data 6] ## get long description and signaltext from apg data set chandesc "" set apgchannel "" regexp {([0-9]*)/(.*)} $channel junk channelid channelsubid RetryTransaction { catch { set channelobj [db $db openidconstruction $channelid $channelsubid] } catch { set apgchannel [dbobj $channelobj get ApgChannel] } if { $apgchannel != "" } { set chandesc [strim [dbobj $apgchannel get AboutText]] set chandef [dbobj $apgchannel get ChannelDefinition] set frameheader [dbobj $apgchannel get "FrameHeaderNetworkId"] # set descriptions for known satellites if {$frameheader == 0 } { set sat_text "A(101)" } elseif {$frameheader == 2} { set sat_text "C(110)" } elseif {$frameheader == 3} { set sat_text "B(119)" } else { set sat_text $frameheader } set transponder [dbobj $chandef get "FrequencyIndex"] set transponder [expr $transponder + 1] # append sat and transponder info to signal_text set signal_text $signal_text-$sat_text-$transponder } } set signal_html " [td nowrap $signal_text] " set chandesc "$chandesc" ## actually write the html row out to the web browser puts $chan [tr "" $td_rcv $td_fav [td $logostr] $td_channum $td_callsign $td_channame [td $chandesc] $signal_html ] } } puts $chan [html_table_end] puts $chan [html_form_input "submit" "update" "Update Changes"] } puts $chan [html_end] } ######################################################################## ## this proc creates a file of tcl commands to set up rcv and fav flags ## for any that are turned on. If off, variable won't exist. This ## file will be "executed" (sourced) during the restore process. proc SaveFlagsToFile {chan fname} { global channeltablestation channeltablenum puts $chan "

Saving current Receive and Favorite flag settings to \"$fname\", please wait......

" # create directory if it doesn't exist set fname_path [file dirname $fname] if {![file isdirectory $fname_path]} { catch {file mkdir $fname_path} } # backup the previous backup if {[file exists $fname]} { catch [file copy -force $fname "$fname.old"] } # open file writable and start writing out tcl code set fd 0 if !{[catch {set fd [open $fname "w"]}]} { puts $fd "# Save file created by ChannelPrefs TWP module." set todaystr [clock format [clock seconds] -format "%a %b %d %Y %H:%M:%S"] puts $fd "# Created at $todaystr" ## get array of Rcv'd channels set channelnumlist [array names channeltablenum] ## loop through all of them and write statements to save file foreach channum [lsort -real $channelnumlist] { if { $channum > 999 } { continue } puts $fd " set savefile_rcv($channum) \"on\" " ## write out statement for fav if on set stationfsid $channeltablenum($channum) catch { set data $channeltablestation($stationfsid) } if {[info exists data]} { set favorite [lindex $data 1] if {$favorite > 0} { puts $fd " set savefile_fav($channum) \"on\" " } } } puts $fd "################### End of data ########################" close $fd puts $chan "SUCCESS!

" } else { puts $chan "ERROR - Could not open file \"$fname\" for writing

" } } ################################################################################# # ADD CHANNEL TO FAVORITES # remember that the Favorite attribute is only present when it is 1, or "In Favorites" proc AddToFavorites {chan stationfsid} { global channeltablestation global channeltablestation_alt global channeltablenum global channeltablenum_alt global db puts $chan "ADDING " # get data from either table, and remember which one set rcv "1" if { [catch {set data $channeltablestation($stationfsid)}] == 1 } { set data $channeltablestation_alt($stationfsid) set rcv "0" } set msg "" if {[info exists data]} { set num [lindex $data 0] puts -nonewline $chan "Channel $num to \"Favorite Channels\" --" set channel [lindex $data 5] regexp {([0-9]*)/(.*)} $channel junk channelid channelsubid set channelobj "" ## make sure value doesn't exist before adding it RetryTransaction { catch { set channelobj [db $db openidconstruction $channelid $channelsubid] } catch { set favorite [dbobj $channelobj get Favorite] } } if { $channelobj != "" } { if { $favorite == "" } { ## execute change by removing the Favorite value from mfs RetryTransaction { set channelobj [db $db openidconstruction $channelid $channelsubid] dbobj $channelobj add Favorite "1" } } else { set msg " Already Set " } if { $msg == "" } { ## check to make sure it changed RetryTransaction { set channelobj [db $db openidconstruction $channelid $channelsubid] set favorite [dbobj $channelobj get Favorite] } if { $favorite == "1" } { ## if it did change, replace the Favorite flag in the appropriate data array to reflect change if { $rcv == "1" } { set channeltablestation($stationfsid) [lreplace $data 1 1 "1"] } else { set channeltablestation_alt($stationfsid) [lreplace $data 1 1 "1"] } set msg " SUCCESS! " } else { set msg " NOT CHANGED " } } } else { set msg " NOT CHANGED, problem rtving channelobj from MFS " } } else { set msg " NOT CHANGED, problem rtving data from channeltablestation($stationfsid) " } puts -nonewline $chan "$msg
" } ################################################################################# # REMOVE CHANNEL FROM FAVORITES # remember that the Favorite attribute is only present when it is 1, or "In Favorites" proc RmvFromFavorites {chan stationfsid} { global channeltablestation global channeltablestation_alt global channeltablenum global channeltablenum_alt global db puts $chan "REMOVING " # get data from either table, and remember which one set rcv "1" if { [catch {set data $channeltablestation($stationfsid)}] == 1 } { set data $channeltablestation_alt($stationfsid) set rcv "0" } set msg "" if {[info exists data]} { set num [lindex $data 0] puts -nonewline $chan "Channel $num from \"Favorite Channels\" --" set channel [lindex $data 5] regexp {([0-9]*)/(.*)} $channel junk channelid channelsubid set channelobj "" ## make sure value exists before removing it RetryTransaction { catch { set channelobj [db $db openidconstruction $channelid $channelsubid] } catch { set favorite [dbobj $channelobj get Favorite] } } if { $channelobj != "" } { if { $favorite == "1" } { ## execute change by removing the Favorite value from mfs RetryTransaction { set channelobj [db $db openidconstruction $channelid $channelsubid] dbobj $channelobj remove Favorite } } else { set msg " Already Set " } if { $msg == "" } { ## check to make sure it changed RetryTransaction { set channelobj [db $db openidconstruction $channelid $channelsubid] set favorite [dbobj $channelobj get Favorite] } if { $favorite == "" } { ## if it did change, replace the Favorite flag in the appropriate data array to reflect change if { $rcv == "1" } { set channeltablestation($stationfsid) [lreplace $data 1 1 "0"] } else { set channeltablestation_alt($stationfsid) [lreplace $data 1 1 "0"] } set msg " SUCCESS! " } else { set msg " NOT CHANGED " } } } else { set msg " NOT CHANGED, problem rtving channelobj from MFS " } } else { set msg " NOT CHANGED, problem rtving data from channeltablestation($stationfsid) " } puts -nonewline $chan "$msg
" } ################################################################################# # ADD CHANNEL TO RECEIVE LIST # remember that the Record attribute is only present when it is 0, or "don't rcv" proc AddToRcv {chan stationfsid} { global channeltablestation global channeltablestation_alt global channeltablenum global channeltablenum_alt global db puts $chan "ADDING " # get data from either table if { [catch {set data $channeltablestation($stationfsid)}] == 1 } { set data $channeltablestation_alt($stationfsid) } set msg "" if {[info exists data]} { set num [lindex $data 0] puts -nonewline $chan "Channel $num to \"Channels You Receive\" --" set channel [lindex $data 5] regexp {([0-9]*)/(.*)} $channel junk channelid channelsubid set channelobj "" ## make sure value doesn't exist before adding it RetryTransaction { catch { set channelobj [db $db openidconstruction $channelid $channelsubid] } catch { set record [dbobj $channelobj get Record] } } if { $channelobj != "" } { if { $record == "0" } { ## execute change by removing the Record=0 and Surf=0 values from mfs RetryTransaction { set channelobj [db $db openidconstruction $channelid $channelsubid] dbobj $channelobj remove Record dbobj $channelobj remove Surf } } else { set msg " Already Set " } if { $msg == "" } { ## check to make sure it changed RetryTransaction { set channelobj [db $db openidconstruction $channelid $channelsubid] set record [dbobj $channelobj get Record] } if { $record == "" } { ## if it did change, adjust the four global arrays to reflect change unset channeltablenum_alt($num) set channeltablenum($num) $stationfsid unset channeltablestation_alt($stationfsid) set channeltablestation($stationfsid) $data set msg " SUCCESS! " } else { set msg " NOT CHANGED " } } } else { set msg " NOT CHANGED, problem rtving channelobj from MFS " } } else { set msg " NOT CHANGED, problem rtving data from channeltablestation($stationfsid) " } puts -nonewline $chan "$msg
" } ################################################################################# # REMOVE CHANNEL FROM RECEIVE LIST # remember that the Record attribute is only present when it is 0, or "don't rcv" proc RmvFromRcv {chan stationfsid} { global channeltablestation global channeltablestation_alt global channeltablenum global channeltablenum_alt global db puts $chan "REMOVING " # get data from either table if { [catch {set data $channeltablestation($stationfsid)}] == 1 } { set data $channeltablestation_alt($stationfsid) } set msg "" if {[info exists data]} { set num [lindex $data 0] puts -nonewline $chan "Channel $num from \"Channels You Receive\" --" set channel [lindex $data 5] regexp {([0-9]*)/(.*)} $channel junk channelid channelsubid set channelobj "" ## make sure value doesn't exist before adding it RetryTransaction { catch { set channelobj [db $db openidconstruction $channelid $channelsubid] } catch { set record [dbobj $channelobj get Record] } } if { $channelobj != "" } { if { $record == "" } { ## execute change by adding the Record=0 and Surf=0 values to mfs RetryTransaction { set channelobj [db $db openidconstruction $channelid $channelsubid] dbobj $channelobj add Record "0" dbobj $channelobj add Surf "0" } } else { set msg " Already Set " } if { $msg == "" } { ## check to make sure it changed RetryTransaction { set channelobj [db $db openidconstruction $channelid $channelsubid] set record [dbobj $channelobj get Record] } if { $record == "0" } { ## if it did change, adjust the four global arrays to reflect change unset channeltablenum($num) set channeltablenum_alt($num) $stationfsid unset channeltablestation($stationfsid) set channeltablestation_alt($stationfsid) $data set msg " SUCCESS! " } else { set msg " NOT CHANGED " } } } else { set msg " NOT CHANGED, problem rtving channelobj from MFS " } } else { set msg " NOT CHANGED, problem rtving data from channeltablestation($stationfsid) " } puts -nonewline $chan "$msg
" } ######################################################################### ## process link for changing channel on livetv ## proc action_channelprefs_change {chan path env} { ## only do this for version with supported SendKey if {$::version < 6} { ## remove the leading slash if {[string index $path 0] == "/"} { set path [string range $path 1 end] } # send each digit of number as keystroke, followed by the enter key foreach s [ split $path {} ] { if {$s == "-" } { set s "delimiter" } SendKey $s } SendKey enter # close browser window when work is done puts $chan "" } } ######################################################################## register_module "channelprefs" "Channel Prefs" "Set Channel Preferences"