12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076 |
- #!/usr/bin/env python
- # coding=utf8
- #
- # This file is part of PlayStream - enigma2 plugin to play video streams from various sources
- # Copyright (c) 2016 ivars777 (ivars777@gmail.com)
- # Distributed under the GNU GPL v3. For full terms see http://www.gnu.org/licenses/gpl-3.0.en.html
- # Used fragments of code from enigma2-plugin-tv3play by Taapat (https://github.com/Taapat/enigma2-plugin-tv3play)
- #
-
- import os,time,sys,os,os.path
- import datetime,re
- import urllib2
-
- from Plugins.Plugin import PluginDescriptor
- from enigma import ePicLoad, eServiceReference, eTimer, getDesktop
- from Screens.Screen import Screen
- from Screens.InfoBarGenerics import InfoBarShowHide
- from Screens.InfoBar import MoviePlayer
- from Screens.MessageBox import MessageBox
- from Screens.LocationBox import LocationBox
- from Screens.ChoiceBox import ChoiceBox
- from Screens.VirtualKeyBoard import VirtualKeyBoard
- #from Screens.InputBox import InputBox
- from Components.AVSwitch import AVSwitch
- from Components.ActionMap import ActionMap, HelpableActionMap
- from Components.Label import Label
- from Components.Input import Input
- from Components.MenuList import MenuList
- from Components.Pixmap import Pixmap
- from Components.Sources.List import List
- from Components.Sources.StaticText import StaticText
- from Components.Button import Button
- from Components.Task import job_manager
- from Components.config import config, ConfigSubsection, ConfigText, ConfigInteger, ConfigLocations, ConfigDirectory, ConfigSet, ConfigYesNo, ConfigSelection, getConfigListEntry, ConfigSelectionNumber, ConfigNumber
- from Components.ConfigList import ConfigListScreen
- from Tools import Notifications
- from Tools.BoundFunction import boundFunction
- from Tools.Directories import resolveFilename, SCOPE_PLUGINS
- from Tools.LoadPixmap import LoadPixmap
- from twisted.web.client import downloadPage,defer,reactor
-
- import ContentSources
- import util
- from VideoDownload import downloadJob, HLSDownloadJob,VideoDownloadList
- #import enigma2_api
-
- e2 = None
- ##########################################################################
- config.plugins.playstream = ConfigSubsection()
- config.plugins.playstream.locations = ConfigLocations(default=["/media/hdd/movie/"])
- config.plugins.playstream.download_dir = ConfigDirectory(default="/media/hdd/movie/")
- config.plugins.playstream.tmp_dir = ConfigDirectory(default="/tmp/playstream/")
- config.plugins.playstream.streamproxy_start = ConfigYesNo(default = True)
- config.plugins.playstream.overwrite_download = ConfigYesNo(default = False)
- #config.plugins.playstream.size = ConfigSelection({"400x240":"400x240","220x132":"220x132","100x60":"100x60"}, default="220x132")
- config.plugins.playstream.clear_tmp = ConfigYesNo(default = True)
-
- class ConfigScreen(ConfigListScreen,Screen):
- skin = """
- <screen position="center,center" size="560,400" title="PlayStream Configuration" >
- <ePixmap name="red" position="0,0" zPosition="2" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
- <ePixmap name="green" position="140,0" zPosition="2" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
- <ePixmap name="yellow" position="280,0" zPosition="2" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
- <ePixmap name="blue" position="420,0" zPosition="2" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
-
- <widget name="key_red" position="0,0" size="140,40" valign="center" halign="center" zPosition="4" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
- <widget name="key_green" position="140,0" size="140,40" valign="center" halign="center" zPosition="4" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
- <widget name="key_yellow" position="280,0" size="140,40" valign="center" halign="center" zPosition="4" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
- <widget name="key_blue" position="420,0" size="140,40" valign="center" halign="center" zPosition="4" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
-
- <widget name="config" position="10,40" size="540,340" scrollbarMode="showOnDemand" />
- </screen>"""
-
- def __init__(self, session, args = 0):
- self.session = session
- #self.setup_title = "Options"
- Screen.__init__(self, session)
- cfg = config.plugins.playstream
- self.list = [
- getConfigListEntry(_("Download folder"), cfg.download_dir),
- getConfigListEntry(_("Overwrite download video"), cfg.overwrite_download),
- getConfigListEntry(_("TMP folder"), cfg.tmp_dir),
- getConfigListEntry(_("Clear tmp folder on exit"), cfg.clear_tmp),
- getConfigListEntry(_("Start playstreamproxy"), cfg.streamproxy_start),
-
- ]
- ConfigListScreen.__init__(self, self.list, session = self.session)
- self["key_red"] = Button(_("Cancel"))
- self["key_green"] = Button(_("Save"))
- self["key_yellow"] = Button("")
- self["key_blue"] = Button("")
- self["setupActions"] = ActionMap(["SetupActions", "ColorActions"],
- {
- "red": self.cancel,
- "green": self.save,
- "save": self.save,
- "cancel": self.cancel,
- "ok": self.ok,
- }, -2)
-
- def getCurrentEntry(self):
- return self["config"].getCurrent()[0]
-
- def getCurrentValue(self):
- return str(self["config"].getCurrent()[1].getText())
-
- def ok(self):
- if self["config"].getCurrent()[1] == config.plugins.playstream.download_dir:
- folder = config.plugins.playstream.download_dir.value
- #self.session.openWithCallback(self.cb_download_dir, LocationBox,"Select Folder")
- self.session.openWithCallback(self.cb_download_dir, LocationBox,"Select download folder","",config.plugins.playstream.download_dir.value,config.plugins.playstream.locations,False,"Select folder",None,True,True)
- elif self["config"].getCurrent()[1] == config.plugins.playstream.tmp_dir:
- self.session.openWithCallback(self.select_tmp_dir, LocationBox,"Select tmp folder","",config.plugins.playstream.download_dir.value,config.plugins.playstream.locations,False,"Select folder",None,True,True)
- else:
- self.save()
-
- def cb_download_dir(self, folder, select=None):
- if not folder:
- return
- print "Folder selected - %s"%folder
- config.plugins.playstream.download_dir.setValue(folder)
- config.plugins.playstream.download_dir.save()
- config.plugins.playstream.locations.save()
- config.save()
-
- def select_tmp_dir(self, folder, select=None):
- if not folder:
- return
- print "Folder selected - %s"%folder
- config.plugins.playstream.tmp_dir.setValue(folder)
- config.plugins.playstream.tmp_dir.save()
- config.plugins.playstream.locations.save()
- config.save()
-
- def save(self):
- print "saving"
- self.saveAll()
- self.close(True,self.session)
-
- def cancel(self):
- #print "cancel"
- self.close(False,self.session)
-
- def make_service(stream):
- url = stream["url"]
- headers = []
- if stream.has_key("headers"):
- for h in stream["headers"]:
- headers.append("%s=%s"%(h,stream["headers"][h]))
- if headers:
- headers ="&".join(headers)
- url = url+"#"+headers
- print "stream_url with headers=",headers
- url = url.encode("utf8")
- if "|" in url:
- url = url.replace("|","#")
- service_type = 4097
- if re.search("\.ts$",url.split("?")[0],re.IGNORECASE):
- service_type = 1
- if "resolver" in stream and stream["resolver"] in ("hqq","viaplay","filmas"):
- url = util.streamproxy_encode(stream["url"], stream["headers"])
- #if os.path.exists("/usr/bin/exteplayer3"): # problem playing hqq streams with gstreamer, use exteplayer3
- #service_type = 5002
- print "service_type=",service_type
- print "stream_url=",url
- service = eServiceReference(service_type, 0, url)
- service.setName( stream["name"])
- return service
-
- #####################################################################################################################
- class PSSubs(Screen):
-
- def __init__(self, session):
- desktopWidth = getDesktop(0).size().width()
- desktopHeight = getDesktop(0).size().height()
- offset = 20
- screenWidth = desktopWidth - (2 * offset)
- widgetWidth = screenWidth / 2 - 5
- self.skin = """
- <screen position="%d,%d" size="%d,140" zPosition="2" backgroundColor="transparent" flags="wfNoBorder">
- <widget name="subtitle" position="0,0" size="%d,140" valign="center" halign="center" font="Regular;36" transparent="1" foregroundColor="white" shadowColor="#40101010" shadowOffset="2,2" />
- </screen>""" % (offset, desktopHeight-offset-140, screenWidth, screenWidth)
- self['subtitle'] = Label()
- Screen.__init__(self, session)
-
-
- #####################################################################################################################
- class PSPlayer(MoviePlayer):
- def __init__(self, session, streams):
- print "PSPlayer init: ",streams
- self.session = session
- self.streams = streams
- self.cur_stream = self.streams[0] # TODO
- self.selected = 0
- self.resume_pos = 0
- service = make_service(self.cur_stream)
-
- MoviePlayer.__init__(self, session, service)
- self.skinName = "MoviePlayer"
- self["actions"] = ActionMap(["MediaPlayerActions","MediaPlayerSeekActions","MoviePlayerActions","InfobarSeekActions","MovieSelectionActions","ColorActions"], {
- "stop":self.leavePlayer,
- "leavePlayer":self.leavePlayer,
-
- "audio":self.select_stream,
- "AudioSelection":self.select_stream,
- "green":self.select_stream,
-
- "subtitles":self.select_captions,
- "text":self.select_captions,
- "yellow_key":self.select_captions,
- "yellow":self.select_captions,
- "pauseServiceYellow":self.select_captions,
- "pause":self.select_captions,
-
- "showEventInfo":self.service_info,
- "info":self.service_info
- })
- self.stimer = eTimer()
- if "callback" in dir(self.stimer):
- self.stimer.callback.append(self.update_subtitles)
- elif "timeout":
- self.stimer_conn = self.stimer.timeout.connect(self.update_subtitles)
- else:
- self.stimer = None
- self.stimer_step = 500
- if self.cur_stream["subs"]:
- self.subs = self.cur_stream["subs"]
- self.cur_subs = 0 # TODO - no konfiguracijas
- self.svisible = True # TODO - no konfiguracija
- self.sind = 0
- self.get_subs_current()
- else:
- self.subs = []
- self.cur_subs = 0
- self.svisible = False
- self.subtitle_window = self.session.instantiateDialog (PSSubs)
- self.onLayoutFinish.append(self.start_subtitles_timer)
-
- def start_subtitles_timer(self):
- if self.stimer:
- self.subtitle_window.show()
- print "start_subtitles_timer"
- self.stimer.start(self.stimer_step)
-
- def get_sub_pts(self,pts):
- sc = self.get_sub_ind(self.sind) # current subbtitle
- while True:
- if not sc:
- return "Error - no subs find" # TODO
- if pts > sc["end"]:
- self.sind += 1
- sc = self.get_sub_ind(self.sind)
- continue
- else:
- if pts <sc["begin"]:
- return " "
- else:
- txt = sc["text"] if sc["text"] else " "
- return txt
-
- def get_sub_ind(self,ind):
- subs_object = self.get_subs_current() # current subs object
- if subs_object:
- return subs_object.subs[ind] if ind<len(subs_object.subs) else None
- else:
- return None
-
- def get_subs_current(self):
- "Return current sub_object"
- if not "subs" in self.subs[self.cur_subs]:
- print "===== Captions to download", self.subs[self.cur_subs]["url"]
- subs_object = util.Captions(self.subs[self.cur_subs]["url"])
- print len(subs_object.subs), "items"
- self.subs[self.cur_subs]["subs"] = subs_object
- if not subs_object:
- return None
- else:
- return subs_object
- else:
- return self.subs[self.cur_subs]["subs"]
-
- def update_subtitles(self):
- if not self.shown and self.svisible:
- seek = self.getSeek()
- pos = seek.getPlayPosition()
- pts = pos[1]/90
- txt0 = "%d:%02d (%i)" % (pts/60/1000, (pts/1000)%60, pts)
- #print "Update_subtitles", txt0
- if not self.subtitle_window.shown:
- self.subtitle_window.show()
- if not self.subs:
- return
- txt = self.get_sub_pts(pts)
- #print "Show subtitle",txt
- #txt = txt0+": "+ txt
- self.subtitle_window["subtitle"].setText(txt)
- elif self.shown and self.svisible:
- if self.subtitle_window.shown:
- self.subtitle_window.hide()
- elif not self.svisible:
- if self.subtitle_window.shown:
- self.subtitle_window.hide()
-
- # struct SubtitleTrack
- # int type;
- # int pid;
- # int page_number;
- # int magazine_number;
- # std::string language_code;
- #selectedSubtitle = ???
- #self.enableSubtitle(selectedSubtitle)
-
- def start_subtitles_timer(self):
- self.stimer.start(self.stimer_step)
-
- def play_service(self,service):
- self.movieSelected(service)
-
- #def doShow(self):
- #self.svisible = False
- #InfoBarShowHide.doShow(self)
-
- #def doHide(self):
- #self.svisible = True
- #InfoBarShowHide.doHide(self)
-
- def service_info(self):
- print "########[MoviePlayer] service_info"
- text = "%s\n%s %s\n%s"%(self.cur_stream["name"],self.cur_stream["lang"],self.cur_stream["quality"],self.cur_stream["desc"])
- text = text.encode("utf8")
- #print text
- mtype = MessageBox.TYPE_INFO
- Notifications.AddPopup(text = text, type=mtype, timeout = 10)
- #Notifications.MessageBox(self.session, text=text, type=MessageBox.TYPE_INFO, timeout=10,
- #close_on_any_key=True,
- #default=True,
- #enable_input=True,
- #msgBoxID=None,
- #picon=False,
- #simple=False,
- #wizard=False,
- #list=None,
- #skin_name=None,
- #timeout_default=None)
- #return True
-
- def select_stream(self):
- print "########[MoviePlayer] select_stream"
- lst = []
- title = "Select stream"
- for i,s in enumerate(self.streams):
- lst.append(("[%s,%s] %s"%(s["lang"],s["quality"],s["name"]),i))
- self.session.openWithCallback(self.cb_select_stream, ChoiceBox, title = title, list = lst,selection = self.selected)
-
- def cb_select_stream(self,answer):
- #print "item_menu_selected",answer
- if not answer:
- return
- self.selected = answer[1]
- service = make_service(self.streams[self.selected])
- self.resume_pos = self.getSeek().getPlayPosition()[1]
- self.play_service(service)
-
- def serviceStarted(self):
- print "serviceStarted"
- if not self.resume_pos:
- self.resume_pos = 0
- print "doSeek",self.resume_pos
- #self.doSeek(self.resume_pos)
-
-
- def select_captions(self):
- print "########[MoviePlayer] select_caption"
- lst = []
- title = "Select subtitles"
- for i,s in enumerate(self.subs):
- lst.append((("%s - %s"%(s["lang"],s["name"])).encode("utf8"),i))
- if self.svisible:
- selection = self.cur_subs
- else:
- selection = len(lst)
- lst.append(("No captions",-1))
- self.session.openWithCallback(self.cb_select_captions, ChoiceBox, title = title, list = lst,selection = selection)
-
- def cb_select_captions(self,answer):
- #print "item_menu_selected",answer
- if not answer:
- return
- if answer[1] == -1:
- self.svisible = False
- else:
- self.cur_subs = answer[1]
- self.svisible = True
-
- def leavePlayer(self):
- self.close()
- #self.session.openWithCallback(self.leavePlayerConfirmed, MessageBox, _("Stop playing?"))
-
- def leavePlayerConfirmed(self, answer):
- if answer:
- self.close()
-
- def doEofInternal(self, playing):
- self.close()
-
- #def getPluginList(self):
- #from Components.PluginComponent import plugins
- #list = []
- #for p in plugins.getPlugins(where = PluginDescriptor.WHERE_EXTENSIONSMENU):
- #if p.name != _("TV Play"):
- #list.append(((boundFunction(self.getPluginName, p.name),
- #boundFunction(self.runPlugin, p), lambda: True), None))
- #return list
-
- #def showMovies(self):
- #pass
-
-
- #####################################################################################################################
- class MainScreen(Screen):
- skin = """
- <screen position="center,center" size="1015,570" title="Play Stream">
- <eLabel position="5,0" size="1000,2" backgroundColor="#aaaaaa" />
- <widget name="title" position="10,2" size="1000,38" font="Regular;30" />
- <widget source="list" render="Listbox" position="10,55" size="580,470" \
- scrollbarMode="showOnDemand" >
- <convert type="TemplatedMultiContent" >
- {
- "template": [MultiContentEntryText(pos=(10, 1), size=(560, 30), \
- font=0, flags=RT_HALIGN_LEFT, text=0)],
- "fonts": [gFont("Regular", 20)],
- "itemHeight": 30
- }
- </convert>
- </widget>
- <widget name="pic" position="646,55" size="327,250" alphatest="on" />
- <widget name="cur" position="610,300" size="400,250" halign="center" font="Regular;20"/>
-
- <ePixmap name="exit" position="10,540" zPosition="2" size="140,40" pixmap="skin_default/buttons/key_exit.png" transparent="1" alphatest="on" />
- <widget name="key_exit" position="10,535" size="140,40" valign="center" halign="center" zPosition="4" backgroundColor="blue" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
- <ePixmap name="red" position="150,535" zPosition="2" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
- <widget name="key_red" position="150,535" size="140,40" valign="center" halign="center" zPosition="4" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
- <ePixmap name="green" position="290,535" zPosition="2" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
- <widget name="key_green" position="290,535" size="140,40" valign="center" halign="center" zPosition="4" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
- <ePixmap name="yellow" position="430,535" zPosition="2" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
- <widget name="key_yellow" position="430,535" size="140,40" valign="center" halign="center" zPosition="4" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
- <ePixmap name="blue" position="570,535" zPosition="2" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
- <widget name="key_blue" position="570,535" size="140,40" valign="center" halign="center" zPosition="4" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
- <ePixmap name="menu" position="750,540" zPosition="2" size="140,40" pixmap="skin_default/buttons/key_menu.png" transparent="1" alphatest="on" />
- <widget name="key_menu" position="750,535" size="140,40" valign="center" halign="center" zPosition="4" backgroundColor="blue" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
-
- </screen>"""
-
- def __init__(self, session):
- Screen.__init__(self, session)
- #self.setTitle2("Home")
- self.session = session
- self.e2 = None
- self["key_red"] = Button(_("Exit"))
- self["key_green"] = Button(_("Select"))
- self["key_yellow"] = Button(_("Options"))
- self["key_blue"] = Button(_("Config"))
- self["key_menu"] = Button("Menu")
- self["key_exit"] = Button("Back")
-
- self["actions"] = ActionMap(["OkCancelActions", "ColorActions","MenuActions", "NumberActions"],
- {
- #"cancel": self.Cancel,
- "ok": self.Ok,
- "green": self.Ok,
- "red": self.Cancel,
- "yellow": self.options_screen,
- "blue": self.config_screen,
- "menu": self.item_menu,
- "cancel": self.Back,
- })
- self["list"] = List([])
- self["list"].onSelectionChanged.append(self.SelectionChanged)
- self["pic"] = Pixmap()
- self["cur"] = Label()
- self["title"] = Label()
- self.downloading = 0
- self.activeDownloads = 0
- if not os.path.exists(config.plugins.playstream.tmp_dir.value):
- os.mkdir(config.plugins.playstream.tmp_dir.value)
- self.onLayoutFinish.append(self.LayoutFinish)
-
- def LayoutFinish(self):
- self.cur_directory = os.path.dirname(os.path.realpath(__file__))
- self.defimage = LoadPixmap(os.path.join(self.cur_directory,"PlayStream.png"))
- #self.defimage = None
- #sc = AVSwitch().getFramebufferScale()
- #self.defimage0 = ePicLoad()
- #self.defimage0.PictureData.get().append(boundFunction(self.FinishDecodeDef, os.path.join(self.cur_directory,"PlayStream.png")))
- #self.defimage0.setPara((self["pic"].instance.size().width(),self["pic"].instance.size().height(),sc[0], sc[1], False, 0, "#00000000"))
- #self.defimage0.startDecode("default")
-
- self.activeDownloads = 0
- self.images = {}
- self.images_url = {}
- self.picloads = {}
- self.history = []
-
- reload(ContentSources)
- self.sources = ContentSources.ContentSources(os.path.join(self.cur_directory,"sources"))
- self.config = self.sources.plugins["config"]
- self.cur_menu = ("Home","config::home","","Sākums") #
- self.content = self.sources.get_content(self.cur_menu[1])
- #print self.content
- self["list"].setList(self.content)
- self["cur"].setText(self.content[0][3])
- self.setTitle2(self.cur_menu[0])
- self.ShowPic(self.content[0][2])
-
-
- def SelectionChanged(self):
- current = self["list"].getCurrent()
- print "[PlayStream] SelectionChanged: current=",current
- if not current: return
- self["cur"].setText(current[3]) if current[3] else self["cur"].setText("")
- if current[2]:
- self.ShowPic(current[2])
- else:
- self.ShowDefPic()
-
- def setTitle2(self,title):
- #print self.keys()
- self["title"].setText(title)
-
- def ShowDefPic(self):
- if self.defimage:
- self["pic"].instance.setPixmap(self.defimage)
-
- def ShowPic(self,image_url):
- if image_url == "default":
- self.ShowDefPic()
- return
- elif self.images.has_key(image_url):
- if self.images[image_url] in (-1,-2):
- return
- elif self.images[image_url] == -3:
- self.ShowDefPic()
- return
- else:
- self["pic"].instance.setPixmap(self.images[image_url])
- else:
- if image_url.startswith("http"):
- fname = image_url.replace(":","-").replace("/","_")
- image_path = os.path.join(config.plugins.playstream.tmp_dir.value, fname)
- self.download_image(image_path, image_url)
- else: # local file
- image_path = os.path.join(self.cur_directory,image_url)
- self.start_decode(image_path,image_url)
-
- def start_decode(self,image_path,image_url):
- self.images[image_url] = -2
- self.images_url[image_path] = image_url
- sc = AVSwitch().getFramebufferScale()
- if not self.picloads.has_key(image_path):
- self.picloads[image_path] = ePicLoad()
- self.picloads[image_path].PictureData.get().append(boundFunction(self.FinishDecode, image_path))
- self.picloads[image_path].setPara((self["pic"].instance.size().width(),
- self["pic"].instance.size().height(),
- sc[0], sc[1], True, 0, "#00000000"))
- #print image_path,image_url
- self.picloads[image_path].startDecode(image_path)
-
- def FinishDecode(self, image_path,picInfo = None):
- image_url = self.images_url[image_path]
- del self.images_url[image_path] #III
- self.images[image_url] = self.picloads[image_path].getData()
- self["pic"].instance.setPixmap(self.images[image_url])
- del self.picloads[image_path]
- if len(self.images)>30:
- del self.images[self.images.keys()[0]]
- # self.images.pop()
-
- #def FinishDecodeDef(self, image_path,picInfo = None):
- # self.defimage = self.defimage0.getData()
- # del self.defimage0
- # self["pic"].instance.setPixmap(self.defimage)
-
- def download_image(self,image_path,image_url):
- #print "Image download started",self.downloading,image_path,image_url
- self.downloading += 1
- self.images[image_url] = -1
- downloadPage(image_url, image_path).addCallback(boundFunction(self.downloadFinished, image_path,image_url)).addErrback(boundFunction(self.downloadFailed, image_path,image_url))
-
- def downloadFinished(self, image_path, image_url, result):
- self.downloading -= 1
- #print "[ Play] Image downloaded finished ",self.downloading,image_path, image_url,result
- self.start_decode(image_path,image_url)
-
- def downloadFailed(self, image_path, image_url,result):
- self.downloading -= 1
- print "[TV Play] Image downloaded failed ",self.downloading,image_path, image_url,result
- self.images[image_url] = -3
-
-
- def Ok(self):
- current = self["list"].getCurrent()
- self.current = current
- index = self["list"].getIndex()
- self.index = index
- print "[PlayStream] - menu selected ", current
- data = current[1].split("::")[1] if "::" in current[1] else current[1]
- if not data:
- return
-
- elif self.sources.is_video(current[1]):
- if self.sources.stream_type(current[1]):
- stream = util.item()
- stream["url"] = current[1]
- stream["name"] = current[0]
- streams = [stream]
- else:
- try:
- streams = self.sources.get_streams(current[1])
- except Exception,e:
- print str(e)
- self.session. open(MessageBox, "Error - %s"%str(e) , MessageBox.TYPE_INFO)
- return
- if streams:
- #print streams
- for s in streams:
- if not s["name"]: s["name"] = current[0]
- if not s["img"]: s["img"] = current[2]
- if not s["desc"]: s["desc"] = current[3]
- try:
- self.session.open(PSPlayer, streams)
- except Exception as e:
- self.msg("Error launching player - " + str(e))
- return
- else:
- self.msg("No stream found - %s"%(self.current[1]))
- return
-
- elif current[1] == "back":
- cur_menu_old = self.cur_menu
- self.cur_menu = self.history.pop()
- new_content = self.sources.get_content(self.cur_menu[1])
- try:
- index = zip(*new_content)[1].index(cur_menu_old[1])
- except:
- index = 0
- self.setTitle2(self.cur_menu[0])
- self.show_content(new_content,index)
-
- else:
- print "selected=",current
- if "{0}" in current[1]:
- self.session.openWithCallback(self.cb_input,VirtualKeyBoard, title="Enter value", text="")
- #a = raw_input("Enter value:")
- #a = "big bang"
- #current = (current[0],current[1].format(a),current[2],current[3])
- #self.get_content(current)
- else:
- self.get_content(current)
-
-
- def cb_input(self,value):
- if not value:
- return
- current = self.current
- current = (current[0],current[1].format(value),current[2],current[3])
- self.get_content(current)
-
- def get_content(self,current):
- self.history.append(self.cur_menu)
- self.cur_menu = current
- try:
- new_content = self.sources.get_content(self.cur_menu[1])
- except Exception,e:
- self.cur_menu = self.history.pop()
- self.session. open(MessageBox, "Error - %s"%str(e) , MessageBox.TYPE_INFO)
- return
- self.setTitle2(self.cur_menu[0])
- self.show_content(new_content)
-
- def Back(self):
- self["list"].setIndex(0)
- self.Ok()
-
- def show_content(self,content,index=0):
- self["list"].setList(content)
- self["list"].setIndex(index)
- self.SelectionChanged()
-
- def Cancel(self):
- print "Exiting PlayStream"
- if config.plugins.playstream.clear_tmp.value and os.path.exists(config.plugins.playstream.tmp_dir.value):
- for name in os.listdir(config.plugins.playstream.tmp_dir.value):
- #print "remove "+os.path.join(config.plugins.playstream.tmp_dir.value, name)
- os.remove(os.path.join(config.plugins.playstream.tmp_dir.value, name))
- #os.rmdir(config.plugins.playstream.tmp_dir.value)
- self.close()
-
-
- def item_menu(self):
- print "\n[PlayStream] options\n"
- self.current = self["list"].getCurrent()
- self.index = self["list"].getIndex()
- #self.session. open(MessageBox, "Item options - %s"%current[0] , MessageBox.TYPE_INFO)
- #args=[current,self.cur_menu]
- #self.session.open(ItemMenuScreen,current,index,self)
- lst = [
- ("Aditional information","info","Display additional information about item"),
- ("Add to bouquet","bouquet","Add current item to Enigma2 bouquet"),
- ("Add to favorites","favorites","Add current item to PlayStrem favorites"),
- ("Show active downloads","download_list","Show active downloads list"),
- ("Set download folder","download_folder","Set download folder")
- ]
- if self.sources.is_video(self.current[1]):
- lst.extend([
- ("Download video to default folder","download","Download video to default folder"),
- ("Download video, ask folder","download2","Download video, ask download folder"),
- ("Download video to subfolder, ask parent folder","download3","Download video to subfolder, ask download folder"),
-
- ])
- else:
- lst.extend([
- ("Download list to default folder","download","Download videos in list (if any)"),
- ("Download list, ask folder","download2","Download videos in list (if any), ask download folder"),
- ])
- if "config::" in self.cur_menu[1]:
- lst.extend([
- ("Rename item","rename","Rename list item"),
- ("Move item","move","Move list item"),
- ("Delete item","delete","Delete list item"),
- ("Add submenu","add_list","Add submenu before selected item"),
- ])
- title = self.current[0]
- self.session.openWithCallback(self.cb_item_menu, ChoiceBox, title = title, list = lst) #TODO
-
- def cb_item_menu(self,answer):
- #print "item_menu_selected",answer
- if not answer:
- return
- self.answer = answer[1]
-
- if answer[1] == "info":
- self.session.open(MessageBox, "Not yet implemented!", MessageBox.TYPE_INFO)
- pass # TODO parada papildus info
-
- elif answer[1] == "bouquet":
- #if not e2:
- #e2 = enigma2_api.DBServices()
- #print "load_buuquets - ",e2._load_bouquets()
- self.session.open(MessageBox, "Not yet implemented!", MessageBox.TYPE_INFO)
-
- elif answer[1] == "favorites":
- lists = self.config.get_lists()
- lists2 = [(self.config.get_title(l),l) for l in lists]
- print lists2
- self.session.openWithCallback(self.cb_favorites, ChoiceBox, title="Selected menu item will be added",list = lists2)
-
- elif answer[1] in ("download2","download3"): # ask download folder before
- self.session.openWithCallback(self.download_prepare, LocationBox,"Select download folder","",config.plugins.playstream.download_dir.value,config.plugins.playstream.locations,False,"Select folder",None,True,True)
-
- elif answer[1] == 'download':
- self.download_prepare(config.plugins.playstream.download_dir.value)
-
- elif answer[1] == 'download_list':
- self.download_list()
-
- elif answer[1] == 'download_folder':
- #downloadDir = "/media/hdd/movie" #config.plugins.playstream.downloadDir.value TODO
- self.session.openWithCallback(self.cb_download_dir, LocationBox,"Select download folder","",config.plugins.playstream.download_dir.value,config.plugins.playstream.locations,False,"Select folder",None,True,True)
-
- elif answer[1] == "delete":
- lst = self.cur_menu[1].replace("config::","")
- #print lst
- self.config.del_item(lst,self.index)
- self.config.write_streams()
- txt = "'%s' deleted from favourite stream list '%s'"%(self.current[0],lst)
- self.session.open(MessageBox, txt, MessageBox.TYPE_INFO,timeout=5)
-
- elif answer[1] == "rename":
- #name2 = "Renamed"
- self.session.openWithCallback(self.cb_rename,VirtualKeyBoard, title="Enter new item name", text=self.current[0])
-
- elif answer[1] == "add_list":
- self.session.open(MessageBox, "Not yet implemented!", MessageBox.TYPE_INFO,timeout=5)
- pass #TODO
- return
-
- def download_prepare(self, download_dir=""):
- current = self.current
- if not download_dir:
- return
- #download_dir = config.plugins.playstream.download_dir.value
- title = re.sub("\[.+?\]","", util.make_fname(current[0])).strip()
- download_dir2 = os.path.join(download_dir, title)
- if not self.sources.is_video(current[1]):
- #self.msg("Can not download listst (yet) - %s"%(current[1]))
- n = 0
- for current2 in self.sources.get_content(current[1]):
- if self.sources.is_video(current2[1]):
- n += 1
- self.download_video(current2,download_dir2)
- if n>0:
- self.msg("%s videos download started to %s"%(n,download_dir2))
- else:
- self.msg("No videos to download")
- else:
- if self.answer == "download":
- download_dir2 = download_dir
- if self.download_video(current,download_dir2):
- self.msg("Video download started to %s"%download_dir2)
-
- def cb_download_dir(self, downloadDir, select=None):
- if not downloadDir:
- return
- print "Folder selected - %s"%downloadDir
- config.plugins.playstream.download_dir.setValue(downloadDir)
- config.plugins.playstream.download_dir.save()
- config.plugins.playstream.locations.save()
- config.save()
-
- def download_list(self):
- self.session.open(VideoDownloadList)
-
- def download_video(self,current, download_dir=""):
- if self.sources.stream_type(current[1]):
- stream = util.item()
- stream["url"] = current[1]
- stream["name"] = current[0]
- streams = [stream]
- else:
- try:
- streams = self.sources.get_streams(current[1])
- except Exception,e:
- print "Error - %s"%str(e)
- self.session. open(MessageBox, "Error - %s"%str(e) , MessageBox.TYPE_INFO)
- return
- if not streams:
- self.msg("No stream found to download - %s"%(self.current[1]))
- return
- for s in streams:
- if not s["name"]: s["name"] = current[0]
- if not s["img"]: s["img"] = current[2]
- if not s["desc"]: s["desc"] = current[3]
-
- if len(streams)>1:
- stream = streams[0] # TODO iespeja izvelēties strīmu, ja to ir vairāki
- else:
- stream = streams[0]
- stream = util.stream_change(stream)
- return self.download_stream(stream, download_dir)
-
- def download_stream(self,stream,download_dir=""):
- print "download stream",stream
- #self.msg("Start downloading..")
- self.stream = stream
- stream_type = self.stream["type"] #self.sources.stream_type(stream["url"])
- if not stream_type: #
- print "Not supported stream type found to download - %s"%(self.current[1])
- self.msg("Not supported stream type found to download - %s"%(self.current[1]))
- return
-
- title = self.stream["name"].strip()
- url = self.stream["url"]
- stream_type = self.stream["type"] #self.sources.stream_type(stream["url"])
- downloadDir = config.plugins.playstream.download_dir.value if not download_dir else download_dir
- if not os.path.exists(downloadDir):
- try:
- os.mkdir(downloadDir)
- except Exception as e:
- print 'Error creating download directory "%s"!\nPlease specify in the settings existing directory\n%s'%(downloadDir,str(e))
- self.msg('Error creating download directory "%s"!\nPlease specify in the settings existing directory\n%s'%(downloadDir,str(e)))
- return
- fname0 = util.make_fname(title)
- fname = fname0 +".mp4"
- outputfile = os.path.join(downloadDir, fname)
- #print "Trying to download - ", current
- if self.stream["img"]:
- try:
- thumb = urllib2.urlopen(stream["img"]).read()
- except:
- thumb = ""
- if thumb:
- imgext = ".jpg"
- m = re.search("(\.\w{3})$",stream["img"])
- if m:
- imgext = m.group(1)
- imgfile = os.path.join(downloadDir,fname0+imgext)
- with open(imgfile,"wb") as f:
- f.write(thumb)
- if self.stream["subs"]:
- suburl = self.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(downloadDir,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
- if "nfo" in self.stream and self.stream["nfo"]:
- nfofile = subfile = os.path.join(downloadDir,fname0+".nfo")
- with open(nfofile,"w") as f:
- nfo_type,nfo = next(self.stream["nfo"].iteritems())
- f.write("<%s>\n"%nfo_type.encode("utf8"))
- for k,v in nfo.iteritems():
- if isinstance(v,unicode): v = v.encode("utf8")
- f.write(" <%s>%s</%s>\n"%(k.encode("utf8"), v, k.encode("utf8")))
- f.write("</%s>\n"%nfo_type.encode("utf8"))
- overwrite = config.plugins.playstream.overwrite_download.value
- if not overwrite and os.path.exists(outputfile):
- self.msg( _('Sorry, this file already exists:\n%s') % outputfile)
- return False
- #os.remove(outputfile)
-
- if stream_type in ("http","https"):
- print "\n**Download %s - %s"%(title,url)
- #reload(downloadJob)
- job_manager.AddJob(downloadJob(url, outputfile, title[:20], self.video_download_stop))
- self.activeDownloads += 1
- #self.msg(_('Video download started!'))
- return True
-
- elif stream_type == "hls":
- #self.msg("HLS stream download not yet implemented!")
- print "\n**Download %s - %s"%(title,url)
- #reload(HLSDownloadJob)
- print "HLSDownload", url,outputfile
- job_manager.AddJob(HLSDownloadJob(url, outputfile, title[:20], self.video_download_stop))
- self.activeDownloads += 1
- #self.msg(_('Video download started!'))
- return True
-
- elif stream_type == "rstp":
- self.msg("RSTP stream download not yet implemented!")
- return False
- else:
- self.msg("Unkown stream type!")
- return False
-
-
- def cb_rename(self,value):
- if not value:
- return
- lst = self.cur_menu[1].replace("config::","")
- pos = self.index
- print value
- item2 = list(self.current)
- item2[0]=value
- item2 = tuple(item2)
- self.config.replace_item(lst,item2,pos)
- self.config.write_streams()
- txt = "'%s' renamed to '%s'"%(self.current[0],value)
- self.session.open(MessageBox, txt, MessageBox.TYPE_INFO,timeout=5)
-
- def cb_favorites(self,answer):
- print "cb_favorites",answer,self.current
- if not answer:
- return
- value = answer[1]
- self.config.add_item(value,self.current)
- self.config.write_streams()
- txt = "'%s' added to favourite stream list '%s'"%(self.current[0],value)
- self.session.open(MessageBox, txt, MessageBox.TYPE_INFO,timeout=3)
- #self.session.openWithCallback(self.callMyMsg, MessageBox, _("Do you want to exit the plugin?"), MessageBox.TYPE_INFO)
-
- def config_screen(self):
- self.session.open(ConfigScreen,self)
-
- def options_screen(self):
- source = self.cur_menu[1].split("::")[0]
- options = self.sources.options_read(source)
- print source
- if not options:
- self.session. open(MessageBox, "No options available for source %s (%s)"%(self.cur_menu[0],source) , MessageBox.TYPE_INFO)
- else:
- self.session.open(OptionsScreen,self)
-
- def video_download_stop(self,title):
- #self.activeDownloads -= 1
- #self.msg("Download '%s'finished!"%title)
- print "video_download_stop ", title
-
- def msg2(self,msg,timeout=10,mtype = None):
- mtype=mtype if mtype else MessageBox.TYPE_INFO
- Notifications.AddPopup(text = msg, type=mtype, timeout=timeout)
-
- def msg(self,msg,timeout=10):
- self.session.open(MessageBox, msg, MessageBox.TYPE_INFO, timeout)
- ##########################################################################
- from Components.config import config, ConfigSubsection, ConfigYesNo,\
- getConfigListEntry, ConfigSelection, ConfigNumber, ConfigDirectory,ConfigText, ConfigSubDict
- from Components.ConfigList import ConfigListScreen
- #from Screens.LocationBox import LocationBox
-
- #config.plugins.playstream = ConfigSubDict()
-
- class OptionsScreen(ConfigListScreen,Screen):
- skin = """
- <screen position="center,center" size="560,400" >
- <ePixmap name="red" position="0,0" zPosition="2" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
- <widget name="key_red" position="0,0" size="140,40" valign="center" halign="center" zPosition="4" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
- <ePixmap name="green" position="140,0" zPosition="2" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
- <widget name="key_green" position="140,0" size="140,40" valign="center" halign="center" zPosition="4" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
- <ePixmap name="yellow" position="280,0" zPosition="2" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
- <widget name="key_yellow" position="280,0" size="140,40" valign="center" halign="center" zPosition="4" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
- <ePixmap name="blue" position="420,0" zPosition="2" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
- <widget name="key_blue" position="420,0" size="140,40" valign="center" halign="center" zPosition="4" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
-
- <widget name="config" position="10,40" size="540,340" scrollbarMode="showOnDemand" />
- </screen>"""
-
- def __init__(self, session,*args):
- self.session = session
- Screen.__init__(self, session)
- self.main = args[0]
- self.setTitle(self.main.cur_menu[0]+" options")
- self.source = self.main.cur_menu[1].split("::")[0]
- self.cfg = ConfigSubDict() #config.plugins.playstream
- self.list = []
- self.options = self.main.sources.options_read(self.source)
- if not self.options:
- #self.session. open(MessageBox, "No options available for source %s (%s)"%(self.main.cur_menu[0],self.source) , MessageBox.TYPE_INFO)
- self.close(False,self.session)
- for k in self.options:
- self.cfg[k]=ConfigText(default=self.options[k],fixed_size=False)
- self.list.append(getConfigListEntry(k, self.cfg[k]))
- ConfigListScreen.__init__(self, self.list, session = self.session)
-
- self["key_red"] = Button(_("Cancel"))
- self["key_green"] = Button("Save")
- self["key_yellow"] = Button("")
- self["key_blue"] = Button("")
- self["setupActions"] = ActionMap(["SetupActions", "ColorActions"],
- {
- "red": self.cancel,
- "green": self.save,
- "save": self.save,
- "cancel": self.cancel,
- "ok": self.ok,
- }, -2)
-
- def getCurrentEntry(self):
- return self["config"].getCurrent()[0]
-
- def getCurrentValue(self):
- return str(self["config"].getCurrent()[1].getText())
-
- def ok(self):
- self.save()
- #if self["config"].getCurrent()[1] == config.plugins.getpicons.folder:
- #folder = config.plugins.getpicons.folder.value
- #self.session.openWithCallback(self.change_dir, LocationBox,"Select Folder")
- #else:
-
-
- #def change_dir(self, folder, select=None):
- #if folder:
- ##print "change_dir to %s"%folder
- #config.plugins.getpicons.folder.value = folder
-
- def save(self):
- print "saving"
- #self.saveAll()
- for k in self.options.keys():
- self.options[k]=self.cfg[k].value
- print "%s=%s"%(k,self.cfg[k].value)
- self.main.sources.options_write(self.source,self.options)
- self.close(True,self.session)
-
- def cancel(self):
- print "cancel"
- self.close(False,self.session)
|