Enigma2 plugin to to play various online streams (mostly Latvian).

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. #!/usr/bin/env python
  2. # coding=utf8
  3. #
  4. #
  5. # This file is part of PlayStream - enigma2 plugin to play video streams from various sources
  6. # Copyright (c) 2016 ivars777 (ivars777@gmail.com)
  7. # Distributed under the GNU GPL v3. For full terms see http://www.gnu.org/licenses/gpl-3.0.en.html
  8. # Used fragments of code from enigma2-plugin-tv3play by Taapat (https://github.com/Taapat/enigma2-plugin-tv3play)
  9. #
  10. import os,time,sys,os,os.path
  11. import datetime,re
  12. from enigma import ePicLoad, eServiceReference, eTimer
  13. from Components.ActionMap import ActionMap,HelpableActionMap
  14. from Components.AVSwitch import AVSwitch
  15. from Components.Label import Label
  16. from Components.MenuList import MenuList
  17. from Components.Pixmap import Pixmap
  18. from Components.Sources.List import List
  19. from Components.Sources.StaticText import StaticText
  20. from Components.Button import Button
  21. from Plugins.Plugin import PluginDescriptor
  22. from Screens.InfoBar import MoviePlayer
  23. from Screens.MessageBox import MessageBox
  24. #from Screens.InputBox import InputBox
  25. from Screens.ChoiceBox import ChoiceBox
  26. from Screens.VirtualKeyBoard import VirtualKeyBoard
  27. from Components.Input import Input
  28. from Screens.Screen import Screen
  29. from Tools.BoundFunction import boundFunction
  30. from Tools.Directories import resolveFilename, SCOPE_PLUGINS
  31. from Tools.LoadPixmap import LoadPixmap
  32. from twisted.web.client import downloadPage,defer,reactor
  33. from Components.Task import job_manager
  34. import ContentSources
  35. from VideoDownload import downloadJob, HLSDownloadJob,VideoDownloadList
  36. #import enigma2_api
  37. TMPDIR = "/tmp/playstream/"
  38. e2 = None
  39. def make_service(stream):
  40. url = stream["url"]
  41. headers = []
  42. if stream.has_key("headers"):
  43. for h in stream["headers"]:
  44. headers.append("%s=%s"%(h,stream["headers"][h]))
  45. if headers:
  46. headers ="&".jpin(headers)
  47. url = url+"#"+headers
  48. print url
  49. url = url.encode("utf8")
  50. service = eServiceReference(4097, 0, url)
  51. service.setName( stream["name"])
  52. return service
  53. #####################################################################################################################
  54. class TVPlayer(MoviePlayer):
  55. def __init__(self, session, service):
  56. MoviePlayer.__init__(self, session, service)
  57. self.skinName = "MoviePlayer"
  58. def leavePlayer(self):
  59. self.close()
  60. #self.session.openWithCallback(self.leavePlayerConfirmed, MessageBox, _("Stop playing?"))
  61. def leavePlayerConfirmed(self, answer):
  62. if answer:
  63. self.close()
  64. def doEofInternal(self, playing):
  65. self.close()
  66. #def getPluginList(self):
  67. #from Components.PluginComponent import plugins
  68. #list = []
  69. #for p in plugins.getPlugins(where = PluginDescriptor.WHERE_EXTENSIONSMENU):
  70. #if p.name != _("TV Play"):
  71. #list.append(((boundFunction(self.getPluginName, p.name),
  72. #boundFunction(self.runPlugin, p), lambda: True), None))
  73. #return list
  74. #def showMovies(self):
  75. #pass
  76. #####################################################################################################################
  77. class PSPlayer(TVPlayer):
  78. def __init__(self, session, streams):
  79. self.session = session
  80. self.streams = streams
  81. self.cur_stream = self.streams[0] # TODO
  82. self.selected = 0
  83. service = make_service(self.cur_stream)
  84. TVPlayer.__init__(self, session, service)
  85. self["actions"] = ActionMap(["MoviePlayerActions","MovieSelectionActions","ColorActions","InfobarAudioSelectionActions"], {
  86. "leavePlayer":self.leavePlayer,
  87. "AudioSelection":self.select_stream,
  88. "audioSelection":self.select_stream,
  89. "green":self.select_stream,
  90. "showEventInfo":self.service_info
  91. })
  92. self.skinName = "MoviePlayer"
  93. def play_service(self,service):
  94. self.movieSelected(service)
  95. def service_info(self):
  96. print "########[MoviePlayer] service_info"
  97. from Tools import Notifications
  98. text = "%s\n%s %s\n%s"%(self.cur_stream["name"],self.cur_stream["lang"],self.cur_stream["quality"],self.cur_stream["desc"])
  99. text = text.encode("utf8")
  100. #print text
  101. type = MessageBox.TYPE_INFO
  102. Notifications.AddPopup(text = text, type=None, timeout = 10)
  103. #Notifications.MessageBox(self.session, text=text, type=MessageBox.TYPE_INFO, timeout=10,
  104. #close_on_any_key=True,
  105. #default=True,
  106. #enable_input=True,
  107. #msgBoxID=None,
  108. #picon=False,
  109. #simple=False,
  110. #wizard=False,
  111. #list=None,
  112. #skin_name=None,
  113. #timeout_default=None)
  114. #return True
  115. def select_stream(self):
  116. print "########[MoviePlayer] select_stream"
  117. lst = []
  118. title = "Select stream"
  119. for i,s in enumerate(self.streams):
  120. lst.append(("[%s,%s] %s"%(s["lang"],s["quality"],s["name"]),i))
  121. self.session.openWithCallback(self.cb_select_stream, ChoiceBox, text = title, list = lst,selection = self.selected)
  122. def cb_select_stream(self,answer):
  123. #print "item_menu_selected",answer
  124. if not answer:
  125. return
  126. self.selected = answer[1]
  127. service = make_service(self.streams[self.selected])
  128. self.play_service(service)
  129. #####################################################################################################################
  130. class MainScreen(Screen):
  131. skin = """
  132. <screen position="center,center" size="1015,570" title="Play Stream">
  133. <eLabel position="5,0" size="1000,2" backgroundColor="#aaaaaa" />
  134. <widget name="title" position="10,2" size="1000,38" font="Regular;30" />
  135. <widget source="list" render="Listbox" position="10,55" size="580,470" \
  136. scrollbarMode="showOnDemand" >
  137. <convert type="TemplatedMultiContent" >
  138. {
  139. "template": [MultiContentEntryText(pos=(10, 1), size=(560, 30), \
  140. font=0, flags=RT_HALIGN_LEFT, text=0)],
  141. "fonts": [gFont("Regular", 20)],
  142. "itemHeight": 30
  143. }
  144. </convert>
  145. </widget>
  146. <widget name="pic" position="646,55" size="327,250" alphatest="on" />
  147. <widget name="cur" position="610,310" size="400,250" halign="center" font="Regular;20"/>
  148. <ePixmap name="red" position="100,530" zPosition="2" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
  149. <widget name="key_red" position="100,530" size="140,40" valign="center" halign="center" zPosition="4" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
  150. <ePixmap name="green" position="240,530" zPosition="2" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
  151. <widget name="key_green" position="240,530" size="140,40" valign="center" halign="center" zPosition="4" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
  152. <ePixmap name="yellow" position="380,530" zPosition="2" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
  153. <widget name="key_yellow" position="380,530" size="140,40" valign="center" halign="center" zPosition="4" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
  154. <ePixmap name="menu" position="560,535" zPosition="2" size="140,40" pixmap="skin_default/buttons/key_menu.png" transparent="1" alphatest="on" />
  155. <widget name="key_menu" position="560,530" size="140,40" valign="center" halign="center" zPosition="4" backgroundColor="blue" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
  156. </screen>"""
  157. def __init__(self, session):
  158. Screen.__init__(self, session)
  159. #self.setTitle2("Home")
  160. self.session = session
  161. self.e2 = None
  162. self["key_red"] = Button(_("Back"))
  163. self["key_green"] = Button(_("Select"))
  164. self["key_yellow"] = Button(_("Options"))
  165. self["key_menu"] = Button("Menu" )
  166. self["actions"] = ActionMap(["OkCancelActions", "ColorActions","MenuActions", "NumberActions"],
  167. {
  168. "cancel": self.Cancel,
  169. "ok": self.Ok,
  170. "green": self.Ok,
  171. "red": self.Back,
  172. "yellow": self.options_screen,
  173. "blue": self.download_list,
  174. "menu": self.item_menu,
  175. })
  176. self["list"] = List([])
  177. self["list"].onSelectionChanged.append(self.SelectionChanged)
  178. self["pic"] = Pixmap()
  179. self["cur"] = Label()
  180. self["title"] = Label()
  181. self.downloading = 0
  182. self.activeDownloads = 0
  183. if not os.path.exists(TMPDIR):
  184. os.mkdir(TMPDIR)
  185. self.onLayoutFinish.append(self.LayoutFinish)
  186. def LayoutFinish(self):
  187. self.cur_directory = os.path.dirname(os.path.realpath(__file__))
  188. self.defimage = LoadPixmap(os.path.join(self.cur_directory,"PlayStream.png"))
  189. #self.defimage = None
  190. #sc = AVSwitch().getFramebufferScale()
  191. #self.defimage0 = ePicLoad()
  192. #self.defimage0.PictureData.get().append(boundFunction(self.FinishDecodeDef, os.path.join(self.cur_directory,"PlayStream.png")))
  193. #self.defimage0.setPara((self["pic"].instance.size().width(),self["pic"].instance.size().height(),sc[0], sc[1], False, 0, "#00000000"))
  194. #self.defimage0.startDecode("default")
  195. self.activeDownloads = 0
  196. self.images = {}
  197. self.images_url = {}
  198. self.picloads = {}
  199. self.history = []
  200. reload(ContentSources)
  201. self.sources = ContentSources.ContentSources(os.path.join(self.cur_directory,"sources"))
  202. self.config = self.sources.plugins["config"]
  203. self.cur_menu = ("Home","config::home","","Sākums") #
  204. try:
  205. self.content = self.sources.get_content(self.cur_menu[1])
  206. except Exception,e:
  207. self.session. open(MessageBox, "Error - %s"%str(e) , MessageBox.TYPE_INFO)
  208. return
  209. print self.content
  210. self["list"].setList(self.content)
  211. self["cur"].setText(self.content[0][3])
  212. self.setTitle2(self.cur_menu[0])
  213. self.ShowPic(self.content[0][2])
  214. def SelectionChanged(self):
  215. current = self["list"].getCurrent()
  216. print "[PlayStream] SelectionChanged: current=",current
  217. if not current: return
  218. self["cur"].setText(current[3]) if current[3] else self["cur"].setText("")
  219. if current[2]:
  220. self.ShowPic(current[2])
  221. else:
  222. self.ShowDefPic()
  223. def setTitle2(self,title):
  224. #print self.keys()
  225. self["title"].setText(title)
  226. def ShowDefPic(self):
  227. if self.defimage:
  228. self["pic"].instance.setPixmap(self.defimage)
  229. def ShowPic(self,image_url):
  230. if image_url == "default":
  231. self.ShowDefPic()
  232. return
  233. elif self.images.has_key(image_url):
  234. if self.images[image_url] in (-1,-2):
  235. return
  236. elif self.images[image_url] == -3:
  237. self.ShowDefPic()
  238. return
  239. else:
  240. self["pic"].instance.setPixmap(self.images[image_url])
  241. else:
  242. if image_url.startswith("http"):
  243. fname = image_url.replace(":","-").replace("/","_")
  244. image_path = os.path.join(TMPDIR, fname)
  245. self.download_image(image_path, image_url)
  246. else: # local file
  247. image_path = os.path.join(self.cur_directory,image_url)
  248. self.start_decode(image_path,image_url)
  249. def start_decode(self,image_path,image_url):
  250. self.images[image_url] = -2
  251. self.images_url[image_path] = image_url
  252. sc = AVSwitch().getFramebufferScale()
  253. if not self.picloads.has_key(image_path):
  254. self.picloads[image_path] = ePicLoad()
  255. self.picloads[image_path].PictureData.get().append(boundFunction(self.FinishDecode, image_path))
  256. self.picloads[image_path].setPara((self["pic"].instance.size().width(),
  257. self["pic"].instance.size().height(),
  258. sc[0], sc[1], False, 0, "#00000000"))
  259. print image_path,image_url
  260. self.picloads[image_path].startDecode(image_path)
  261. def FinishDecode(self, image_path,picInfo = None):
  262. image_url = self.images_url[image_path]
  263. del self.images_url[image_path] #III
  264. self.images[image_url] = self.picloads[image_path].getData()
  265. self["pic"].instance.setPixmap(self.images[image_url])
  266. del self.picloads[image_path]
  267. if len(self.images)>30:
  268. del self.images[self.images.keys()[0]]
  269. # self.images.pop()
  270. #def FinishDecodeDef(self, image_path,picInfo = None):
  271. # self.defimage = self.defimage0.getData()
  272. # del self.defimage0
  273. # self["pic"].instance.setPixmap(self.defimage)
  274. def download_image(self,image_path,image_url):
  275. print "Image download started",self.downloading,image_path,image_url
  276. self.downloading += 1
  277. self.images[image_url] = -1
  278. downloadPage(image_url, image_path).addCallback(boundFunction(self.downloadFinished, image_path,image_url)).addErrback(boundFunction(self.downloadFailed, image_path,image_url))
  279. def downloadFinished(self, image_path, image_url, result):
  280. self.downloading -= 1
  281. print "[TV Play] Image downloaded finished ",self.downloading,image_path, image_url,result
  282. self.start_decode(image_path,image_url)
  283. def downloadFailed(self, image_path, image_url,result):
  284. self.downloading -= 1
  285. print "[TV Play] Image downloaded failed ",self.downloading,image_path, image_url,result
  286. self.images[image_url] = -3
  287. def Ok(self):
  288. current = self["list"].getCurrent()
  289. self.current = current
  290. index = self["list"].getIndex()
  291. self.index = index
  292. print "[PlayStream] - menu selected ", current
  293. #if len(current[1].split("::"))<2 or not current[1].split("::")[1]: #
  294. # return # TODO - kaut kā jēdzigak jāapstradā nederigs ieraksts (paziņojums?)
  295. if self.sources.is_video(current[1]):
  296. if self.sources.stream_type(current[1]):
  297. stream = stream0
  298. stream["url"] = cur2[1]
  299. stream["name"] = cur2[0]
  300. streams = [stream]
  301. else:
  302. try:
  303. streams = self.sources.get_streams(current[1])
  304. except Exception,e:
  305. self.msg("Error - %s"%str(e))
  306. return
  307. if streams:
  308. print streams
  309. self.session.open(PSPlayer, streams)
  310. else:
  311. self.msg("No stream found - %s"%(self.current[1]))
  312. return
  313. #if not self.sources.stream_type(current[1]):
  314. #current = self.sources.get_content(current[1])
  315. #print "Item to play",current
  316. #stream_type = self.sources.stream_type(current[1])
  317. #url = current[1]
  318. #title = current[0]
  319. #if not stream_type: #
  320. #print stream_type
  321. #self.msg("No stream found - %s"%(self.current[1]))
  322. #return
  323. #self.playVideo(current)
  324. elif current[1] == "back":
  325. cur_menu_old = self.cur_menu
  326. self.cur_menu = self.history.pop()
  327. new_content = self.sources.get_content(self.cur_menu[1])
  328. try:
  329. index = zip(*new_content)[1].index(cur_menu_old[1])
  330. except:
  331. index = 0
  332. self.setTitle2(self.cur_menu[0])
  333. self.show_content(new_content,index)
  334. else:
  335. print "selected=",current
  336. if "{0}" in current[1]:
  337. self.session.openWithCallback(self.cb_input,VirtualKeyBoard, title="Enter value", text="")
  338. #a = raw_input("Enter value:")
  339. #a = "big bang"
  340. #current = (current[0],current[1].format(a),current[2],current[3])
  341. #self.get_content(current)
  342. else:
  343. self.get_content(current)
  344. def cb_input(self,value):
  345. if not value:
  346. return
  347. current = self.current
  348. current = (current[0],current[1].format(value),current[2],current[3])
  349. self.get_content(current)
  350. def get_content(self,current):
  351. self.history.append(self.cur_menu)
  352. self.cur_menu = current
  353. try:
  354. new_content = self.sources.get_content(self.cur_menu[1])
  355. except Exception,e:
  356. self.cur_menu = self.history.pop()
  357. self.session. open(MessageBox, "Error - %s"%str(e) , MessageBox.TYPE_INFO)
  358. return
  359. self.setTitle2(self.cur_menu[0])
  360. self.show_content(new_content)
  361. def Back(self):
  362. self["list"].setIndex(0)
  363. self.Ok()
  364. def show_content(self,content,index=0):
  365. self["list"].setList(content)
  366. self["list"].setIndex(index)
  367. self.SelectionChanged()
  368. def Cancel(self):
  369. #if os.path.exists(TMPDIR):
  370. #for name in os.listdir(TMPDIR):
  371. #os.remove(os.path.join(TMPDIR, name))
  372. #os.rmdir(TMPDIR)
  373. self.close()
  374. def playVideo(self, current):
  375. hlspath = current[1]
  376. print "[TV Play] Play:", current
  377. ##SERVICE 4097:0:0:0:0:0:0:0:0:0:http%3a//127.0.0.1%3a7777#Cookie1=test3&User-Agent=CustomUserAgent&Cookie=test4:test_headers
  378. ref = eServiceReference(4097, 0, hlspath)
  379. ref.setName(current[0])
  380. self.session.open(TVPlayer, ref)
  381. def item_menu(self):
  382. print "\n[PlayStream] options\n"
  383. self.current = self["list"].getCurrent()
  384. self.index = self["list"].getIndex()
  385. #self.session. open(MessageBox, "Item options - %s"%current[0] , MessageBox.TYPE_INFO)
  386. #args=[current,self.cur_menu]
  387. #self.session.open(ItemMenuScreen,current,index,self)
  388. lst = [
  389. ("Aditional information","info","Display additional information about item"),
  390. ("Add to bouquet","bouquet","Add current item to Enigma2 bouquet"),
  391. ("Add to favorites","favorites","Add current item to PlayStrem favorites"),
  392. ("Download list","download_list","Show download list")
  393. ]
  394. if self.sources.is_video(self.current[1]):
  395. lst.extend([
  396. ("Download video","download","Download video in background"),
  397. ])
  398. if "config::" in self.cur_menu[1]:
  399. lst.extend([
  400. ("Rename item","rename","Rename list item"),
  401. ("Move item","move","Move list item"),
  402. ("Delete item","delete","Delete list item"),
  403. ("Add submenu","add_list","Add submenu before selected item"),
  404. ])
  405. title = self.current[0]
  406. self.session.openWithCallback(self.cb_item_menu, ChoiceBox, text = title, list = lst) #TODO
  407. def cb_item_menu(self,answer):
  408. #print "item_menu_selected",answer
  409. if not answer:
  410. return
  411. if answer[1] == "info":
  412. self.session.open(MessageBox, "Not yet implemented!", MessageBox.TYPE_INFO)
  413. pass # TODO parada papildus info
  414. elif answer[1] == "bouquet":
  415. #if not e2:
  416. #e2 = enigma2_api.DBServices()
  417. #print "load_buuquets - ",e2._load_bouquets()
  418. self.session.open(MessageBox, "Not yet implemented!", MessageBox.TYPE_INFO)
  419. elif answer[1] == "favorites":
  420. lists = self.config.get_lists()
  421. lists2 = [(l,l) for l in lists]
  422. self.session.openWithCallback(self.cb_favorites, ChoiceBox, text="Select menu item will be added",list = lists2)
  423. elif answer[1] == 'download':
  424. current = self.current
  425. if not self.sources.is_video(current[1]):
  426. self.msg("Can not download listst (yet) - %s"%(current[1]))
  427. return
  428. #if not self.sources.stream_type(current[1]):
  429. #current = self.sources.get_content(current[1])
  430. try:
  431. streams = self.sources.get_streams(current[1])
  432. except Exception,e:
  433. self.msg("Error - %s"%str(e))
  434. return
  435. if not streams:
  436. self.msg("No stream found to download - %s"%(self.current[1]))
  437. return
  438. if len(streams)>1:
  439. stream = streams[0] # TODO iespeja izvelēties strīmu, ja to ir vairāki
  440. else:
  441. stream = streams[0]
  442. stream_type = stream["type"] #self.sources.stream_type(stream["url"])
  443. if not stream_type: #
  444. self.msg("Not supported stream type found to download - %s"%(self.current[1]))
  445. return
  446. title = streams[0]["name"]
  447. url = streams[0]["url"]
  448. downloadDir = "/media/hdd/movie" #config.plugins.playstream.downloadDir.value TODO
  449. if not os.path.exists(downloadDir):
  450. self.msg(_('Sorry, download directory "%s" not exist!\nPlease specify in the settings existing directory'%downloadDir))
  451. return
  452. fname = re.sub("[/\n\r\t,]","_",title)+".mp4"
  453. outputfile = os.path.join(downloadDir, fname)
  454. if os.path.exists(outputfile):
  455. self.msg( _('Sorry, this file already exists:\n%s') % outputfile)
  456. return
  457. print "Trying to download - ", current
  458. if stream_type in ("http","https"):
  459. print "\n**Download %s - %s"%(title,url)
  460. #reload(downloadJob)
  461. job_manager.AddJob(downloadJob(url, outputfile, title[:20], self.video_download_stop))
  462. self.activeDownloads += 1
  463. self.msg(_('Video download started!'))
  464. elif stream_type == "hls":
  465. #self.msg("HLS stream download not yet implemented!")
  466. print "\n**Download %s - %s"%(title,url)
  467. #reload(HLSDownloadJob)
  468. print "HLSDownload", url,outputfile
  469. job_manager.AddJob(HLSDownloadJob(url, outputfile, title[:20], self.video_download_stop))
  470. self.activeDownloads += 1
  471. self.msg(_('Video download started!'))
  472. elif stream_type == "rstp":
  473. self.msg("RSTP stream download not yet implemented!")
  474. else:
  475. self.msg("Unkown stream type!")
  476. elif answer[1] == 'download_list':
  477. self.download_list()
  478. elif answer[1] == "delete":
  479. lst = self.cur_menu[1].replace("config::","")
  480. #print lst
  481. self.config.del_item(lst,self.index)
  482. self.config.write_streams()
  483. txt = "'%s' deleted from favourite stream list '%s'"%(self.current[0],lst)
  484. self.session.open(MessageBox, txt, MessageBox.TYPE_INFO,timeout=5)
  485. elif answer[1] == "rename":
  486. #name2 = "Renamed"
  487. self.session.openWithCallback(self.cb_rename,VirtualKeyBoard, title="Enter new item name", text=self.current[0])
  488. elif answer[1] == "add_list":
  489. self.session.open(MessageBox, "Not yet implemented!", MessageBox.TYPE_INFO,timeout=5)
  490. pass #TODO
  491. return
  492. def download_list(self):
  493. self.session.open(VideoDownloadList)
  494. def cb_rename(self,value):
  495. if not value:
  496. return
  497. lst = self.cur_menu[1].replace("config::","")
  498. pos = self.index
  499. print value
  500. item2 = list(self.current)
  501. item2[0]=value
  502. item2 = tuple(item2)
  503. self.config.replace_item(lst,item2,pos)
  504. self.config.write_streams()
  505. txt = "'%s' renamed to '%s'"%(self.current[0],value)
  506. self.session.open(MessageBox, txt, MessageBox.TYPE_INFO,timeout=5)
  507. def cb_favorites(self,answer):
  508. print "cb_favorites",answer
  509. if not answer:
  510. return
  511. value = answer[1]
  512. self.config.add_item(value,self.current)
  513. self.config.write_streams()
  514. txt = "'%s' added to favourite stream list '%s'"%(self.current[0],value)
  515. self.session.open(MessageBox, txt, MessageBox.TYPE_INFO,timeout=3)
  516. #self.session.openWithCallback(self.callMyMsg, MessageBox, _("Do you want to exit the plugin?"), MessageBox.TYPE_INFO)
  517. def options_screen(self):
  518. source = self.cur_menu[1].split("::")[0]
  519. options = self.sources.options_read(source)
  520. print source
  521. if not options:
  522. self.session. open(MessageBox, "No options available for source %s (%s)"%(self.cur_menu[0],source) , MessageBox.TYPE_INFO)
  523. else:
  524. self.session.open(OptionsScreen,self)
  525. def video_download_stop(self,title):
  526. #self.activeDownloads -= 1
  527. #self.msg("Download '%s'finished!"%title)
  528. print "video_download_stop ", title
  529. def msg(self,msg,timeout=10):
  530. self.session.open(MessageBox, msg, MessageBox.TYPE_INFO, timeout)
  531. ##########################################################################
  532. from Components.config import config, ConfigSubsection, ConfigYesNo,\
  533. getConfigListEntry, ConfigSelection, ConfigNumber, ConfigDirectory,ConfigText, ConfigSubDict
  534. from Components.ConfigList import ConfigListScreen
  535. #from Screens.LocationBox import LocationBox
  536. config.plugins.playstream = ConfigSubDict()
  537. class OptionsScreen(ConfigListScreen,Screen):
  538. skin = """
  539. <screen position="center,center" size="560,400" >
  540. <ePixmap name="red" position="0,0" zPosition="2" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
  541. <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" />
  542. <ePixmap name="green" position="140,0" zPosition="2" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
  543. <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" />
  544. <ePixmap name="yellow" position="280,0" zPosition="2" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
  545. <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" />
  546. <ePixmap name="blue" position="420,0" zPosition="2" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
  547. <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" />
  548. <widget name="config" position="10,40" size="540,340" scrollbarMode="showOnDemand" />
  549. </screen>"""
  550. def __init__(self, session,*args):
  551. self.session = session
  552. Screen.__init__(self, session)
  553. self.main = args[0]
  554. self.setTitle(self.main.cur_menu[0]+" Options")
  555. self.source = self.main.cur_menu[1].split("::")[0]
  556. self.cfg = config.plugins.playstream
  557. self.list = []
  558. self.options = self.main.sources.options_read(self.source)
  559. if not self.options:
  560. #self.session. open(MessageBox, "No options available for source %s (%s)"%(self.main.cur_menu[0],self.source) , MessageBox.TYPE_INFO)
  561. self.close(False,self.session)
  562. for k in self.options:
  563. self.cfg[k]=ConfigText(default=self.options[k],fixed_size=False)
  564. self.list.append(getConfigListEntry(k, self.cfg[k]))
  565. ConfigListScreen.__init__(self, self.list, session = self.session)
  566. self["key_red"] = Button(_("Cancel"))
  567. self["key_green"] = Button("Save")
  568. self["key_yellow"] = Button("")
  569. self["key_blue"] = Button("")
  570. self["setupActions"] = ActionMap(["SetupActions", "ColorActions"],
  571. {
  572. "red": self.cancel,
  573. "green": self.save,
  574. "save": self.save,
  575. "cancel": self.cancel,
  576. "ok": self.ok,
  577. }, -2)
  578. def getCurrentEntry(self):
  579. return self["config"].getCurrent()[0]
  580. def getCurrentValue(self):
  581. return str(self["config"].getCurrent()[1].getText())
  582. def ok(self):
  583. self.save()
  584. #if self["config"].getCurrent()[1] == config.plugins.getpicons.folder:
  585. #folder = config.plugins.getpicons.folder.value
  586. #self.session.openWithCallback(self.change_dir, LocationBox,"Select Folder")
  587. #else:
  588. #def change_dir(self, folder, select=None):
  589. #if folder:
  590. ##print "change_dir to %s"%folder
  591. #config.plugins.getpicons.folder.value = folder
  592. def save(self):
  593. print "saving"
  594. #self.saveAll()
  595. for k in self.options.keys():
  596. self.options[k]=self.cfg[k].value
  597. print "%s=%s"%(k,self.cfg[k].value)
  598. self.main.sources.options_write(self.source,self.options)
  599. self.close(True,self.session)
  600. def cancel(self):
  601. print "cancel"
  602. self.close(False,self.session)