#!/usr/bin/env python # coding=utf8 import sys, os, traceback from Tkinter import * try: from ttk import * except: pass import tkMessageBox as tkm import tkSimpleDialog as tkd import PIL, StringIO from PIL import ImageTk, Image import requests, urllib2 from ContentSources import ContentSources from sources.SourceBase import stream_type import util class Main(Frame): def __init__(self, sources, cfg_file="streams.cfg"): self.root = Tk() self.root.geometry("1050x600") Frame.__init__(self, self.root) img = PhotoImage(file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'icon.gif')) #img = PhotoImage(file= 'icon.gif') self.root.tk.call('wm', 'iconphoto', self.root._w, img) self.pack(fill=BOTH, expand=1) self.initUI() items = ["item %s" % i for i in range(20)] if sources: self.sources = sources else: self.sources = ContentSources("sources", cfg_file) self.picons_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "picons") self.tmp_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "tmp") if not os.path.exists(self.tmp_path): os.mkdir(self.tmp_path) self.history = [] self.cur_index = 0 self.cur = ("Home", "config::home", "", "PlayStream home") def initUI(self): self.master.title("PlayStream") self.txt1 = Label(self) self.txt1.pack(side=TOP, fill=X, padx=15) self.txt1.configure(font=("Tahoma", 14, "bold")) self.txt1.config(text="") self.txt2 = Label(self) self.txt2.pack(side=TOP, fill=X, padx=15) self.txt2.config(text="") self.txt2.configure(font=("Tahoma", 12)) frame1 = Frame(self) frame1.pack(side=TOP, fill=X, padx=15) scrollbar = Scrollbar(frame1, orient=VERTICAL) self.listbox = Listbox(frame1, width=80, height=30, yscrollcommand=scrollbar.set) scrollbar.config(command=self.listbox.yview) #self.listbox.config(yscrollcommand=scrollbar.set) self.listbox.pack(side=LEFT) scrollbar.pack(side=LEFT, fill=Y) self.listbox.focus_set() self.listbox.bind('<>', lambda evt: self.list_action(evt, "Changed")) self.listbox.bind(' ', lambda evt:self.list_action(None, "Return")) self.listbox.bind(' ', self.list_action) self.pic = Canvas(frame1, width=400, height=250) self.pic.pack(side=TOP, expand=1) frame2 = Frame(frame1, height=250, width=400) frame2.pack(side=TOP) scrollbar2 = Scrollbar(frame2) self.desc = Text(frame2, height=15, width=70, wrap="word", yscrollcommand=scrollbar2.set) #, borderwidth=0, highlightthickness=0) scrollbar2.config(command=self.desc.yview) scrollbar2.pack(side="right", fill="y") self.desc.configure(font=("Tahoma", 10)) self.desc.pack(anchor=N) frame3 = Frame(self, height=40) frame3.pack(side=TOP, fill=X, padx=15) self.b_select = Button(frame3, text="Select", command=lambda :self.list_action(None, "Return"), width=10) self.b_select.pack(side=LEFT, anchor=S) self.b_back = Button(frame3, text="Back", command=lambda :self.list_action(None, "Escape"), width=10) self.b_back.pack(side=LEFT, anchor=S) self.b_options = Button(frame3, text="Options", command=lambda :self.list_action(None, "Options"), width=10) self.b_options.pack(side=LEFT, anchor=S) self.b_config = Button(frame3, text="Config", command=lambda :self.list_action(None, "Config"), width=10) self.b_config.pack(side=LEFT, anchor=S) self.b_exit = Button(frame3, text="Exit", command=self.quit, width=10) self.b_exit.pack(side=LEFT, anchor=S) def list_action(self, evt=None, key=None): cs = int(self.listbox.curselection()[0]) self.cur_index = cs if (not key) and evt: w = evt.widget value = w.get(cs) key = evt.keysym #print 'Key: %s' % (key) data = self.content[cs][1] cur2 = self.content[cs] if key == "Changed": self.show_desc() self.show_pic() elif key == "Return" and data <> "back": if not self.sources.is_video(data): if "{0}" in data: a = tkd.askstring("Search", "Search for") cur2 = (cur2[0],cur2[1].format(a),cur2[2],cur2[3]) self.history.append((self.cur, cs)) self.cur = self.content[cs] self.cur_index = 0 try: self.show_content(cur2) except Exception as e: print unicode(e) traceback.print_exc() tkm.showerror("Error getting content", unicode(e)) prev = self.history.pop() self.cur = prev[0] self.cur_index = prev[1] self.show_content(self.cur, self.cur_index) return else: self.play_video(self.content[cs]) self.listbox.selection_set(self.cur_index) self.listbox.activate(self.cur_index) self.listbox.focus_set() elif key == "BackSpace" or key == "Escape" or (key == "Return" and data == "back"): if self.history: prev = self.history.pop() self.cur = prev[0] self.cur_index = prev[1] self.show_content(self.cur, self.cur_index) elif key == "Right": index2 = self.cur_index + 20 index2 = min(index2, self.listbox.index(END) - 1) self.set_list_item(index2) elif key == "Left": index2 = self.cur_index - 20 index2 = max(index2, 0) self.set_list_item(index2) elif key in ("i", "I"): print "TODO - indo" def set_list_item(self, index): self.cur_index = index self.listbox.selection_clear(0, END) self.listbox.selection_set(index) self.listbox.activate(index) self.listbox.focus_set() self.update() def show_content(self, cur2, cur_index=0): data = cur2[1] self.txt1.config(text=cur2[0]) self.content = self.sources.get_content(data) self.listbox.delete(0, END) for item in self.content: self.listbox.insert(END, item[0]) self.listbox.selection_set(cur_index) self.listbox.activate(cur_index) self.listbox.focus_set() self.show_desc() self.show_pic() def show_desc(self): cs = self.listbox.curselection()[0] self.txt2.config(text=self.content[cs][0]) self.desc.config(state=NORMAL) self.desc.delete("1.0", END) self.desc.insert(END, self.content[cs][3]) self.desc.insert(END, "\n\n"+self.content[cs][1]) self.desc.insert(END, "\n"+self.content[cs][2]) self.desc.config(state=DISABLED) def show_pic(self): cs = self.listbox.curselection()[0] img = self.content[cs][2] self.pic.delete(ALL) if not img: return if not img.startswith("http"): img_path = os.path.join(self.picons_path, img) if img and os.path.exists(img_path): im = Image.open(img_path) else: im = None print "No image found ", img_path elif img: fcache = img.replace(":", "_").replace("/", "-").replace(":", "_") fcache = os.path.join(self.tmp_path, fcache) if os.path.exists(fcache): im = Image.open(fcache) else: r = requests.get(img) if r.status_code == 200: img_data = r.content im = Image.open(StringIO.StringIO(r.content)) with open(fcache, "wb") as f: f.write(r.content) else: im = None if im: im.thumbnail((400, 250)) image = ImageTk.PhotoImage(im) imagesprite = self.pic.create_image(200, 125,image=image) self.pic.image = image def play_video(self, cur2): if self.sources.stream_type(cur2[1]): stream = util.item() stream["url"] = cur2[1] stream["name"] = cur2[0] streams = [stream] else: try: streams = self.sources.get_streams(cur2[1]) except Exception as e: print unicode(e) traceback.print_exc() tkm.showerror("Error getting streams", unicode(e)) return if not streams: tkm.showerror("Error getting streams", "No streams found") return if len(streams) > 1: lst = [] for i,s in enumerate(streams): s = {k:v.decode("utf8") if v and isinstance(v, str) else v for k,v in zip(s.keys(), s.values())} lst.append(("[%s,%s] %s"%(s["lang"],s["quality"],s["name"]),i)) a = ChoiceBox("ChoiceBox test", "Select stream", lst, parent=self, width=40).result stream = streams[a] else: stream = streams[0] stream = util.stream_change(stream) title = stream["name"] if not "nfo" in stream or not stream["nfo"] else util.nfo2title(stream["nfo"]) desc = stream["desc"] if not "nfo" in stream or not stream["nfo"] else util.nfo2desc(stream["nfo"]) img = stream["img"] url = stream["url"] suburl = "" print url if "subs" in stream and stream["subs"]: suburl = stream["subs"][0]["url"] print "\n**Download subtitles %s - %s"%(title,suburl) subs = urllib2.urlopen(suburl).read() if subs: fname0 = re.sub("[/\n\r\t,:\?]","_",title) subext = ".srt" subfile = os.path.join(self.tmp_path,fname0+subext) if ".xml" in suburl: subs = util.ttaf2srt(subs) with open(subfile,"w") as f: f.write(subs) else: print "\n Error downloading subtitle %s"%suburl print "\n**Play stream %s\n%s" % (title, url.encode("utf8")) player(url,title,suburl,stream["headers"]) def start(self): self.root.mainloop() class ChoiceBox(tkd.Dialog): #a = ChoiceBox("ChoiceBox test", "Select stream", items, parent=self).result def __init__(self, title, prompt, items, width=20, height=15, initialvalue=0, parent = None): if not parent: import Tkinter parent = Tkinter._default_root self.prompt = prompt self.items = items self.width = width self.height = height self.result = None self.initialvalue = initialvalue tkd.Dialog.__init__(self, parent, title) def body(self, master): w = Label(self, text=self.prompt, justify=LEFT) w.pack(side=TOP) frame1 = Frame(self) frame1.pack(side=TOP, fill=X, expand=1, padx=5) scrollbar = Scrollbar(frame1, orient=VERTICAL) self.listbox = Listbox(frame1, yscrollcommand=scrollbar.set, width=self.width, height=self.height) scrollbar.config(command=self.listbox.yview) #self.listbox.config(yscrollcommand=scrollbar.set) self.listbox.pack(side=LEFT, fill=BOTH, expand=1) scrollbar.pack(side=LEFT, fill=Y) for item in self.items: self.listbox.insert(END, item) self.listbox.selection_set(self.initialvalue) self.listbox.activate(self.initialvalue) self.listbox.bind(' ', self.list_select) self.listbox.bind(' ', self.list_key) self.update() self.geometry("+%d+%d"%(self.parent.winfo_rootx()+100, self.parent.winfo_rooty()+100 )) return self.listbox def list_key(self, evt): key = evt.keysym #print 'Key %s' % (key) if key == "Return": self.ok() elif key == "Escape": self.cancel() def list_select(self, evt): self.ok() def apply(self): self.result = self.listbox.curselection()[0] class Info(tkd.Dialog): #a = ChoiceBox("ChoiceBox test", "Select stream", items, parent=self).result def __init__(self, title, items, width=20, height=15, initialvalue=0, parent = None): if not parent: import Tkinter parent = Tkinter._default_root self.prompt = prompt self.items = items self.width = width self.height = height self.result = None self.initialvalue = initialvalue tkd.Dialog.__init__(self, parent, title) def body(self, master): w = Label(self, text=self.prompt, justify=LEFT) w.pack(side=TOP) frame1 = Frame(self) frame1.pack(side=TOP, fill=X, expand=1, padx=5) scrollbar = Scrollbar(frame1, orient=VERTICAL) self.listbox = Listbox(frame1, yscrollcommand=scrollbar.set, width=self.width, height=self.height) scrollbar.config(command=self.listbox.yview) #self.listbox.config(yscrollcommand=scrollbar.set) self.listbox.pack(side=LEFT, fill=BOTH, expand=1) scrollbar.pack(side=LEFT, fill=Y) for item in self.items: self.listbox.insert(END, item) self.listbox.selection_set(self.initialvalue) self.listbox.activate(self.initialvalue) self.listbox.bind(' ', self.list_select) self.listbox.bind(' ', self.list_key) self.update() self.geometry("+%d+%d"%(self.parent.winfo_rootx()+100, self.parent.winfo_rooty()+100 )) return self.listbox def list_key(self, evt): key = evt.keysym #print 'Key %s' % (key) if key == "Return": self.ok() elif key == "Escape": self.cancel() def list_select(self, evt): self.ok() def apply(self): self.result = self.listbox.curselection()[0] def run(sources=None, data="config::home", title="Home", cfg_file="streams.cfg"): app = Main(sources, cfg_file=cfg_file) app.show_content((title, data, "", "")) app.start() def run_cli(sources, data="config::home", title="Home", cfg_file="streams.cfg"): #options = sources.options_read("ltc") #print options history = [] cur = ("Home",data,None,None) content = sources.get_content(cur[1]) exit_loop = False while True: print for i,item in enumerate(content): s = "%i: %s - %s %s"%(i,item[0],item[1],item[2]) print s #.encode(sys.stdout.encoding,"replace") while True: a = raw_input("Enter number, (-) for download, q for exit: ") if a in ("q","Q","x","X"): exit_loop = True print "Exiting" break try: n = int(a) break except: print "Not number!" if exit_loop: break download = False if n<0: n = abs(n) download = True cur2 = content[n] data0 = cur2[1].split("::")[1] if "::" in cur2[1] else cur2[1] if not data0: pass elif cur2[1] == "back": cur = history.pop() elif sources.is_video(cur2[1]): if sources.stream_type(cur2[1]): stream = util.item() stream["url"] = cur2[1] stream["name"] = cur2[0] streams = [stream] else: try: if not download: streams = sources.get_streams(cur2[1]) else: stream = util.item() stream["url"] = cur2[1] stream["name"] = cur2[0] stream["url"] = util.streamproxy_encode2(stream["url"]) print stream["url"] streams = [stream] except Exception as e: print unicode(e) traceback.print_exc() streams = [] if streams: if not download: play_video(streams) else: #urlp = util.streamproxy_encode2(streams[0]["url"]) #print urlp #util.player(urlp) #Downloader.download_video(streams) pass else: print "**No stream to play - %s "%( cur2[1]) raw_input("Press any key") #import os #os.system('"c:\Program Files (x86)\VideoLAN\VLC\vlc.exe" "%s"'%cur2[1]) else: if "{0}" in cur2[1]: a = raw_input("Enter value:") cur2 = (cur2[0],cur2[1].format(a),cur2[2],cur2[3]) history.append(cur) cur = cur2 try: content = sources.get_content(cur[1]) except Exception as e: print unicode(e) traceback.print_exc() raw_input("Continue?") def play_video(streams, select=False): if len(streams)>1 and select: for i,s in enumerate(streams): print "%s: [%s,%s,%s] %s"%(i,s["quality"],s["lang"],s["type"],s["name"]) a = raw_input("Select stram to play: ") try: n = int(a) except: n = 0 if n>=len(streams): stream = streams[-1] else: stream = streams[n] else: stream = streams[0] stream = util.stream_change(stream) title = stream["name"] if not "nfo" in stream or not stream["nfo"] else util.nfo2title(stream["nfo"]) desc = stream["desc"] if not "nfo" in stream or not stream["nfo"] else util.nfo2desc(stream["nfo"]) img = stream["img"] url = stream["url"] suburl = "" print url if "subs" in stream and stream["subs"]: suburl = stream["subs"][0]["url"] print "\n**Download subtitles %s - %s"%(title,suburl) subs = urllib2.urlopen(suburl).read() if subs: fname0 = re.sub("[/\n\r\t,:\?]","_",title) subext = ".srt" subfile = os.path.join("",fname0+subext) if ".xml" in suburl: subs = ttaf2srt(subs) with open(subfile,"w") as f: f.write(subs) else: print "\n Error downloading subtitle %s"%suburl print "\n**Play stream %s\n%s" % (title, url.encode("utf8")) return player(url,title,suburl,stream["headers"]) def player(url, title = "", suburl= "",headers={}): from subprocess import call cmd1 = [r"c:\Program Files\VideoLAN\VLC\vlc.exe",url, "--meta-title",title.decode("utf8").encode(sys.getfilesystemencoding()), "--http-user-agent","Enigma2" ] # gst-launch-1.0 -v souphttpsrc ssl-strict=false proxy=127.0.0.1:8888 extra-headers="Origin:adadadasd" location="http://bitdash-a.akamaihd.net/content/sintel/sintel.mpd" ! decodebin! autovideosink cmd2 = [ r"C:\gstreamer\1.0\x86_64\bin\gst-launch-1.0","-v", "playbin", 'uri="%s"'%url, #"souphttpsrc", "ssl-strict=false", #"proxy=127.0.0.1:8888", #'location="%s"'%url, #'!decodebin!autovideosink' ] cmd3 = ["ffplay.exe",url] cmd = cmd3 if url.startswith("https") else cmd2 ret = call(cmd) #if ret: #a = raw_input("*** Error, continue") return if __name__ == "__main__": show_hidden = False data= sys.argv[1] if len(sys.argv) > 1 else "config::home" cfg_file = sys.argv[2] if len(sys.argv) > 2 else "streams.cfg" #sources = ContentSources("sources") sources = None run(sources, data, cfg_file=cfg_file)