#!/usr/bin/python import sys import os import os.path from Tkinter import * from subprocess import * import thread import threading import atexit import time import datetime ### configuration section # your ivtv device device = '/dev/video0' # for a list of regions, run # ivtv-tune -L -d/dev/video0 # from the command line region = 'europe-west' # do you want to try the experimental recording # functions? recorder = True ### ### end of configuration section def initMsg(master): global Messages msgframe = LabelFrame(master, text='Messages', width='600', height='100') msgframe.grid(row=2, column=0, sticky='nsew') msgframe.grid_rowconfigure(0, weight=1) msgframe.grid_columnconfigure(0, weight=1) Messages = Text(msgframe, height=1) Messages.grid(row=0, column=0, sticky='nswe') sb=Scrollbar(msgframe) sb.grid(row=0, column=1, sticky='ns') Messages.configure(yscrollcommand=sb.set) sb.configure(command=Messages.yview) # enddef def putMsg(s): global Messages Messages.insert('1.0',s+'\n') Messages.yview(0) root.update() # enddef def replaceMsg(s): global Messages Messages.delete('1.0','1.end') Messages.insert('1.0',s+'\n') Messages.yview(0) root.update() # enddef def cleanup(): global Stop global video video.stop() Stop = True for t in threading.enumerate()[1:]: print 'waiting for ' + t.getName() t.join print 'ok' # endfor # enddef class Recorder: """Singleton for the VCR""" def __init__(self, master): global Stop global Running Stop = False Running = False self.enabled = True self.frame = LabelFrame(master, text='Video Recorder', width='600', height='100') self.frame.grid(row=1, column=0, sticky='nsew') self.frame.grid_rowconfigure(0, weight=1) self.frame.grid_columnconfigure(0, weight=1) self.lbl_station = Label(self.frame, text='Station') self.lbl_station.grid(row=0, column=0) self.ent_station = Entry(self.frame, textvariable='channelname') self.ent_station.grid(row=1, column=0) self.ent_station.configure(state='readonly') self.lbl_date = Label(self.frame, text='Date') self.lbl_date.grid(row=0, column=1) self.ent_date = Entry(self.frame) self.ent_date.grid(row=1, column=1) self.lbl_start = Label(self.frame, text='Start Time') self.lbl_start.grid(row=0, column=2) self.ent_start = Entry(self.frame) self.ent_start.grid(row=1, column=2) # self.lbl_stop = Label(self.frame, text='Stop Time') # self.lbl_stop.grid(row=2, column=2) # self.ent_stop = Entry(self.frame) # self.ent_stop.grid(row=3, column=2) self.lbl_duration = Label(self.frame, text='Duration') self.lbl_duration.grid(row=2, column=1) self.ent_duration = Entry(self.frame) self.ent_duration.grid(row=3, column=1) self.lbl_record = Label(self.frame, text='Record') self.lbl_record.grid(row=2, column=0) self.ent_record = Checkbutton(self.frame, command=self.toggle) self.ent_record.grid(row=3, column=0) now = datetime.datetime.now() self.ent_date.insert(0, '%02d.%02d.%d' % (now.day,now.month,now.year)) self.ent_start.insert(0, '%02d:%02d' % (now.hour,now.minute)) self.ent_duration.insert(0, '5') # enddef def toggle(self): if self.enabled: self.disable() self.enabled = False putMsg('disabled') else: self.enable() self.enabled = True putMsg('enabled') # endif # enddef def disable(self): self.ent_station.configure(textvariable='recordstation') self.ent_date.configure(state='disabled') self.ent_start.configure(state='disabled') # self.ent_stop.configure(state='disabled') self.ent_duration.configure(state='disabled') self.startRecording() # def def enable(self): self.ent_station.configure(textvariable='channelname') self.ent_date.configure(state='normal') self.ent_start.configure(state='normal') # self.ent_stop.configure(state='normal') self.ent_duration.configure(state='normal') self.stopRecording() # def def startRecording(self): global Stop global Running now = datetime.datetime.now() day = self.ent_date.get().split('.') begin = self.ent_start.get().split(':') duration = int(self.ent_duration.get()) * 60 start = datetime.datetime(*[int(x) for x in (day[2],day[1],day[0],begin[0],begin[1],0)]) diff = start - now self.t1 = threading.Timer(diff.seconds, self.record) self.t1.setName('record-thread') self.t1.start() self.t2 = threading.Timer(diff.seconds+duration, self.stopRecording) self.t2.setName('stop-recording-thread') self.t2.start() t3 = threading.Thread(target=self.wait, args=(start,)) t3.setName('wait-and-display-thread') t3.start() # enddef def wait(self, start): global Stop global Running before = True while not Stop: time.sleep(60) if Running: if before: before = False # endif runtime = datetime.datetime.now() - start replaceMsg('Time elapsed %10s' % datetime.timedelta(0,runtime.seconds)) else: runtime = start - datetime.datetime.now() replaceMsg('Time to wait %10s' % datetime.timedelta(0,runtime.seconds)) # endif # endwhile # endef def stopRecording(self): global Running global Stop if not Running: try: self.t1.cancel() self.t2.cancel() except: print "not timer to cancel" pass # endtry # endif Stop = True # enddef def record(path='./'): global Stop global Running global video video.stop() time.sleep(5) f = open('/dev/video0','r') g = open('%s.mpg' % time.ctime(time.time()).replace(' ','_'),'w') putMsg('started recording at %s' % time.ctime(time.time())) Running = True while not Stop: try: a = f.read(128) g.write(a) except: break # endtry # endwhile f.close() g.close() putMsg('stopped recording at %s' % time.ctime(time.time())) Stop = True # enddef class VideoApp: def __init__(self,button): self.app = None self.on = False self.button = button # enddef def start(self): self.on = True self.app = Popen("/bin/sh", stdin=PIPE) self.app.stdin.write("cat /dev/video0 2>/dev/null | gxine stdin:/ &\n") self.app.stdin.flush() self.button.configure(text="TV off") # enddef def stop(self): try: self.app.stdin.write("kill $!\n") self.on = False self.button.configure(text="TV on") except: pass # endtry # enddef def toggle(self): if self.on: self.stop() else: self.start() # endif # enddef # endclass class ChannelList: """Singleton for the channel listbox""" def __init__(self, master): self.list = [] self.idx = 0 self.frame = LabelFrame(master, text='Channel List', width='600', height='600') self.frame.grid(row=0, column=0, sticky='nsew') self.frame.grid_rowconfigure(0, weight=1) self.frame.grid_columnconfigure(0, weight=1) self.editframe = Frame(self.frame) self.editframe.grid(row=0, column=2, columnspan=1) self.lbl_number = Label(self.editframe, text='Number') self.lbl_number.grid(row=0, column=0) self.ent_number = Entry(self.editframe) self.ent_number.grid(row=0, column=1) self.lbl_name = Label(self.editframe, text='Name') self.lbl_name.grid(row=1, column=0) self.ent_name = Entry(self.editframe, textvariable='channelname') self.ent_name.grid(row=1, column=1) self.but_name = Button(self.editframe, text="Set Name", command=self.updateName) self.but_name.grid(row=1, column=2) self.box = Listbox(self.frame) self.box.grid(row=0, column=0, columnspan=1) self.sb=Scrollbar(self.frame) self.sb.grid(row=0, column=1, sticky='ns') self.box.configure(yscrollcommand=self.sb.set) self.sb.configure(command=self.box.yview) self.box.bind("<>", self.tune) self.box.bind("", self.edit) self.box.bind("", self.next) self.box.bind("", self.previous) master.bind("", self.previous) self.load() self.box.select_set(self.idx,self.idx) self.tune() # enddef def grid(self, **args): self.box.grid(args) # enddef def load(self): global region global device home = os.getenv("HOME") if not os.access(home+"/.watchit", os.F_OK): os.mkdir(home+"/.watchit") # endif channelstxt = home+"/.watchit/channels.txt" if not os.access(channelstxt, os.F_OK): if os.access("/usr/local/share/watchit/channels.txt", os.F_OK): channelstxt = "/usr/local/share/watchit/channels.txt" else: fin = os.popen("ivtv-tune -t%s -d%s -l" % (region, device)) fout = file(home+"/.watchit/channels.txt", "w") i = 0 for line in fin: channel = line.split()[0] check = os.popen("ivtv-tune -t%s -d%s -c %s" % (region, device,channel)) response = check.readline() if len(response.split()) == 3: continue # endif i = i+1 fout.write("%d %s -\n" % (i, channel)) # endfor fin.close() fout.close() # endif # endif f = file(channelstxt, "r") for line in f: tmp = line.split() tmp = tmp[:] + ["-", "-", "-"][len(tmp):] self.list.append(line) self.box.insert(END, "%5s %5s %5s" % (tmp[0], tmp[1], tmp[2])) # endfor f.close() # enddef def save(self): home = os.getenv("HOME") f = file(home+"/.watchit/channels.txt", "w") for entry in self.box.get(0,END): f.write(entry + "\n") # endfor f.close() # enddef def edit(self, arg): channel = int(self.box.curselection()[0]) # enddef def tune(self, arg=""): global region global device info = self.getEntry().split() channel = info[1] os.system("ivtv-tune -t%s -d%s -c%s" % (region, device,channel)) self.ent_number.delete(0,END) self.ent_number.insert(0, info[0]) self.box.see(self.idx) self.ent_name.delete(0,END) self.ent_name.insert(0, info[2]) # enddef def getEntry(self): self.idx = int(self.box.curselection()[0]) select = self.box.get(self.idx, END) return select[0] # enddef def getName(self): return self.getEntry().split()[2] # enddef def updateName(self, arg=""): # self.idx = int(self.box.curselection()[0]) self.box.select_set(self.idx,self.idx) entry = self.box.get(self.idx, END)[0].split() entry[2] = self.ent_name.get().replace(' ','_') self.box.delete(self.idx,self.idx) self.box.insert(self.idx, "%5s %5s %5s" % (entry[0],entry[1],entry[2])) self.box.select_clear(0,END) self.box.select_set(self.idx,self.idx) self.save() # enddef def set(self,pos): self.box.select_clear(0, END) self.idx = pos % len(self.list) self.box.select_set(self.idx, self.idx) self.tune() def next(self, arg=""): self.box.select_clear(0, END) self.idx = (self.idx + 1) % len(self.list) self.box.select_set(self.idx, self.idx) self.tune() # enddef def previous(self, arg=""): self.box.select_clear(0, END) self.idx = (self.idx + len(self.list) - 1) % len(self.list) self.box.select_set(self.idx, self.idx) self.tune() # enddef # endclass ### main program # root=Tk() # configure the root window # root.title(os.path.basename(sys.argv[0])) root.grid_rowconfigure(0, weight=1) root.grid_columnconfigure(0, weight=1) #controlframe = Frame(root) #controlframe.grid(row=0, column=1) buttonframe = Frame(root) buttonframe.grid(row=3, column=0, sticky='we') tv = Button(buttonframe, text="TV on") tv.grid(row=0, column=0, sticky='w') video = VideoApp(tv) tv.configure(command=video.toggle) quit = Button(buttonframe, text="Quit", command=root.destroy) quit.grid(row=0, column=1, sticky='e') channels = ChannelList(root) channels.grid(row=0, column=0, sticky='nsew') if recorder: vcr = Recorder(root) # endif initMsg(root) putMsg('Welcome!') atexit.register(cleanup) root.mainloop()