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