no need to translate... use german text for german streaming plugin
[enigma2-plugins.git] / zdfmediathek / src / plugin.py
1 # -*- coding: UTF-8 -*-
2 # ZDF Mediathek by AliAbdul\r
3 from Components.ActionMap import HelpableActionMap
4 from Components.AVSwitch import AVSwitch\r
5 from Components.Label import Label\r
6 from Components.MenuList import MenuList\r
7 from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest
8 from Components.Pixmap import Pixmap
9 from Components.PluginComponent import plugins\r
10 from enigma import eListboxPythonMultiContent, ePicLoad, eServiceReference, eTimer, getDesktop, gFont
11 from os import listdir
12 from Plugins.Plugin import PluginDescriptor
13 from Screens.ChoiceBox import ChoiceBox
14 from Screens.HelpMenu import HelpableScreen
15 from Screens.InfoBar import MoviePlayer
16 from Screens.MessageBox import MessageBox\r
17 from Screens.Screen import Screen\r
18 from Screens.VirtualKeyBoard import VirtualKeyBoard
19 from time import sleep
20 from Tools.BoundFunction import boundFunction
21 from Tools.Directories import resolveFilename, SCOPE_PLUGINS
22 from Tools.HardwareInfo import HardwareInfo
23 from Tools.LoadPixmap import LoadPixmap\r
24 from twisted.web.client import downloadPage, getPage\r
25 import htmlentitydefs, re, urllib2
26
27 ###################################################
28
29 MAIN_PAGE = "http://www.zdf.de"
30
31 PNG_PATH = resolveFilename(SCOPE_PLUGINS)+"/Extensions/ZDFMediathek/"
32
33 TYPE_NOTHING = 0
34 TYPE_MOVIE = 1
35 TYPE_PODCAST = 2
36 TYPE_MOVIELIST_CATEGORY = 3
37
38 LIST_LEFT = 0
39 LIST_RIGHT = 1
40 LIST_NONE = 2
41
42 deviceName = HardwareInfo().get_device_name()
43 if deviceName.startswith("dm800") or deviceName == "dm500hd":
44         PLAY_MP4 = False #Benutze True, wenn rtsp streaming mit der Dreambox funktioniert
45 else:
46         PLAY_MP4 = False
47
48 try:
49         from LT.LTStreamPlayer import streamplayer
50 except ImportError:
51         try:
52                 from Plugins.Extensions.LTMediaCenter.LTStreamPlayer import streamplayer
53         except ImportError:
54                 streamplayer = None
55
56 try:
57         from Plugins.Extensions.VlcPlayer.VlcServerConfig import vlcServerConfig
58 except ImportError:
59         vlcServerConfig = None
60
61 ###################################################
62
63 def decode(line):\r
64         pat = re.compile(r'\\u(....)')\r
65         def sub(mo):\r
66                 return unichr(fromHex(mo.group(1)))\r
67         return pat.sub(sub, unicode(line))\r
68 \r
69 def decode2(line):\r
70         pat = re.compile(r'&#(\d+);')\r
71         def sub(mo):\r
72                 return unichr(int(mo.group(1)))\r
73         return decode3(pat.sub(sub, unicode(line)))\r
74 \r
75 def decode3(line):\r
76         dic = htmlentitydefs.name2codepoint\r
77         for key in dic.keys():\r
78                 entity = "&" + key + ";"\r
79                 line = line.replace(entity, unichr(dic[key]))\r
80         return line\r
81 \r
82 def fromHex(h):\r
83         return int(h, 16)
84
85 ###################################################
86
87 class ChangedMoviePlayer(MoviePlayer):
88         def __init__(self, session, service):
89                 MoviePlayer.__init__(self, session, service)
90                 self.skinName = "MoviePlayer"
91
92         def leavePlayer(self):
93                 self.session.openWithCallback(self.leavePlayerConfirmed, MessageBox, "Abspielen beenden?")
94
95         def leavePlayerConfirmed(self, answer):
96                 if answer:
97                         self.close()
98
99         def doEofInternal(self, playing):
100                 pass
101
102         def getPluginList(self):
103                 list = []
104                 for p in plugins.getPlugins(where=PluginDescriptor.WHERE_EXTENSIONSMENU):
105                         if p.name != "ZDF Mediathek":
106                                 list.append(((boundFunction(self.getPluginName, p.name), boundFunction(self.runPlugin, p), lambda: True), None))
107                 return list
108
109         def showMovies(self):
110                 pass
111
112 ###################################################
113
114 def getMovieDetails(div):
115         list = []
116         # Lese Sendung...
117         reonecat = re.compile(r'<p class="grey"><a href="(.+?)">(.+?)</a></p>', re.DOTALL)
118         content = reonecat.findall(div)
119         if len(content):
120                 broadcast = decode2(decode(content[0][1])).encode("UTF-8")
121                 list.append(content[0][0])
122                 if broadcast.startswith("<"):
123                         broadcast = ""
124                 list.append(broadcast)
125         # Lese Titel...
126         reonecat = re.compile(r'<p><b><a href=".+?">(.+?)</a></b></p>', re.DOTALL)
127         titles = reonecat.findall(div)
128         if len(titles):
129                 title = titles[0]
130                 if '<br/>' in title:
131                         idx = title.index('<br/>')
132                         title = title[:idx]
133                 if '<br />' in title:
134                         idx = title.index('<br />')
135                         title = title[:idx]
136                 title = decode2(decode(title)).encode("UTF-8")
137                 list.append(title)
138         # Lese Thumbnail-URL...
139         reonecat = re.compile(r'<img src="(.+?)"', re.DOTALL)
140         thumbnails = reonecat.findall(div)
141         if len(thumbnails):
142                 list.append(thumbnails[0])
143         # Lese Videolänge...
144         if ('VIDEO, ' in div):
145                 reonecat = re.compile(r'>VIDEO, (.+?)</a></p>', re.DOTALL)
146                 lengths = reonecat.findall(div)
147                 if len(lengths):
148                         list.append(lengths[0])
149         else:
150                 list.append("Live")
151         # Alles gefunden?
152         if len(list) == 5:
153                 return list
154         else:
155                 return None
156
157 def getCategoryDetails(div):
158         list = []
159         # Lese Rubrik...
160         reonecat = re.compile(r'<p class="grey"><a href="(.+?)">(.+?)</a></p>', re.DOTALL)
161         content = reonecat.findall(div)
162         if len(content):
163                 broadcast = decode2(decode(content[0][1])).encode("UTF-8")
164                 list.append(content[0][0])
165                 if broadcast.startswith("<"):
166                         broadcast = ""
167                 list.append(broadcast)
168         # Lese Titel...
169         reonecat = re.compile(r'<p><b><a href=".+?">(.+?)</a></b></p>', re.DOTALL)
170         titles = reonecat.findall(div)
171         if len(titles):
172                 title = titles[0]
173                 if '<br/>' in title:
174                         idx = title.index('<br/>')
175                         title = title[:idx]
176                 if '<br />' in title:
177                         idx = title.index('<br />')
178                         title = title[:idx]
179                 title = decode2(decode(title)).encode("UTF-8")
180                 list.append(title)
181         # Lese Thumbnail-URL...
182         reonecat = re.compile(r'<img src="(.+?)"', re.DOTALL)
183         thumbnails = reonecat.findall(div)
184         if len(thumbnails):
185                 list.append(thumbnails[0])
186         # Lese Beitragsanzahl...
187         reonecat = re.compile(r'">(.+?)BEITR&Auml;GE ZUR SENDUNG</a></p>', re.DOTALL)
188         counts = reonecat.findall(div)
189         if len(counts):
190                 count = counts[0]
191                 if '">' in count:
192                         while '">' in count:
193                                 idx = count.index('">')
194                                 count = count[idx+2:]
195                 if '"/>' in count:
196                         while '"/>' in count:
197                                 idx = count.index('"/>')
198                                 count = count[idx+3:]
199                 list.append("%sBeitraege"%count)
200         else:
201                 reonecat = re.compile(r'">(.+?)BEITR&Auml;GE ZUM THEMA</a></p>', re.DOTALL)
202                 counts = reonecat.findall(div)
203                 if len(counts):
204                         count = counts[0]
205                         if '">' in count:
206                                 while '">' in count:
207                                         idx = count.index('">')
208                                         count = count[idx+2:]
209                         if '"/>' in count:
210                                 while '"/>' in count:
211                                         idx = count.index('"/>')
212                                         count = count[idx+3:]
213                         list.append("%sBeitraege"%count)
214                 else:
215                         reonecat = re.compile(r'">(.+?)BEITR&Auml;GE ZUR RUBRIK</a></p>', re.DOTALL)
216                         counts = reonecat.findall(div)
217                         if len(counts):
218                                 count = counts[0]
219                                 if '">' in count:
220                                         while '">' in count:
221                                                 idx = count.index('">')
222                                                 count = count[idx+2:]
223                                 if '"/>' in count:
224                                         while '"/>' in count:
225                                                 idx = count.index('"/>')
226                                                 count = count[idx+3:]
227                                 list.append("%sBeitraege"%count)
228         # Alles gefunden?
229         if len(list) == 5:
230                 return list
231         else:
232                 return None
233
234 ###################################################
235
236 def getMovieUrl(url):
237         try:\r
238                 f = urllib2.urlopen(url)\r
239                 txt = f.read()\r
240                 f.close()
241         except:
242                 txt = ""
243         if ('rtsp' in txt) and ('.mp4' in txt):
244                 idx = txt.index('rtsp')
245                 idx2 = txt.index('.mp4')
246                 return txt[idx:idx2+4]
247         else:
248                 return None
249
250 def getTitleLinks(html):
251         links = []
252         start = '<div id="breadcrumbContainer">'
253         end = '</div>'
254         if start in html:
255                 idx = html.index(start)
256                 html = html[idx:]
257                 idx = html.index(end)
258                 html = html[:idx]
259                 reonecat = re.compile(r'<a href="(.+?)">(.+?)</a>', re.DOTALL)
260                 for url, name in reonecat.findall(html):
261                         name = decode2(decode(name)).encode("UTF-8")
262                         links.append([url, name])
263         return links
264
265 def getLeftMenu(html):
266         list = []
267         reonecat = re.compile(r'<div id="navigationContainer">(.+?)</div>', re.DOTALL)
268         leftMenu = reonecat.findall(html)
269         if len(leftMenu):
270                 reonecat = re.compile(r'<li><a href="(.+?)"(.+?)</a>', re.DOTALL)
271                 for url, name in reonecat.findall(leftMenu[0]):
272                         if name.startswith(' class="active">'):
273                                 active = True
274                                 name = name[16:]
275                         else:
276                                 active = False
277                                 name = name[1:]
278                         if (name != "Hilfe") and (not 'Podcasts' in name): # TODO: Podcasts brauchen noch etwas Arbeit... derzeit deaktiviert
279                                 list.append([url, name, active])
280         return list
281
282 def getRightMenu(html):
283         list = []
284         # Suche Filme...
285         if '" class="play" target="_blank">Abspielen</a></li>' in html:
286                 reonecat = re.compile(r'<li>(.+?)<a href="(.+?)" class="play" target="_blank">Abspielen</a></li>', re.DOTALL)
287                 for speed, movie in reonecat.findall(html):
288                         list.append([speed, movie])
289                 if len(list):
290                         return [TYPE_MOVIE, list]
291         # Suche podcasts...
292         if '<!-- Start:Podcasts -->' in html:
293                 reonecat = re.compile(r'<!-- Start:Podcasts -->(.+?)<!-- Ende:Podcasts -->', re.DOTALL)
294                 tmp = reonecat.findall(html)
295                 if len(tmp):
296                         reonecat = re.compile(r'<p><b><a href="(.+?)".+?">(.+?)</a></b></p>', re.DOTALL)
297                         podcasts = reonecat.findall(tmp[0])
298                         for podcast in podcasts:
299                                 list.append([podcast[0], podcast[1]])
300                 if len(list):
301                         return [TYPE_PODCAST, list]
302         # Suche Videos und Rubriken...
303         start = '<div class="beitragListe">'
304         if '<div class="beitragFooterSuche">' in html:
305                 end = '<div class="beitragFooterSuche">'
306         else:
307                 end = '<div class="beitragFooter">'
308         if (start in html) and (end in html):
309                 while (start in html) and (end in html):
310                         idx = html.index(start)
311                         html = html[idx:]
312                         reonecat = re.compile(r'%s(.+?)%s'%(start, end), re.DOTALL)
313                         blocks = reonecat.findall(html)
314                         if blocks:
315                                 reonecat = re.compile(r'<div class="image">(.+?)</li>', re.DOTALL)
316                                 divs = reonecat.findall(blocks[0])
317                                 for div in divs:
318                                         details = None
319                                         if ('VIDEO, ' in div) or ('>LIVE<' in div):
320                                                 details = getMovieDetails(div)
321                                         elif 'BEITR&Auml;GE ZU' in div:
322                                                 details = getCategoryDetails(div)
323                                         if details:
324                                                 list.append([details[0], details[1], details[2], details[3], details[4]])
325                         html = html[1:]
326                 reonecat = re.compile(r'<a href="(.+?)" class="weitereBeitraege"', re.DOTALL)
327                 more = reonecat.findall(html)
328                 if len(more):
329                         more = more[0]
330                         if 'href="' in more:
331                                 while 'href="' in more:
332                                         idx = more.index('href="')
333                                         more = more[idx+6:]
334                         list.append([more, "", "", "", "Weitere  Beitraege laden."])
335         if len(list):
336                 return [TYPE_MOVIELIST_CATEGORY, list]
337         # Nichts :(
338         return [TYPE_NOTHING, list]
339
340 ###################################################
341
342 class LeftMenuList(MenuList):
343         def __init__(self):
344                 MenuList.__init__(self, [], False, eListboxPythonMultiContent)
345                 self.l.setItemHeight(20)
346                 self.l.setFont(0, gFont("Regular", 18))
347                 self.menu = []
348                 self.active = True
349                 self.current = 0
350
351         def setActive(self, active):
352                 self.active = active
353                 self.SetList(self.menu, True)
354
355         def entry(self, text, active, selected):
356                 res = [(text)]
357                 if text.startswith("- Heute"):
358                         text = "- Heute"
359                 elif text.startswith("- Gestern"):
360                         text = "- Gestern"
361                 elif text.startswith("- Morgen"):
362                         text = "- Morgen"
363                 if selected:
364                         res.append(MultiContentEntryPixmapAlphaTest(pos=(0, 0), size=(20, 20), png=LoadPixmap(cached=True, path=PNG_PATH+"active.png")))
365                 if active:
366                         res.append(MultiContentEntryText(pos=(25, 0), size=(175, 20), font=0, text=text, color=0xf47d19))
367                 else:
368                         res.append(MultiContentEntryText(pos=(25, 0), size=(175, 20), font=0, text=text, color=0xffffff))
369                 return res
370
371         def SetList(self, l, moveCursor=False):
372                 del self.menu
373                 self.menu = l
374                 if moveCursor:
375                         idx = 0
376                         for x in l:
377                                 if x[2]:
378                                         self.current = idx
379                                 idx += 1
380                 list = []
381                 idx = 0
382                 for x in l:
383                         if (idx == self.current) and self.active:
384                                 selected = True
385                         else:
386                                 selected = False
387                         list.append(self.entry(x[1], x[2], selected))
388                         idx += 1
389                 self.setList(list)
390
391         def getCurrentUrl(self):
392                 if len(self.menu):
393                         return self.menu[self.current][0]
394                 else:
395                         return None
396
397         def select(self, index):
398                 if len(self.menu):
399                         if (index > -1) and (index < len(self.menu)):
400                                 self.current = index
401                                 self.SetList(self.menu)
402
403         def first(self):
404                 self.select(0)
405
406         def last(self):
407                 self.select(len(self.menu)-1)
408
409         def previous(self):
410                 if len(self.menu):
411                         self.select(self.current-1)
412
413         def next(self):
414                 if len(self.menu):
415                         self.select(self.current+1)
416
417 ###################################################
418
419 class RightMenuList(MenuList):
420         def __init__(self):
421                 MenuList.__init__(self, [], False, eListboxPythonMultiContent)
422                 self.l.setFont(0, gFont("Regular", 18))
423                 self.l.setFont(1, gFont("Regular", 16))
424                 self.listCompleted = []
425                 self.callback = None
426                 self.idx = 0
427                 self.thumb = ""
428
429         def buildEntries(self):
430                 if self.type == TYPE_PODCAST:
431                         list = []
432                         for x in self.list:
433                                 title = x[1]
434                                 if '<br/>' in title:
435                                         idx = title.index('<br/>')
436                                         title = title[:idx]
437                                 title = decode2(decode(title)).encode("UTF-8")
438                                 res = [(x[0], title)]
439                                 res.append(MultiContentEntryText(pos=(0, 0), size=(430, 20), font=0, text=title))
440                                 list.append(res)
441                         self.setList(list)
442                         if self.callback:
443                                 self.callback()
444                 elif self.type == TYPE_MOVIELIST_CATEGORY:
445                         if self.idx == len(self.list):
446                                 self.setList(self.listCompleted)
447                                 if self.callback:
448                                         self.callback()
449                         else:
450                                 self.downloadThumbnail()
451
452         def downloadThumbnail(self):
453                 thumbUrl = self.list[self.idx][3]
454                 if not thumbUrl.startswith("http://"):
455                         thumbUrl = "%s%s"%(MAIN_PAGE, thumbUrl)
456                 try:
457                         req = urllib2.Request(thumbUrl)
458                         url_handle = urllib2.urlopen(req)\r
459                         headers = url_handle.info()\r
460                         contentType = headers.getheader("content-type")
461                 except:
462                         contentType = None
463                 if contentType:
464                         if 'image/jpeg' in contentType:
465                                 self.thumb = "/tmp/zdf.jpg"
466                         elif 'image/gif' in contentType:
467                                 self.thumb = "/tmp/zdf.gif"
468                         elif 'image/png' in contentType:
469                                 self.thumb = "/tmp/zdf.png"
470                         else:
471                                 print "[ZDF Mediathek] Unknown thumbnail content-type:", contentType
472                                 self.thumb = None
473                 else:
474                         self.thumb = None
475                 if self.thumb:
476                         downloadPage(thumbUrl, self.thumb).addCallback(self.downloadThumbnailCallback).addErrback(self.downloadThumbnailError)
477                 else:
478                         self.buildEntry(None)
479
480         def downloadThumbnailError(self, err):
481                 print "[ZDF Mediathek] Error:", err
482                 self.buildEntry(None)
483
484         def downloadThumbnailCallback(self, txt=""):
485                 sc = AVSwitch().getFramebufferScale()
486                 self.picload = ePicLoad()
487                 self.picload.PictureData.get().append(self.buildEntry)
488                 self.picload.setPara((94, 60, sc[0], sc[1], False, 1, "#00000000"))
489                 self.picload.startDecode(self.thumb)
490
491         def buildEntry(self, picInfo=None):
492                 x = self.list[self.idx]
493                 res = [(x[0], x[2])]
494                 if picInfo:
495                         ptr = self.picload.getData()
496                         if ptr != None:
497                                 res.append(MultiContentEntryPixmapAlphaTest(pos=(0, 0), size=(94, 60), png=ptr))
498                 res.append(MultiContentEntryText(pos=(100, 0), size=(430, 20), font=0, text=x[2]))
499                 res.append(MultiContentEntryText(pos=(100, 20), size=(430, 20), font=0, text=x[4]))
500                 res.append(MultiContentEntryText(pos=(100, 40), size=(430, 20), font=1, text=x[1]))
501                 self.listCompleted.append(res)
502                 self.idx += 1
503                 self.buildEntries()
504
505         def SetList(self, l):
506                 self.type = l[0]
507                 self.list = l[1]
508                 if self.type == TYPE_PODCAST:
509                         self.l.setItemHeight(20)
510                         self.buildEntries()
511                 elif self.type == TYPE_MOVIELIST_CATEGORY:
512                         self.l.setItemHeight(60)
513                         del self.listCompleted
514                         self.listCompleted = []
515                         self.idx = 0
516                         self.buildEntries()
517                 else:
518                         self.setList([])
519                         if self.callback:
520                                 self.callback()
521
522 ###################################################
523
524 class ZDFMediathekCache(Screen):
525         skin = """
526                 <screen position="center,center" size="76,76" flags="wfNoBorder" backgroundColor="#ffffff" >
527                         <eLabel position="2,2" zPosition="1" size="72,72" font="Regular;18" backgroundColor="#252525" />
528                         <widget name="spinner" position="14,14" zPosition="2" size="48,48" alphatest="on" />
529                 </screen>"""
530
531         def __init__(self, session):
532                 self.session = session
533                 Screen.__init__(self, session)
534                 
535                 self["spinner"] = Pixmap()
536                 self.curr = 0
537                 
538                 self.timer = eTimer()
539                 self.timer.callback.append(self.showNextSpinner)
540
541         def start(self):
542                 self.show()
543                 self.timer.start(200, False)
544
545         def stop(self):
546                 self.hide()
547                 self.timer.stop()
548
549         def showNextSpinner(self):
550                 self.curr += 1
551                 if self.curr > 10:
552                         self.curr = 0
553                 png = LoadPixmap(cached=True, path=PNG_PATH + str(self.curr) + ".png")
554                 self["spinner"].instance.setPixmap(png)
555
556 ###################################################
557
558 class ZDFMediathek(Screen, HelpableScreen):
559         def __init__(self, session):
560                 self.session = session
561                 
562                 desktop = getDesktop(0)
563                 size = desktop.size()
564                 width = size.width()
565                 
566                 if width == 720:
567                         self.skin = """<screen position="0,0" size="720,576" flags="wfNoBorder" backgroundColor="#252525" >"""
568                 else:
569                         self.skin = """<screen position="center,center" size="720,576" title="ZDF Mediathek" backgroundColor="#252525" >"""
570                 self.skin += """<ePixmap position="40,30" size="133,40" pixmap="%s" />
571                                 <widget name="navigationTitle" position="250,40" size="430,25" font="Regular;18" backgroundColor="#252525" foregroundColor="#f47d19" noWrap="1" />
572                                 <widget name="leftList" position="40,70" size="200,440" transparent="1" selectionDisabled="1" />
573                                 <widget name="rightList" position="250,70" size="430,480" backgroundColor="#3d3c3c" backgroundColorSelected="#565656" selectionDisabled="1" scrollbarMode="showOnDemand" />
574                                 <ePixmap pixmap="skin_default/buttons/key_menu.png" position="40,520" size="35,25" transparent="1" alphatest="on" />
575                                 <widget name="serverName" position="80,520" size="160,20" font="Regular;18" backgroundColor="#252525" foregroundColor="#f47d19" />
576                                 <widget name="fakeList" position="0,0" size="0,0" />
577                         </screen>""" % (PNG_PATH+"logo.png")
578                 
579                 Screen.__init__(self, session)
580                 
581                 self["navigationTitle"] = Label(" ")
582                 self["leftList"] = LeftMenuList()
583                 self["rightList"] = RightMenuList()
584                 self["fakeList"] = MenuList([])
585                 self["serverName"] = Label("Server")
586                 
587                 HelpableScreen.__init__(self)
588                 
589                 self["actions"] = HelpableActionMap(self, "ZDFMediathekActions",
590                         {
591                                 "back": (self.exit, "Beenden"),
592                                 "ok": (self.ok, "Selektieren"),
593                                 "left": (self.left, "Seite hoch"),
594                                 "right": (self.right, "Seite runter"),
595                                 "up": (self.up, "Hoch"),
596                                 "down": (self.down, "Runter"),
597                                 "previousList": (self.toggleList, "Liste umschalten"),
598                                 "nextList": (self.toggleList, "Liste umschalten"),
599                                 "menu": (self.selectServer, "Selektiere Server"),
600                                 "search": (self.search, "Suche"),
601                                 "previousPage": (self.previousPage, "Vorherige Seite")
602                         }, -2)
603                 
604                 self.cacheDialog = self.session.instantiateDialog(ZDFMediathekCache)
605                 self["rightList"].callback = self.deactivateCacheDialog
606                 self.working = False
607                 self.currentList = LIST_RIGHT
608                 self.linkPreviousPage = ""
609                 
610                 self.transcodeServer = None
611                 self.cacheTimer = eTimer()
612                 self.cacheTimer.callback.append(self.chechCachedFile)
613                 
614                 self.onLayoutFinish.append(self.getPage)
615
616         def getPage(self, page=None):
617                 self.working = True
618                 if not page:
619                         page = "/ZDFmediathek/hauptnavigation/startseite?flash=off"
620                 url = "%s%s"%(MAIN_PAGE, page)
621                 getPage(url).addCallback(self.gotPage).addErrback(self.error)
622
623         def error(self, err=""):
624                 print "[ZDF Mediathek] Error:", err
625                 self.working = False
626                 self.deactivateCacheDialog()
627
628         def gotPage(self, html=""):
629                 rightMenu = getRightMenu(html)
630                 if rightMenu[0] == TYPE_MOVIE:
631                         list = []
632                         for x in rightMenu[1]:
633                                 list.append(("%s %s"%(x[0], x[1].split(".")[-1]), x[1]))
634                         if len(list):
635                                 self.session.openWithCallback(self.play, ChoiceBox, title="Selektiere...", list=list)
636                         else:
637                                 self.working = False
638                 else:
639                         self.cacheDialog.start()
640                         self.currentList = LIST_NONE
641                         links = getTitleLinks(html)
642                         txt = ""
643                         for x in links:
644                                 txt = txt + x[1] + " / "
645                         if len(txt) > 1:
646                                 txt = txt[:-3]
647                                 if (len(links) > 1):
648                                         self.linkPreviousPage = links[-2][0]
649                                 else:
650                                         self.linkPreviousPage = ""
651                         else:
652                                 self.linkPreviousPage = ""
653                         self["navigationTitle"].setText(txt)
654                         self["leftList"].SetList(getLeftMenu(html), True)
655                         self["rightList"].SetList(rightMenu)
656                         self["leftList"].selectionEnabled(0)
657                         self["rightList"].selectionEnabled(1)
658                         self["fakeList"].selectionEnabled(0)
659                         self["leftList"].setActive(False)
660
661         def previousPage(self):
662                 self.getPage(self.linkPreviousPage)
663
664         def search(self):
665                 self.session.openWithCallback(self.searchCallback, VirtualKeyBoard, title="Suche nach:")
666
667         def searchCallback(self, callback):
668                 if callback and (callback != ""):
669                         self.getPage("/ZDFmediathek/suche?sucheText=%s&offset=0&flash=off"%(callback.replace(" ", "+")))
670
671         def play(self, callback):
672                 self.working = False
673                 if callback is not None:
674                         url = callback[1]
675                         if url.endswith(".mov"):
676                                 url = getMovieUrl(url)
677                         if url:
678                                 if PLAY_MP4 and url.endswith(".mp4"):
679                                         ref = eServiceReference(4097, 0, url)
680                                         self.session.open(ChangedMoviePlayer, ref)
681                                 else: # Die Hardware kann das Format nicht direkt abspielen, mit Stream2Dream oder vlc Server probieren...
682                                         if self.transcodeServer is not None:
683                                                 if self.transcodeServer == "LT Stream2Dream":
684                                                         r = streamplayer.play(url)
685                                                         if r == "ok":
686                                                                 sleep(6)
687                                                                 self.currentList = LIST_NONE
688                                                                 self.cacheDialog.start()
689                                                                 self.cacheTimer.start(1000, False)
690                                                 else:
691                                                         self.transcodeServer.play(self.session, url, self["rightList"].getCurrent()[0][1])
692                                         else:
693                                                 self.session.open(MessageBox, "Es wurde kein Server ausgewählt!", MessageBox.TYPE_ERROR)
694                         else:
695                                 self.session.open(MessageBox, "Fehler beim Ermitteln der Film-URL!", MessageBox.TYPE_ERROR)
696
697         def chechCachedFile(self):
698                 try:
699                         f = open ("/tmp/mpstream/progress.txt")
700                         content = f.read()
701                         f.close()
702                         list = content.split("-")
703                         cacheMB = int(list[0])
704                         if cacheMB > 10: # Starte nach 10 MB Bufferung
705                                 self.cacheTimer.stop()
706                                 self.playCachedFile()
707                 except:
708                         pass
709
710         def deactivateCacheDialog(self):
711                 self.cacheDialog.stop()
712                 self.currentList = LIST_RIGHT
713                 self.working = False
714
715         def playCachedFile(self):
716                 self.deactivateCacheDialog()
717                 ref = eServiceReference(1, 0, "/tmp/mpstream/MPStream.ts")
718                 self.session.openWithCallback(self.stopStream2Dream, ChangedMoviePlayer, ref)
719
720         def stopStream2Dream(self, callback=None):
721                 streamplayer.stop()
722                 sleep(4)
723
724         def toggleList(self):
725                 if not self.working:
726                         if self.currentList == LIST_LEFT:
727                                 self.currentList = LIST_RIGHT
728                                 self["leftList"].setActive(False)
729                                 self["fakeList"].selectionEnabled(0)
730                                 self["rightList"].selectionEnabled(1)
731                         elif self.currentList == LIST_RIGHT:
732                                 self.currentList = LIST_LEFT
733                                 self["leftList"].setActive(True)
734                                 self["rightList"].selectionEnabled(0)
735                                 self["fakeList"].selectionEnabled(1)
736
737         def selectServer(self):
738                 list = []
739                 if streamplayer:
740                         list.append(("LT Stream2Dream", "LT Stream2Dream"))
741                 if vlcServerConfig:
742                         serverList = vlcServerConfig.getServerlist()
743                         for x in serverList:
744                                 list.append((x.getName(), x))
745                 if len(list):
746                         self.session.openWithCallback(self.serverChosen, ChoiceBox, title="Waehle den Server...", list=list)
747
748         def serverChosen(self, callback):
749                 if callback:
750                         server = callback[1]
751                         if server == "LT Stream2Dream":
752                                 if not streamplayer.connected:
753                                         self.transcodeServer = "LT Stream2Dream"
754                                         self["serverName"].setText("LT Stream2Dream")
755                                         self.connectToStream2Dream()
756                         else:
757                                 if streamplayer:
758                                         if streamplayer.connected:
759                                                 streamplayer.logout()
760                                 self.transcodeServer = server
761                                 self["serverName"].setText(server.getName())
762
763         def connectToStream2Dream(self):
764                 streamplayer.login()
765                 try:
766                         list = listdir("/tmp/mp")
767                 except:
768                         list = []
769                 if len(list) < 2:
770                         self.session.open(MessageBox, "Die Verbindung zu LT Stream2Dream konnte nicht hergestellt werden!", MessageBox.TYPE_ERROR)
771                         streamplayer.logout()
772                         self.transcodeServer = None
773                         self["serverName"].setText("Server")
774
775         def exit(self):
776                 if not self.working:
777                         if self.currentList == LIST_LEFT:
778                                 self.toggleList()
779                         elif self.currentList == LIST_RIGHT:
780                                 if streamplayer:
781                                         if streamplayer.connected:
782                                                 streamplayer.logout()
783                                 self.session.deleteDialog(self.cacheDialog)
784                                 self.close()
785                         else:
786                                 if streamplayer:
787                                         if streamplayer.connected:
788                                                 streamplayer.stop()
789                                                 sleep(4)
790                                 self.deactivateCacheDialog()
791
792         def ok(self):
793                 if not self.working:
794                         if self.currentList == LIST_LEFT:
795                                 self.getPage(self["leftList"].getCurrentUrl())
796                         elif self.currentList == LIST_RIGHT:
797                                 curr = self["rightList"].getCurrent()
798                                 if curr:
799                                         self.getPage(curr[0][0])
800                         elif streamplayer:
801                                 if streamplayer.connected:
802                                         if streamplayer.caching or streamclient.streaming:
803                                                 self.playCachedFile()
804
805         def left(self):
806                 if not self.working:
807                         if self.currentList == LIST_LEFT:
808                                 self["leftList"].first()
809                         elif self.currentList == LIST_RIGHT:
810                                 self["rightList"].pageUp()
811
812         def right(self):
813                 if not self.working:
814                         if self.currentList == LIST_LEFT:
815                                 self["leftList"].last()
816                         elif self.currentList == LIST_RIGHT:
817                                 self["rightList"].pageDown()
818
819         def up(self):
820                 if not self.working:
821                         if self.currentList == LIST_LEFT:
822                                 self["leftList"].previous()
823                         elif self.currentList == LIST_RIGHT:
824                                 self["rightList"].up()
825
826         def down(self):
827                 if not self.working:
828                         if self.currentList == LIST_LEFT:
829                                 self["leftList"].next()
830                         elif self.currentList == LIST_RIGHT:
831                                 self["rightList"].down()
832
833 ###################################################
834
835 def start(session, **kwargs):
836         session.open(ZDFMediathek)
837
838 def Plugins(**kwargs):
839         return PluginDescriptor(name="ZDF Mediathek", description="Streame von der ZDF Mediathek", where=[PluginDescriptor.WHERE_EXTENSIONSMENU, PluginDescriptor.WHERE_PLUGINMENU], fnc=start)