Software | charlie on software - Part 6

Archive for the ‘ software ’ Category

Remote control of a TiVo from the Linux command line

I’m a huge fan of TiVo brand DVRs, so much so that I own two of them for myself. That being said,  most of the time that I am watching TV, I also have my laptop open with me. Since I run Linux on my laptops, I knew there had to be a way to write a set of shell scripts to allow me to use my always open terminal to easily manipulate my TiVo.

This is the solution that I came up with:

Assume that ~/bin is on your PATH

Create ~/bin/tivoircode with the following contents:

#!/usr/bin/env python

#simple python script to send remote IR commands to a TiVo DVR
#this script should never be called directly, but rather via
#symbolic links to it
#Written by Charlie Meyer <>
#December 2012

import socket
import sys
import time
import os.path

#set this to the ip address of the tivo to control
tivo_address = ""

sock = None

def connect():
    global sock
    global tivo_address
        sock = socket.socket()
        sock.connect((tivo_address, 31339))
    except Exception, msg:
        print msg

def disconnect():
    global sock

def send_code(code):
    if not sock:
        sock.sendall("IRCODE "+code+"\r")
    except Exception, msg:
        print msg

times = 1;
if(len(sys.argv) > 1):
    times = int(sys.argv[1])

for i in range(0,times):


This is the base script from which all others will inherit. Obviously you will need to change the variable at the top of the file to point to the IP address of the TiVo which you want to control.

Now, here comes the fun part. There are a series of symbolic links that need to be made. The name of the link is the raw IR code that is sent to the TiVo, and they all link back to the master script we just created. I have not added all of the remote functions to my environment, but rather only the ones that I regularly use:

lrwxrwxrwx 1 chuck chuck   10 Dec  3 21:48 CLEAR -> tivoircode
lrwxrwxrwx 1 chuck chuck   10 Dec  3 21:50 PAUSE -> tivoircode
lrwxrwxrwx 1 chuck chuck   10 Dec  3 21:51 REPLAY -> tivoircode
lrwxrwxrwx 1 chuck chuck   10 Dec  3 21:51 RIGHT -> tivoircode
lrwxrwxrwx 1 chuck chuck   10 Dec  3 21:52 LEFT -> tivoircode
lrwxrwxrwx 1 chuck chuck   10 Dec  3 21:52 UP -> tivoircode
lrwxrwxrwx 1 chuck chuck   10 Dec  3 21:52 DOWN -> tivoircode
lrwxrwxrwx 1 chuck chuck   10 Dec  3 21:54 PLAY -> tivoircode
lrwxrwxrwx 1 chuck chuck   10 Dec  3 21:54 INFO -> tivoircode
lrwxrwxrwx 1 chuck chuck   10 Dec  3 21:55 SELECT -> tivoircode
lrwxrwxrwx 1 chuck chuck   10 Dec  3 21:56 ADVANCE -> tivoircode
lrwxrwxrwx 1 chuck chuck   10 Dec  3 22:02 TIVO -> tivoircode
lrwxrwxrwx 1 chuck chuck   10 Dec  3 22:03 WINDOW -> tivoircode
lrwxrwxrwx 1 chuck chuck   10 Dec  3 22:04 CHANNELUP -> tivoircode
lrwxrwxrwx 1 chuck chuck   10 Dec  3 22:04 CHANNELDOWN -> tivoircode
lrwxrwxrwx 1 chuck chuck   10 Dec  3 22:04 THUMBSDOWN -> tivoircode
lrwxrwxrwx 1 chuck chuck   10 Dec  3 22:04 THUMBSUP -> tivoircode
lrwxrwxrwx 1 chuck chuck   10 Dec  4 18:04 GUIDE -> tivoircode

To create each one of these, use the ln command, such as:

ln -s tivoircode PLAY

to link PLAY to tivoircode

You should now be able to use the command PLAY in your terminal to cause the TiVo to emulate a regular infrared remote control pressing the play button.

Based on research done online, the following IRCODE commands can be symlinked to my tivoricode script and work properly (should be self-explanatory):


I wanted to make it a little easier for me, since typing PLAY is probably harder than actually just pressing the play button on the physical remote. To solve this, I created a set of bash aliases that map shorthand commands to the symbolic links we just created. Here is what I added to my ~/.bashrc at the bottom:

#TiVO commands
alias info="INFO"
alias cl="CLEAR"
alias pa="PAUSE"
alias pu="PAUSE"
alias replay="REPLAY"
alias rw="REPLAY"
alias re="REPLAY"
alias down="DOWN"
alias d="DOWN"
alias up="UP"
alias u="UP"
alias left="LEFT"
alias l="LEFT"
alias right="RIGHT"
alias r="RIGHT"
alias play="PLAY"
alias pl="PLAY"
alias select="SELECT"
alias sel="SELECT"
alias ff="ADVANCE"
alias skip="ADVANCE"
alias tivo="TIVO"
alias zoom="WINDOW"
alias zm="WINDOW"
alias chup="CHANNELUP"
alias chu="CHANNELUP"
alias pgu="CHANNELUP"
alias pgup="CHANNELUP"
alias chdn="CHANNELDOWN"
alias chd="CHANNELDOWN"
alias pgdn="CHANNELDOWN"
alias pgd="CHANNELDOWN"
alias thumbsup="THUMBSUP"
alias thup="THUMBSUP"
alias thu="THUMBSUP"
alias thumbsdown="THUMBSDOWN"
alias thdn="THUMBSDOWN"
alias thd="THUMBSDOWN"
alias guide="GUIDE"
alias gu="GUIDE"

Now, i can use my TiVo from the konsole (via yakuake) that I always have running using commands such as `ff 6` to fast forward 6×30 seconds, `rw 3` to rewind 3×8 seconds, `pu` to pause, `pl` to play, etc etc etc

shoutout to Alex Lambert for his help pointing out some of the obvious to me

ITiCSE 2012 Slides

In a few weeks, I will be traveling with Michael Woodley to Haifa, Israel to attend the ITiCSE 2012 conference (conference on innovation and technology in computer science education). This will be my second trip to this conference as I traveled to Germany last summer to present work on another topic. This year, I will be presenting on the course that I have helped to develop at the University of Illinois at Urbana-Champaign over the past six years. The paper can be seen in a previous post here, but the slide deck I will be using to present can be seen here:

In order to view this page you need Flash Player 9+ support!

Get Adobe Flash player

In addition to the week I will be spending in Israel, I will be making a side trip after to Istanbul, Turkey to meet with Professor Barış Aktemur at Özyeğin University there as he is replicating our course. This is the second ever installment worldwide of our programming studio concept, and we are excited to meet with him to discuss how his first semester of the course was as well as share our tips for success and learn from him what we can do to improve our course as well.

I’m looking forward to the trip to Asia very much, but not so much to the 20 hours of travel that it will take to get to Israel as well as the 8 hours of time difference that I will need to adjust to once I arrive. Wish me luck!

Gradient Backgrounds With Processing

I came across the need to make a gradient background for a visualization prototype I was working on for a course. We were using processing, and here is the code that I came up with to accomplish it. Usage should be fairly straightforward, and it should be easy to modify for any needs anyone has.

class GradientBackground{
  color[] colors;
  int c_alpha;
  GradientBackground(color[] t_colors, int t_alpha){
    colors = t_colors;
    c_alpha = t_alpha;
    float w = width;
    int colorWidth = (int)((w / (colors.length-1)));
    int colorHeight = height;
    for(int colorIndex = 0; colorIndex < (colors.length-1); colorIndex++){
      setGradient(colorIndex*colorWidth, 0, colorWidth, colorHeight, colors[colorIndex], colors[colorIndex+1]);    

  void setGradient(int x, int y, float w, float h, color c1, color c2 ){
    float deltaR = red(c2)-red(c1);
    float deltaG = green(c2)-green(c1);
    float deltaB = blue(c2)-blue(c1);
    for (int i=y; i<=(y+h); i++){
        for (int j = 1; j<=w; j++){
          color c = color(
          //point(j+x, i); //this line is buggy, doesnt work properly with most recent version of processing
          rect(j+x, i,1,1);