Previous section   Next section

Hack 90 Extracting Your Now Showing List

figs/moderate.giffigs/hack90.gif

Ask TiVo's MFS database for your Now Showing List, including title, description, and date and time the show aired.

Curious about what's showing? Want to keep track of your television viewing habits (or at least what's been recorded for you) over time? You can ask the TiVo MFS with some pretty trivial data mining. We'll start with the Now Showing List and everything TiVo knows about the shows we currently have queued up for watching. We'll write the title, description, and date and time the show aired to a file and save it. You can even automate this using cron [Hack #44] and write the files to your PC's NFS-mounted [Hack #56] drive if you are truly serious about archiving that data.

Let's go over what we already know. We know that recorded programs are all held in /Recording/NowShowingByTitle, and we know that each of these programs has all the information we want somewhere in its closure of objects. Therefore, we can easily find the date the show aired, the name of the program, and the name of the episode.

Before we write the code, let's actually find all this information in the closure listed in [Hack #89]. The date and time the show aired are listed in the top Recording object under StartDate and StartTime; conveniently, this is listed under the FSID of the object in /Recording/NowShowingByTitle. The rest of the information seems to be in the Program object. The path between the Recording object and the Program object seems to pass through Showing. We want to grab the Recording object, follow through the Showing attribute to a Showing object, and follow that out to a Program attribute.

Seems simple enough. All we need to do is express this in Tcl. The heart of the program just makes use of mfs commands to maneuver through the directories and then uses dbobj commands to dig into the database. To get a rundown of some of the commands that people know about (remember that these things are discovered, not documented), take a gander at Table 7-2 and Table 7-3.

Table 7-2. Some of the mfs commands used to manipulate files on the Media Filesystem

Filesystem command

Purpose

mfs find <path>

Look for an item in the MFS and return its FSID and type

mfs mkdir <path>

Make a named directory

mfs rmdir <path>

Remove a named directory

mfs streamsize <fsid>

Get the size of a recording stream

mfs moddate <fsid>

Return the last time an object was modified, in seconds since the Unix epoch time

mfs size <fsid>

Return the size of a given MFS object

mfs scan <path> [-start string] [-count number] [-backward]

List up to a certain number of items in a specific MFS directory that optionally starts with a specified string

Table 7-3. Some of the dbobj commands used to manipulate database objects

Database object command

Purpose

dbobj equal <dbobj> <dbobj>

Test the equality of two database objects

dbobj <dbobj> fsid

Return the FSID of a database object

dbobj <dbobj> subobjid

Return the subobjid of a database object

dbobj <dbobj> type

Return the type of a database object

dbobj <dbobj> attrs

Return the attributes of a database object

Dbobj <dbobj> attrtype <attr>

Get the type of an attribute of a database

dbobj <dbobj> get [-noerror] <attr> [<index>]

Get the value of a specific attribute of this type

dbobj <dbobj> add <attr> <tclobj>

Append an attribute of a given name to a database object

Dbobj <dbobj> remove <attr> [<tclobj>]

Remove the last attribute of a given name from a database object

dbobj <dbobj> delete

Delete a particular database object (be careful with this one)

dbobj <dbobj> clear

Clear out a particular database object

dbobj <dbobj> removeat <attr> <index>

Remove a specific attribute from a database object. The index is used when there are multiple attributes with the same name

dbobj <dbobj> copyfrom <dbobj>

Copy a database object

The Code

You'll need my tivotime library (http://www.bitwaste.com/tivo/tivotime.tar.gz) to handle time in a manner TiVo understands. Download it, extract tivotime.tcl from the archive, and drop it [Hack #36] into /var/hack/lib/tcl on your TiVo.

#!/tvbin/tivosh

# include code to do a timezone conversion back into our time format
source /var/hack/lib/tcl/tivotime.tcl

# open the database
set db [dbopen]

# pull out the first 50 recorded shows from the database
set recdir "/Recording/NowShowingByTitle"
transaction {
    set files [mfs scan $recdir -count 50]
}
    
while { [llength $files] > 0 } {
    # iterate through the shows we extracted
    foreach rec $files {
        # grab the FSID of the program from the list
        set fsid [lindex $rec 0]

        transaction {
            # get the object that represents this recording and the
            # object that represents this episode.
            set recordingobj [db $db openid $fsid]
            set episodeobj [dbobj [dbobj $recordingobj get Showing][RETURN]
            get Program]
            
            # pull out the date the show aired 
            # convert it to something a bit more
            # human-readable using the tivotime library
            set showtime [::tivotime::converttime \
                              [dbobj $recordingobj get StartDate] \
                              [dbobj $recordingobj get StartTime] ]
            set showtime [clock format $showtime -format "%m/%d/%Y %H:%M"]
            
            # pull out the show's name and episode title
            regsub -all "\[\{\}\]" [dbobj $episodeobj get Title] ""[RETURN]
           programname
           regsub -all "\[\{\}\]" [dbobj $episodeobj get[RETURN]
           EpisodeTitle] episodename
        }
            
        # output a pipe (|) delimited list containing the date,
        # show name, and episode title
            puts "$showtime | $programname | $episodename"
    }
    
    # and grab the next 50 television shows
    set lastName [lindex [lindex $files end] 1]
    transaction {
            set files [mfs scan $recdir -start $lastName -count 50]
    }

    if { $lastName == [lindex [lindex $files 0] 1] } {
            set files [lrange $files 1 end]
    }    
}

Save the code as nowshowing.tcl in TiVo's /var/hack/bin directory and make it executable:

bash-2.02# chmod 755 /var/hack/bin/nowshowing.tcl

Running the Hack

From TiVo's command line Section 3.3, invoke the script, like so:

bash-2.02# /var/hack/bin/nowshowing.tcl
06/07/2003 21:29 | 2003 MTV Movie Awards | 
05/20/2003 19:59 | 24 | Day 2: 7:00 - 8:00AM
06/05/2003 18:59 | The Amazing Race 4 | It Doesn't Say Anything About First 
Come, First Served. And We're Bigger
12/02/2001 15:59 | The Armenians: A Story of Survival | 
06/02/2003 01:59 | Coming Attractions | 
05/14/2003 18:59 | Dawson's Creek | All Good Things ... Must Come to an End
05/07/2003 18:59 | Dawson's Creek | Joey Potter and Capeside Redemption
04/30/2003 18:59 | Dawson's Creek | Goodbye, Yellow Brick Road
04/16/2003 18:59 | Dawson's Creek | Lovelines
04/09/2003 18:59 | Dawson's Creek | Love Bites
02/12/2003 19:59 | Dawson's Creek | Castaways
02/05/2003 19:59 | Dawson's Creek | Clean and Sober
01/15/2003 19:59 | Dawson's Creek | Day Out of Days
12/11/2002 19:59 | Dawson's Creek | Merry Mayhem
11/20/2002 19:59 | Dawson's Creek | Everything Put Together Falls Apart
11/13/2002 19:59 | Dawson's Creek | Spiderwebs
11/06/2002 19:59 | Dawson's Creek | Ego Tripping at the Gates of Hell
10/30/2002 19:59 | Dawson's Creek | Living Dead Girl
10/23/2002 18:59 | Dawson's Creek | The Impostors
10/16/2002 18:59 | Dawson's Creek | Instant Karma!
06/07/2003 02:59 | East Meets West | Sushi 303
06/04/2003 14:29 | Epicurious | Dim Sum
06/05/2003 01:29 | Food 911 | Two Guys, a Girl and a Brisket!
06/04/2003 01:29 | Food 911 | Empanadas to Go
06/02/2003 19:59 | For Love or Money | 
06/05/2003 03:29 | The Galloping Gourmet | Mantay
05/13/2003 18:59 | Gilmore Girls | Here Comes the Son
05/06/2003 18:59 | Gilmore Girls | Say Goodnight, Gracie
06/04/2003 15:29 | Great Chefs of the World | Stuffed Mushrooms; Hazelnut 
Napoleon
06/04/2003 14:59 | Great Chefs of the World | Shrimp Ceviche; Lamb; Banana 
Pudding
04/18/2003 19:59 | John Doe | Remote Control
06/04/2003 19:59 | Junkyard Wars | Manic Mud Racers
06/06/2003 23:37 | Late Night With Conan O'Brien | 
05/25/2003 20:59 | Single in the Hamptons | 
03/02/2003 16:59 | Smallville | Rosetta
02/23/2003 16:59 | Smallville | Fever
02/16/2003 16:59 | Smallville | Prodigal
02/09/2003 16:59 | Smallville | Rush
06/08/2003 14:59 | Star Trek: The Next Generation | A Fistful of Datas
05/07/2003 19:59 | The West Wing | Commencement
04/23/2003 19:59 | The West Wing | Evidence of Things Not Seen
02/26/2003 20:59 | The West Wing | Red Haven's on Fire
02/19/2003 20:59 | The West Wing | California 47th

To capture the Now Playing List as a pipe-delimited text file, use the > redirect symbol and supply the name of a file to which to write. For example, sending output to a file called nowshowing.out in the /var/out directory would look like this:

bash-2.02# /var/hack/bin/nowshowing.tcl > /var/out/nowshowing.out

  Previous section   Next section
Top