Woohoo: streams back INTO the TiVo

Warren Toomey wkt at t...
Sun, 30 Jun 2002 15:00:53 +1000 (EST)


Hi all,
I wish I could take credit for this but all I've done is added
the ele2pestriple stuff into an existing script.

The script allows you to take a vsplit TyStream (i.e separate audio and video
files) on the Unix side, and insert it back into the MFS of the TiVo and
make it Now Showing.

Drawbacks: at present, only one tystream is re-inserted. If there is a
Tcl-savvy person out there, here's my wishlist:

- a script to export details of an existing Now Showing program
out to an ASCII Unix file.

- this script modified to re-import the above ASCII Unix file
so the Now Showing actually gives real details of the recording.

- this script modified to allow an arbitrary # of TyStreams,
which would become Parts in the new recording.

Anyway, it's a start.

Cheers all,
Warren

[ file is called file-to-recording.tcl ]

#!/tvbin/tivosh
#
# This script takes the elementary audio and video components of a TyStream
# (such as created by vsplit) in the Unix filesystem, copies these two files
# into the MFS and makes a TyStream. It then makes a NowShowing program
# entry so that you can watch it!
#
# Someone (who?) wrote most of this. Warren just added the bit to
# copy the Unix files into the MFS.
#
source $tcl_library/tv/mfslib.tcl

#
# Usage
# 
proc Usage {} {
puts {Usage: file-to-recording filename MFSname title time duration}
puts { Filename is the Unix filename without .mpv or .mpa}
puts { MFSname is the MFS filename with no slashes}
puts { title is a single word, or a phrase in double quotes}
puts { time is the start time: seconds since midnight tonight, e.g 0}
puts { duration is in seconds, e.g 3600}
exit
}

proc RecordMovie {unixPath mfsPath} {
global env
set TIVO_ROOT $env(TIVO_ROOT)
if {[RetryTransaction {catch {mfs find $mfsPath}}]} {
puts "Recording $unixPath to $mfsPath ..."
exec $TIVO_ROOT/tvbin/ele2pestriple $unixPath.mpv $unixPath.mpa $mfsPath
} else {
puts "MFS movie $mfsPath already exists."
exit
}
}

#
# I do not use the regular RetryTransaction because I do not like the fact
# it adds a puts in the middle if a transaction fails
proc MyRetryTransaction { body } {
global errorInfo errorCode

while { 1 } {
set code [catch {transaction {uplevel $body}} string]
if { $code == 0 } {
return $string
} elseif { $code == 1 } {
if { $errorCode == "errTmActiveLockConflict" ||
$errorCode == "errTmBackgroundHoldoff" ||
$errorCode == "errFsLockConflict" } {
after 100
# retry the transaction
continue
}
return -code error -errorinfo $errorInfo -errorcode $errorCode $string
} elseif { $code == 2 } {
return -code return $string
} elseif { $code == 3 } {
return -code break $string
} elseif { $code == 4 } {
return -code continue $string
}
}
}



#
# Main Part
#

if {$argc != 5} { Usage }

set today [expr [clock seconds] / 86400]
set now [expr [clock seconds] % 86400]
set date $today ;# days since 1970

set filename [lindex $argv 0]
set path [lindex $argv 1]
set title [lindex $argv 2]
set startTime [lindex $argv 3]
set duration [lindex $argv 4]


#
# Copy the file over to an MFS tystream
#
RecordMovie $filename /Recording/TmsId/$path

# Get a handle to the database
set db [dbopen]

# Create a recording object (with a bogus showing) that
# holds the stream file, and unlink it from its old location.
# (If it's not unlinked, MyWorld will be unable to delete it.)

MyRetryTransaction {

# figure out the fsid
set info [mfs find /Recording/TmsId/$path]
set fsid [lindex $info 0]
mfs unlink /Recording/TmsId/$path

# create the recording
set recording [db $db create Recording]
dbobj $recording set BitRate 0 ;# obsolete
dbobj $recording set ErrorString "test recording"
dbobj $recording set ExpirationDate [expr $today + 2]
dbobj $recording set ExpirationTime 0 ;# midnight
dbobj $recording set RecordQuality 100
dbobj $recording set Score 0
dbobj $recording set SelectionType 5 ;# explicit timer
dbobj $recording set StartDate $date
dbobj $recording set StartTime $startTime
dbobj $recording set State 4 ;# complete
dbobj $recording set StopDate $date
dbobj $recording set StopTime [expr $startTime + $duration]


# create a part
set part [db $db createsub RecordingPart $recording]
dbobj $part set Begin 0
dbobj $part set End [expr $duration * 1000]
dbobj $part set File $fsid
dbobj $recording add Part $part


# create a dummy program
set program [db $db create Program]
dbobj $program set Title $title


# create a dummy station
set station [db $db create Station]
dbobj $station set CallSign "Tuner2"
dbobj $station set Name "Tuner2"

# create a showing
set showing [db $db createsub Showing $recording]
dbobj $showing set Date $date
dbobj $showing set Duration $duration
dbobj $showing set Program $program
dbobj $showing set Station $station
dbobj $showing set Time $startTime
dbobj $recording set Showing $showing
puts [ dbobj $recording fsid ]
}