And Now For Something Really Esoteric

And off topic. But last week I got a refurb SiliconDust HDHomeRun TV Tuner in my continuing quest to tell satellite and cable providers to shove it. And it’s awesome. HD TV streaming to any device on my network. I can’t recommend it enough.

But while Linux support is good, if you aren’t using MythTV (which it purportedly works great with), the terminal interface is a pain. Using VLC and a terminal you can tune into a channel only after running a bunch of lengthy terminal commands, followed by another lengthy commands to change channels again should you accidentally land on the WB. It’s almost as bad as installing MythTV. Almost.

So, for the exactly none of you that could use this, I present my python script for changing channels on the little beast from Linux. It defaults to tuner 0, the default HDHomeRun on the network, and the channel list in the same directory as listings.txt, though all those are configurable via command line options. It isn’t pretty - my python skills don’t range far past hello world - but it works. On Ubuntu, the HDHomeRun libraries are in the repos - sudo apt-get install hdhomerun-config.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#!/usr/bin/python

###################################################
# Code to make me not want to kill myself
# when using HDHomeRun
###################################################

import os
import subprocess
import time
import getopt, sys


channelList = []
device = "FFFFFFFF"
tuner = "0"
channelFile = "listings.txt"


###################################
# Create Channel List
# channel, program, description
###################################
def readChannels(thefile):
myfile = open(thefile, "r").readlines()
for index in range(len(myfile)):
if "PROGRAM" in myfile[index]:

program = myfile[index].split()[1].rstrip(":") # program
description = myfile[index].split(":")[1].replace("\n", "").replace("\r","") # Description

i = 3
while (i < 10):
if myfile[index - i].split()[0] == "SCANNING:":
channel = myfile[index - i].split()[1]
break
else:
i += 1

channelList.append([channel,program,description])

return

###################################
# Launch VLC
###################################
def launchVLC():
#os.system("vlc udp://@:1234 &amp;")
p = subprocess.Popen(["vlc", "udp://@:1234"], stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
time.sleep(2)
return

###################################
# Tune HDHomeRun to VLC
###################################
def hdTarget(device, tuner):
test = os.system("hdhomerun_config " + str(device) + " set /tuner" + str(tuner) + "/target 192.168.1.109:1234")
return

###################################
# Set Channel
###################################
def hdChannel(device, tuner, channel):
os.system("hdhomerun_config " + str(device) + " set /tuner" + str(tuner) + "/channel 8vsb:" + str(channel))
return

###################################
# Set Program
###################################
def hdProgram(device, tuner, program):
os.system("hdhomerun_config " + str(device) + " set /tuner" + str(tuner) + "/program " + str(program))
return

###################################
# Print Menu
###################################
def printMenu():
print "------------------------------"
i = 1
for ch in channelList:
print str(i) + " - " + ch[2]
i += 1
print "x - Exit"


###################################
# Present the channel selector and
# change channels. It's self-
# referencing.
###################################
def channelSelector():
printMenu()
foo = raw_input("Enter something: ")
try:
if int(foo) and int(foo) > 0 and int(foo) <= (len(channelList)):
print "Yee haw - we be changin' channels!"
print ""
hdChannel(device, tuner, channelList[int(foo) - 1][0])
hdProgram(device, tuner, channelList[int(foo) - 1][1])
else:
print "That's not a channel. Idiot."
print ""

except:
if foo == "x":
print "Thank you have a nice day come again."
sys.exit(2)
else:
print "You suck. Try again."
print ""
channelSelector()


###################################
# Usage
###################################
def usage():
print "Usage: tv.py [options]"
print "Control my HDHomeRun from Linux in such a way that doesn't make me want to shoot it."
print ""
print "-h, --help Help"
print "-d <device>, --device <device> ID of device. Default is FFFFFFFF, or only 1 on network."
print "-t <tuner>, --tuner <tuner> Device tuner. Default is 0."
return



def main():
try:
opts, args = getopt.getopt(sys.argv[1:], "hd:t:f:", ["help", "device=", "tuner=", "file="])
except getopt.GetoptError, err:
# print help information and exit:
print str(err) # will print something like "option -a not recognized"
usage()
sys.exit(2)

global channelFile
global device
global tuner

for o, a in opts:
if o in ("-d", "--device"):
device == a
elif o in ("-f", "--file"):
channelFile = a
elif o in ("-t", "--tuner"):
tuner = a
elif o in ("-h", "--help"):
usage()
sys.exit()
else:
assert False, "unhandled option"

launchVLC()
hdTarget(device, tuner)
readChannels(channelFile)
hdChannel(device, tuner, channelList[0][0])
hdProgram(device, tuner, channelList[0][1])
channelSelector()


if __name__ == "__main__":
main()

The result is a VLC player launching with the first channel in the channel list, and a menu like this:

[crayon lang=”default”]
1 - 46.1 WJZY-HD
2 - 46.2 WJZY-SD
3 - 58.1 UNC-TV
4 - 58.2 UNC-KD
5 - 58.3 UNC-EX
6 - 55.1 WMYT-HD
7 - 55.2 WMYT-SD
8 - 55.3 WordNet
9 - 9.1 WSOC-TV
10 - 9.2 WSOC-WX
11 - 3.1 WBTV-DT
12 - 3.2 WBTV-SD
13 - 36.1 WCNC-HD
14 - 36.2 WCNC-LW
x - Exit
Enter something: