#!/usr/bin/env python # -*- coding: UTF-8 -*- '''Videoremote version 5.3 This program is a video mplayer selector for an infreared remote. (c) 2003-2009 Jan ONDREJ (SAL) This program is licensed under GPLv2+. ''' import gobject import gtk import os, re, sys, locale, string, math, time, traceback from sdict import sdict import httpfs, iptv2, urllib, urllib2 try: import pylirc except: pass COLUMN_SHOW = 0 COLUMN_CNTR = 1 GDK=gtk.keysyms files_menu = 1 dirname=os.path.dirname(sys.argv[0]) win = None class globals: command_line = [] menutype = None stored_values = [] lastpath = '' path = '' column = None prog_progs = { 1:"Mark", 2:"JOJ", 3:"TA3", 4:"Prima", 5:"ČT *1", # Ceska televizia 6:"ČT *2", 7:"Hallmark", 8:"Spektrum", 9:"Discovery", 10:"DEKO", 11:"Paprika", 12:"Film", # Film+ 13:"MGM", 14:"VH1", 15:"(STV *1|Jednotka)", 16:"(STV *2|Dvojka)", 17:"Jetix", 18:"Minimax", 19:"Musicbox", 20:"Zone romantica", 21:"Zone club", 22:"Zone reality", 23:"Animal planet", 24:"(M1|MTV)", 25:"TV 2", 26:"Duna", 27:"Acko", 28:"CNN", 29:"Pro7", 30:"Sport1", 31:"Eurosport", 32:"Extreme", 33:"Galaxysport", 34:"HBO", 35:"Teleprior", 36:"Nautik" } def ls(path): if path.startswith('http://'): l=httpfs.listdir(path) else: l=os.listdir(path) l.sort() l.append('../') for i in ['.x','.mplayer.conf']: try: l.remove(i) except: pass return l def recode(s, charset=None): if charset==None: charset = locale.getlocale()[1] try: return urllib.unquote_plus(unicode(s, charset)) except UnicodeError: print "UnicodeError:",s return s shlist=[] class seen: def __init__(self): self.log_file=os.path.join(dirname,'last_seen.log') # load last seen file try: self.files=dict([x.strip().split('\t',1) for x in open(self.log_file).readlines()]) except IOError: self.files={} def save(self): # store it back f=open(self.log_file+'.tmp','w') f.write('\n'.join(["%s\t%s" % (x,self.files[x]) for x in sorted(self.files)])) f.close() os.rename(self.log_file+'.tmp',self.log_file) def count(self,name): c=[x[:-4] for x in self.files.values()].count(name.rstrip('\r\n')[:-4]) if c>9: return 9 else: return c def inc(self,name): if not name.startswith('http://'): name=os.path.abspath(name.rstrip('\r\n')) t=time.strftime("%Y:%m:%d %H:%M:%S.%%s") % str(time.time()%1)[2:5] self.files[t]=name def last_idx(self,path): paths=[(os.path.join(path,x),id) for x,id in zip(shlist,range(len(shlist))) if os.path.isdir(os.path.join(path,x))] for key in sorted(self.files.keys(),reverse=True): value=self.files[key] for p,id in paths: if p in value: print p,key,value,sorted(self.files.keys()).index(key) return id raise ValueError,'Not found' seen=seen() def set_model(store, list, path=""): global sw,shlist shlist=list sw.get_vadjustment().set_value(0) sw.get_hadjustment().set_value(0) store.clear() store.d={} cursor,cursor_line=-1,0 if path=="": for item in list.keys(): iter = store.append() store.d[recode(item)]=list.get(item) store.set(iter, COLUMN_SHOW, recode(item), COLUMN_CNTR, '') else: for item in list: iter = store.append() if os.path.isdir(path+"/"+item) and (not item.endswith('/')): item2=item+"/" else: item2=item store.d[recode(item2)]=[item] cntr=seen.count(path.rstrip('/')+"/"+item) if (cursor<0) and (cntr==0): cursor=cursor_line store.set(iter, COLUMN_SHOW, recode(item2), COLUMN_CNTR, str(cntr or '')) cursor_line+=1 #traceback.print_stack() return cursor class base: ''' base class ''' def __add__(self,second): x=base() x.ADD_A=self x.ADD_B=second return x def main(self,row,column,treeview,model): self.ADD_A.main(row,column,treeview,model) self.ADD_B.main(row,column,treeview,model) class set_menu(base): def __init__(self, menutype, store_value=None): self.menutype = menutype self.store_value = store_value def main(self,row,column,treeview,model): globals.stored_values.append(self.store_value) globals.menutype=self.menutype set_model(model,globals.menutype) treeview.set_cursor(0,column,0) class film(base): def main(self,row,column,treeview,model): globals.path = os.environ['HOME']+'/ln/video' globals.lastpath=globals.path globals.menutype = files_menu set_model(model, ls(globals.path), globals.path) treeview.set_cursor(0,column,0) class nextfilm(base): def main(self,row,column,treeview,model): globals.path = globals.lastpath globals.menutype = files_menu set_model(model, ls(globals.path), globals.path) if treeview.cursor_pos.has_key(globals.path): treeview.set_cursor(treeview.cursor_pos[globals.path],column,0) class myexec(base): def __init__(self,*args): self.args = args def main(self, row, column, treeview, model): print self.args os.execvp(self.args[0], self.args) class system(base): def __init__(self,arg): self.arg=arg def main(self,row,column,treeview,model): os.system(self.arg) class run(base): def __init__(self,*args): self.arg=args def main(self,row,column,treeview,model): print [self.arg[0]]+globals.command_line seen.save() os.execvp(self.arg[0],[self.arg[0]]+globals.command_line) class run_mplayer(run): def main(self,row,column,treeview,model): if os.path.exists(os.path.join(globals.lastpath,'.mplayer.conf')): globals.command_line.insert(0,'-include') globals.command_line.insert(1, os.path.join(globals.lastpath,'.mplayer.conf')) run.main(self,row,column,treeview,model) class run_xine(run): def main(self,row,column,treeview,model): globals.command_line.append('-f') run.main(self,row,column,treeview,model) class run_vlc(run): def main(self,row,column,treeview,model): globals.command_line.append('-f') run.main(self,row,column,treeview,model) class fork_run(run): def main(self,row,column,treeview,model): if os.fork()==0: os.execvp(self.arg[0],[self.arg[0]]+globals.command_line) else: globals.path=globals.lastpath globals.menutype=files_menu set_model(model,ls(globals.path),globals.path) globals.command_line=[] if treeview.cursor_pos.has_key(globals.path): treeview.set_cursor(treeview.cursor_pos[globals.path],column,0) class fork_run_mplayer(fork_run): def main(self,row,column,treeview,model): if os.path.exists(os.path.join(globals.lastpath,'.mplayer.conf')): globals.command_line.extend([ '-include',os.path.join(globals.lastpath,'.mplayer.conf')]) fork_run.main(self,row,column,treeview,model) class arg(base): def __init__(self,*args): self.args=args def main(self,row,column,treeview,model): globals.command_line.extend(self.args) treeview.set_cursor(0,column,0) class tvprog(base): def __init__(self,download_prog,force_download=False): self.force_download=force_download self.download_prog=download_prog def main(self, row, column, treeview, model): globals.menutype='TVPROG' p=list(self.tv_prog()) set_model(model, p, 'TV') treeview.set_cursor(0, column, 0) globals.column=column def tv_prog(self, file=None): yield time.strftime("%c") reg_title=re.compile('') reg_row=re.compile('^([^<>]+) *
') f = urllib2.urlopen('http://www.salstar.sk/wap/tv/?channel=all') for line in f.readlines(): r_title = reg_title.search(line) if r_title: yield "" yield "TV: %s" % r_title.group(1) continue r_row = reg_row.search(line) if r_row: yield r_row.group(1) class antik_archive(base): def __init__(self, date=None): self.date = date globals.alias_list = [] def main(self, row, column, treeview, model): self.prog = globals.stored_values.pop(-1) globals.menutype='ALIAS' globals.alias_list=iptv2.parse_prog(self.prog, self.date) set_model(model, [' '.join(x[1:]) for x in globals.alias_list], 'TV') treeview.set_cursor(0, column, 0) globals.column=column class exit(base): def main(self,row,column,treeview,model): gtk.main_quit() mplayer_menu = sdict([ {'PLAY (mplayer)': run_mplayer('mplayer')}, {'NEXTFILE': nextfilm()}, {'PLAY without exit': fork_run_mplayer('mplayer')}, {'seek 00:30:00': arg('-ss','00:30:00')}, {'seek 01:00:00': arg('-ss','01:00:00')}, {'aspect 16:10': arg('-aspect','16:10')}, {'crop 16:10': arg('-vf','crop=720:480:0:48','-vo','sdl')}, {'aspect 4:3': arg('-aspect','4:3')}, #{'crop 16:9': arg('-vf','crop=720:428:0:74')}, {'Video out: VDPAU': arg('-vo','vdpau')}, {'Video out: SDL': arg('-vo','sdl')}, {'broken': arg('-ni','-nocache','-mc','0','-forceidx','-nobps','-vf-del','0')}, {'no index': arg('-noidx')}, {'channels1': arg('-channels','1')}, {'deinterlace': arg('-vf', 'kerndeint,yadif,pp=l5/lowpass5')}, {'framedrop': arg('-framedrop')}, {'forced index': arg('-forceidx')}, {'demuxer=lavf (ANTIK archiv)': arg('-demuxer', 'lavf')}, {'ISO8859-2': arg('-subcp','iso8859-2')}, {'subdelay -30': arg('-subdelay','-30')}, {'subfps 23.976': arg('-subfps','23.976')}, {'subfps 29.970': arg('-subfps','29.970')}, {'subfps 25.0': arg('-subfps','25.0')}, {'subfuzziness': arg('-sub-fuzziness', '2')}, {'PLAY (xine)': run_xine('xine')}, {'PLAY (vlc)': run_vlc('vlc')}, ]) vlc_menu = sdict([ {'PLAY (vlc)': run_vlc('vlc')}, ]) help_menu = sdict([ {'HELP PANASONIC': myexec(dirname+'/showrem.py','--remote','PANASONIC')}, {'HELP JVC': myexec(dirname+'/showrem.py','--remote','JVCs')}, {'HELP NEC': myexec(dirname+'/showrem.py','--remote','NEC')} ]) ADAY=24*60*60 TODAY=time.time() // ADAY * ADAY iptv_date_menu = sdict([ {time.strftime("%c", time.localtime(TODAY-x*ADAY)): antik_archive(TODAY-x*ADAY)} for x in range(60) ]) iptv_prog_menu = sdict([ {x[0]: set_menu(iptv_date_menu, x[0])} for x in iptv2.CHANNELS_ITEMS ]) download_prog_old=['xterm','-e', '(date;wget -T 10 -U mozilla -O - "http://www.salstar.sk/wap/tv/mar.php?channel=all" )>/tmp/tv.html; sleep 2s'] download_prog=['xterm','-e', '(date;wget -T 10 -U mozilla -O - "http://www.salstar.sk/wap/tv/?channel=all" )>/tmp/tv.html; sleep 2s'] def dvb_start(ch): #deint = 'fd/ffmpegdeint' deint = 'l5/lowpass5' return myexec( 'mplayer', 'dvb://'+ch, '-vo', 'x11', '-vf', 'kerndeint,yadif,pp='+deint, '-cache-min', '10' # lower to min 10% cache ) dvb_menu = sdict([ {'Markíza': dvb_start('Markiza')}, {'TV JOJ': dvb_start('TV JOJ')}, {'TA3': dvb_start('TA3')}, {'STV1': dvb_start('STV1')}, {'STV2': dvb_start('STV2')}, {'STV3': dvb_start('STV3')} ]) tv_menu = sdict([ {'DVB-T': set_menu(dvb_menu)}, {'START': myexec('tvtime','--fullscreen')}, {'TV program': tvprog(download_prog)}, #{'New program': tvprog(download_prog,True)}, #{'New program V2': tvprog(download_prog_old,True)}, {'ANTIK': set_menu(iptv_prog_menu)}, {'CANCEL': myexec('killall','sleep')}, {'0:15 OFF': myexec(dirname+'/poweroff.sh','15m')}, {'1:00 OFF': myexec(dirname+'/poweroff.sh','60m')}, {'1:30 OFF': myexec(dirname+'/poweroff.sh','90m')}, {'2:00 OFF': myexec(dirname+'/poweroff.sh','2h')}, {'0:01 OFF': myexec(dirname+'/poweroff.sh','1m')} ]) record_menu = sdict([ {'RECORD MOVIE': run(dirname+'/tvrec')}, {'PLAY IT': arg('--play')}, {'SNAPSHOT': myexec(dirname+'/tvrec','--snapshot')}, {'STEREO': arg('-tv','amode=1')}, {'LANG1': arg('-tv','amode=2')}, {'TIME 00:30:00': arg('--mins','30')}, {'TIME 01:00:00': arg('--mins','60')}, {'TIME 01:30:00': arg('--mins','90')}, {'TIME 02:00:00': arg('--mins','120')}, {'TIME 03:00:00': arg('--mins','180')}, {'POWEROFF': arg('--poweroff')}, {'TIME 00:01:00': arg('--mins','1')} ]) system_menu = sdict([ {'RestartIR': system('killall irxevent; irxevent &')+exit()}, {'VIDEO': system('amixer sset Line mute')}, {'TV': system('amixer sset Line unmute')}, {'NO MIC': system('amixer sset Mic mute')}, {'MONITOR OFF': system('xset dpms force standby')}, {'MOUNT /mnt/o': system('mount /mnt/o')} ]) programs_menu = sdict([ {'FILM': film()}, {'TV': set_menu(tv_menu)}, {'RECORD': set_menu(record_menu)}, {'MP3': myexec('xmms')}, {'SYSTEM': set_menu(system_menu)}, {'CLOCK': myexec(dirname+'/clock.py')}, {'PICTURES': myexec(sys.argv[0],'--path',os.environ['HOME']+'/sal/pictures')}, {'HELP': set_menu(help_menu)} ]) def pushkey(treeview, keyval): try: keyval=keyval.keyval except: pass model=treeview.get_model() column=treeview.get_column(2) if keyval == GDK.Escape: gtk.main_quit() if keyval == ord('x'): npath=os.path.join(globals.path,'.x') if os.path.isdir(npath): globals.lastpath=globals.path globals.path=npath set_model(model,ls(globals.path),globals.path) treeview.set_cursor(0,column,0) return True if keyval in [ord('t'),ord('v')]: line=treeview.get_cursor()[0][0]+1 # cursor position try: for i in shlist[line:]: if ((keyval==ord('t')) and (i[:2]=='TV') \ or (keyval==ord('v')) and (i[:2]=='20')): for y in [9,8,7,6,5,4,3,2,1]: treeview.set_cursor(line+y,column,0) if keyval==ord('v'): treeview.set_cursor(line-1,column,0) print line treeview.set_cursor(line,column,1) break line+=1 return True except: print "exception?" def row_activated(treeview, row, column): model=treeview.get_model() iter = model.get_iter(row) #print treeview try: arg = model.d[unicode(model.get_value(iter, COLUMN_SHOW), 'UTF8')] val = arg[0] print arg except KeyError: print "Nokey:", repr([model.get_value(iter, COLUMN_SHOW)]), repr(model.d) arg = [] val = '' except AttributeError: val = arg globals.oldpath=globals.path if globals.menutype==files_menu: if (val=='..'): globals.path = os.path.dirname(globals.path) elif type(val)==type(''): globals.path = os.path.join(globals.path,val) treeview.cursor_pos[globals.oldpath]=row if os.path.islink(globals.path): # symlink, set new path and let to pass below print "LINK:", os.readlink(globals.path) globals.path = os.readlink(globals.path) if val=='VIDEO_TS': globals.command_line.append('dvd://%s' % os.path.dirname(globals.path)) globals.menutype = vlc_menu set_model(model, vlc_menu) elif os.path.isdir(globals.path) or globals.path.endswith('/'): globals.lastpath=globals.path c=set_model(model,ls(globals.path),globals.path) if treeview.cursor_pos.has_key(globals.path) & (val=='..'): treeview.set_cursor(treeview.cursor_pos[globals.path],column,0) else: try: treeview.set_cursor((seen.last_idx(globals.path),),column,0) except ValueError: treeview.set_cursor(c,column,0) else: if re.search('\.(txt|sub|srt|ssa|utf|smi|rt|aqt|jss)$', globals.path,re.IGNORECASE): if '-sub' in globals.command_line: globals.command_line[globals.command_line.index('-sub')+1] \ +=','+globals.path else: globals.command_line.extend(['-vo', 'sdl', '-sub', globals.path]) globals.path=globals.oldpath set_model(model, ls(globals.path), globals.path) if treeview.cursor_pos.has_key(globals.path) & (val=='..'): treeview.set_cursor(treeview.cursor_pos[globals.path],column,0) elif (re.search('.(gif|jpg|png|bmp)$',globals.path,re.IGNORECASE)): cl=['gqview','-f',globals.path] if os.fork()==0: os.execvp(cl[0],cl) else: globals.path=os.path.dirname(globals.oldpath) set_model(model,ls(globals.path),globals.path) if treeview.cursor_pos.has_key(globals.path): treeview.set_cursor(treeview.cursor_pos[globals.path],column,0) else: globals.command_line.append(globals.path) globals.menutype = mplayer_menu print globals.path seen.inc(globals.path) set_model(model, mplayer_menu) elif globals.menutype=='TVPROG': line=treeview.get_cursor()[0][0]+1 # cursor position for i in shlist[:line]: if i[:4]=='TV: ': prg=i for ch,p in prog_progs.items(): #print p,prg if re.search('^TV: '+p,prg,re.IGNORECASE): break rc=os.system("tvtime-command NOOP") if rc>0: os.system("tvtime --fullscreen &") for i in range(50): # 5 seconds rc=os.system("tvtime-command CHANNEL_%d CHANNEL_%d" \ % (int(math.floor(ch/10)),ch%10)) if rc==0: break time.sleep(0.1) elif globals.menutype=="ALIAS": line = treeview.get_cursor()[0][0] # cursor position key = globals.alias_list[line][0] os.execvp( 'mplayer', ['mplayer', '-demuxer', 'lavf', iptv2.FTP_URL % key, iptv2.FTP_URL % (key+1)] ) else: val.main(row,column,treeview,model) treeview.grab_focus() def check_lirc(): dir={'Up':(0,-1),'Down':(0,1), 'Right':(200,0),'Left':(-200,0), 'Page_Up':(0,-10), 'Page_Down':(0,10)} events=pylirc.nextcode() if events: print events treeview=globals.treeview if events: for ev in events: if ev=='Return': model,iter=treeview.get_selection().get_selected() row=model.get_path(iter) column=treeview.get_column(COLUMN_SHOW) treeview.emit('row-activated',row,column) elif ev=='Escape': gtk.main_quit() elif ev in dir.keys(): model=treeview.get_model() x,y=dir[ev] if y!=0: line=treeview.get_cursor()[0][0] if (line+y)<0: treeview.set_cursor(0) elif (line+y)